Spire.Doc for JavaScript (39)
Children categories
Get, Replace, Delete Word Bookmark Content and Insert Elements with JavaScript in React
2026-07-17 02:45:00 Written by Nina TangBookmarks are invisible positioning markers in Word documents that act as coordinates, precisely marking a location or a range of text. But the true value of bookmarks goes beyond positioning—by programmatically retrieving content within a bookmark range, replacing placeholder text, removing unwanted content, or inserting text, paragraphs, tables, and images at bookmark positions, developers can implement advanced document processing workflows such as automatic contract template filling, dynamic report data injection, and batch form content cleanup. The combination of "read, write, delete, and insert" operations around bookmark content forms the core of Word automation.
Spire.Doc for JavaScript runs entirely in the browser via WebAssembly, handling bookmark content retrieval, replacement, deletion, and element insertion directly — all managed through a virtual file system (VFS) with no backend server required.
This article covers four core features:
- Get Bookmark Content
- Replace Bookmark Content
- Delete Bookmark Content
- Insert Text, Paragraphs, Tables, and Images at a Bookmark
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Get Bookmark Content
Getting bookmark content is the prerequisite for any bookmark operation. After locating a bookmark with BookmarksNavigator, the GetBookmarkContent method returns the content within the bookmark range as a TextBodyPart object, which developers can iterate through its BodyItems collection to retrieve elements.
function App() {
const bookmarkContent = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the WASM module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the Word file into VFS
const inputFileName = 'ContractTemplate_en.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Load the Word document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Create a BookmarksNavigator and move to the bookmark
let navigator = new docModule.BookmarksNavigator(doc);
navigator.MoveToBookmark("myBookmark");
let textBodyPart = navigator.GetBookmarkContent();
// Iterate through elements in the bookmark content and extract text
let text = "";
for (let i = 0; i < textBodyPart.BodyItems.Count; i++) {
let item = textBodyPart.BodyItems.get_Item(i);
if (item instanceof docModule.Paragraph) {
for (let j = 0; j < item.ChildObjects.Count; j++) {
let childObject = item.ChildObjects.get_Item(j);
if (childObject instanceof docModule.TextRange) {
text += childObject.Text;
}
}
}
}
// Save as a .txt file
const outputFileName = "GetBookmarkContent.txt";
// Write the text file to VFS and trigger download
window.dotnetRuntime.Module.FS.writeFile(outputFileName, text);
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
// Release resources
doc.Dispose();
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Get Bookmark Content from Word Document</h1>
<button onClick={bookmarkContent}>
Generate
</button>
</div>
);
}
export default App;
Executing the code above extracts the text content from the bookmark "myBookmark" and saves it as a separate .txt file:

Replace Bookmark Content
Replacing bookmark content is the most common operation in document template filling. After locating a bookmark with BookmarksNavigator, the ReplaceBookmarkContent method supports replacement with both plain text and complex elements like tables, making it ideal for placeholder replacement in contract generation, report filling, and similar scenarios.
function App() {
const replaceBookmarkContent = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the WASM module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load fonts and Word file into VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'BookmarkSample.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Load the Word document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Create a BookmarksNavigator and move to the bookmark
let navigator = new docModule.BookmarksNavigator(doc);
navigator.MoveToBookmark("Bookmark1");
// Replace the content of "书签1" — with text
navigator.ReplaceBookmarkContent({ text: "This is the text that will replace the bookmark.", saveFormatting: true });
// Continue to replace "书签2" — with a table
navigator.MoveToBookmark("Bookmark2");
// Create a table
let table = new docModule.Table(doc, true);
table.ResetCells(4, 5);
// Create data and fill it into the table
let dt = [
["City", "Province", "Population", "Area (km²)", "Abbrev."],
["Beijing", "Beijing", "21.89M", "16410", "BJ"],
["Shanghai", "Shanghai", "24.75M", "6340", "SH"],
["Guangzhou", "Guangdong", "18.67M", "7434", "GZ"]];
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 5; j++) {
table.Rows.get_Item(i).Cells.get_Item(j).AddParagraph().AppendText(dt[i][j]);
}
}
// Create a TextBodyPart instance and add the table to it
let part = new docModule.TextBodyPart({ doc: doc });
part.BodyItems.Add(table);
// Replace the current bookmark content with the TextBodyPart
navigator.ReplaceBookmarkContent({ bodyPart: part });
// Save as a new .docx file
const outputFileName = "ReplaceBookmark.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Read the generated file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
// Release resources
doc.Dispose();
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Replace Bookmark Content in Word</h1>
<button onClick={replaceBookmarkContent}>
Generate
</button>
</div>
);
}
export default App;
This method supports replacing bookmark content with plain text or complex elements like tables. The bookmark marker itself is preserved after replacement, making it easy to locate again later. The figure below shows the result:

Delete Bookmark Content
Deleting bookmark content and removing a bookmark marker are two different operations. After locating a bookmark with BookmarksNavigator, calling DeleteBookmarkContent removes the text content within the bookmark range while preserving the bookmark marker itself for later refilling. If you only need to clear the content while keeping the positioning marker, this method is the preferred choice.
function App() {
const deleteBookmarkContent = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the WASM module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the Word file into VFS
const inputFileName = 'ContractTemplate_en.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Load the Word document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Create a BookmarksNavigator and move to the bookmark
let navigator = new docModule.BookmarksNavigator(doc);
navigator.MoveToBookmark("myBookmark");
// Delete bookmark content, keep the bookmark marker
navigator.DeleteBookmarkContent(true);
// Save as a new .docx file
const outputFileName = "RemoveBookmark.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Read the generated file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
// Release resources
doc.Dispose();
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Delete Bookmark Content in Word</h1>
<button onClick={deleteBookmarkContent}>
Generate
</button>
</div>
);
}
export default App;
DeleteBookmarkContentremoves only the text content within the bookmark range — the bookmark marker itself remains.Bookmarks.Remove, on the other hand, removes the bookmark marker, leaving the text within the range unaffected.
After execution, the text within the bookmark "myBookmark" is removed, but the bookmark marker stays in the document:

Insert Text, Paragraphs, Tables, and Images at a Bookmark
Spire.Doc supports flexibly inserting various types of document elements at bookmark positions. It provides InsertText, InsertParagraph, and InsertTable methods for inserting text, paragraphs, and tables. Elements can also be inserted based on the index of the bookmark start node within the paragraph's ChildObjects collection.
function App() {
const insertElementsAtBookmark = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the WASM module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load fonts and Word file into VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'BookmarkSample1.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Create a Document object and load the file
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Move to the bookmark position
let navigator = new docModule.BookmarksNavigator(doc);
navigator.MoveToBookmark("Bookmark1");
// 1. Insert text
navigator.InsertText("This is the inserted text content.", true);
// 2. Insert paragraph
let newParagraph = new docModule.Paragraph(doc);
newParagraph.AppendText("This is the inserted paragraph content.")
navigator.MoveToBookmark("Bookmark2");
navigator.InsertParagraph(newParagraph);
// 3. Insert table — 2 rows, 3 columns
let table = new docModule.Table(doc, true);
table.ResetCells(2, 3);
table.Rows.get_Item(0).Cells.get_Item(0).AddParagraph().AppendText("Name");
table.Rows.get_Item(0).Cells.get_Item(1).AddParagraph().AppendText("Quantity");
table.Rows.get_Item(0).Cells.get_Item(2).AddParagraph().AppendText("Note");
table.Rows.get_Item(1).Cells.get_Item(0).AddParagraph().AppendText("Product A");
table.Rows.get_Item(1).Cells.get_Item(1).AddParagraph().AppendText("100");
table.Rows.get_Item(1).Cells.get_Item(2).AddParagraph().AppendText("In Stock");
navigator.MoveToBookmark("Bookmark3");
navigator.InsertTable(table);
// 4. Insert image
const imageFileName = 'pic.png';
await window.spire.FetchFileToVFS(imageFileName, '', `${process.env.PUBLIC_URL}/data/`);
let picture = new docModule.DocPicture(doc);
picture.LoadImage(imageFileName);
picture.Width = 100;
picture.Height = 200;
navigator.MoveToBookmark("Bookmark4");
// Get the bookmark start node
let start = navigator.CurrentBookmark.BookmarkStart;
// Get the paragraph containing the bookmark
let bookmarkPara = start.OwnerParagraph;
// Get the index of the bookmark start node in the paragraph
let startIndex = bookmarkPara.ChildObjects.IndexOf(start);
// Insert the image after the bookmark start node
bookmarkPara.ChildObjects.Insert(startIndex + 1, picture);
// Save as a .docx file
const outputFileName = "InsertToBookmark.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Read the generated file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
// Release Document resources
doc.Dispose();
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Insert Elements at Bookmark Position</h1>
<button onClick={insertElementsAtBookmark}>
Generate
</button>
</div>
);
}
export default App;
The figure below shows the generated document with text, paragraph, table, and image inserted at bookmark positions:

FAQ
Formatting (font, size, color) is lost after replacing bookmark content — how to keep it?
ReplaceBookmarkContent replaces with plain text by default, discarding the original formatting. To preserve the bookmark's existing formatting, pass saveFormatting: true:
navigator.ReplaceBookmarkContent({ text: "New content", saveFormatting: true });
The replacement text will then inherit the original font, size, color, and other formatting from the bookmark.
How to batch process multiple bookmarks in a document?
Iterate through the doc.Bookmarks collection, locating and operating on each bookmark one by one:
for (let i = 0; i < doc.Bookmarks.Count; i++) {
let bookmark = doc.Bookmarks.get_Item(i);
navigator.MoveToBookmark(bookmark.Name);
// Perform replace, delete, or insert operations
}
What's the difference between DeleteBookmarkContent and removing a bookmark marker?
DeleteBookmarkContent: Clears only the content within the bookmark range. The bookmark marker stays in the document, so you can still locate it by name and fill in new content later.Bookmarks.Remove: Removes the bookmark marker itself. The content within the bookmark range is unaffected, but the bookmark name disappears and can no longer be located.
Choose the appropriate operation based on your needs: use DeleteBookmarkContent if you need to keep the "placeholder" capability, or remove the marker if the bookmark is no longer needed.
When inserting multiple elements at the same bookmark, why does only the last one take effect?
Methods like InsertText, InsertParagraph, and InsertTable insert based on the bookmark's current position. When inserting multiple times at the same bookmark, subsequent insertions may overwrite or shift previously inserted content. It is recommended to use separate bookmarks for each insertion, or re-locate the bookmark after each insert before proceeding with the next operation.
Get a Free License
Spire.Doc for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Bookmarks are invisible positioning markers in Word documents that act as coordinates, precisely marking a location or a range of text. Whether it's a fill-in area in a contract template, a key section to jump to in a long document, or a data insertion point when generating reports in batch, bookmarks are the critical anchor behind these operations. Developers can use bookmarks for dynamic content filling, navigation, content extraction, and other advanced features, making bookmark management one of the most commonly used capabilities in Word automation.
Spire.Doc for JavaScript runs entirely in the browser via WebAssembly, handling bookmark creation, navigation, and deletion directly — all managed through a virtual file system (VFS) with no backend server required.
This article covers three core features:
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Add a Bookmark to a Paragraph
To add a bookmark in an existing document, use AppendBookmarkStart and AppendBookmarkEnd to mark the bookmark region on a paragraph. You can add bookmark markers to existing paragraphs or append a new paragraph with a bookmark. Spire.Doc also supports nested bookmarks for building hierarchical structures.
function App() {
const createBookmarkInWord = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the Word file into VFS
const inputFileName = 'ChinaTravelGuide.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Load the document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Get the first section and add bookmarks
let section = doc.Sections.get_Item(0);
AddBookmark(section);
// Save as a .docx file
const outputFileName = "AddBookmark.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Read the file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
// Release resources
doc.Dispose();
};
function AddBookmark(section) {
// Bookmark 1: add bookmark markers around existing paragraphs
let paraStart = section.Paragraphs.get_Item(1);
let paraEnd = section.Paragraphs.get_Item(3);
paraStart.AppendBookmarkStart("Bookmark1");
paraEnd.AppendBookmarkEnd("Bookmark1");
// Bookmark 2: add a new paragraph with a bookmark
let paragraph = section.AddParagraph();
paragraph.AppendBookmarkStart("Bookmark2");
paragraph.AppendText("This is a new paragraph");
paragraph.AppendBookmarkEnd("Bookmark2");
}
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Add Bookmark in Word</h1>
<button onClick={createBookmarkInWord}>
Generate
</button>
</div>
);
}
export default App;
Bookmarks added to the generated Word document

Add a Bookmark to Selected Text
To add a bookmark to specific text within an existing paragraph, first locate the text with FindAllString, create bookmark objects using the BookmarkStart and BookmarkEnd constructors, then insert the start marker before and the end marker after the matched TextRange via ChildObjects.Insert.
function App() {
const addBookmarkForMatchedText = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the WASM module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the Word file into VFS
const inputFileName = 'ChinaTravelGuide.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Load the Word document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Find all occurrences of "Street" in the document
let textSelections = doc.FindAllString('Street', false, true);
// Iterate over each match and insert bookmark start/end markers
for (let i = 0; i < textSelections.length; i++) {
// Create bookmark start and end objects (named "Bookmark_0", "Bookmark_1", ...)
let start = new docModule.BookmarkStart(doc, "Bookmark_" + i);
let end = new docModule.BookmarkEnd(doc, "Bookmark_" + i);
let selection = textSelections[i];
// Get the TextRange of the matched text
let textRange = selection.GetAsOneRange();
// Get the paragraph containing the matched text
let para = textRange.OwnerParagraph;
// Get the index of the TextRange within the paragraph's child objects
let index = para.ChildObjects.IndexOf(textRange);
// Insert the bookmark start before the TextRange and the bookmark end after it
para.ChildObjects.Insert(index, start);
para.ChildObjects.Insert(index + 2, end);
}
// Save as a new .docx file
const outputFileName = "AddBookmark.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Read the generated file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
// Release document resources
doc.Dispose();
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Add Bookmarks for Specific Text in Word Documents</h1>
<button onClick={addBookmarkForMatchedText}>
Generate
</button>
</div>
);
}
export default App;
This approach is ideal for scenarios where you need to add positioning markers on top of an existing document, such as marking fill-in areas in a completed contract. The figure below shows the result after execution:

Remove a Bookmark
Removing a bookmark only removes the bookmark markers themselves — the text content within the bookmark range is preserved. Retrieve the bookmark object from the document.Bookmarks collection, then call the Remove method to delete it.
function App() {
const deleteBookmark = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the WASM module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the Word file into VFS
const inputFileName = 'AddBookmark.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Load the Word document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Get the bookmark by name
let bookmark = doc.Bookmarks.get_Item("Bookmark_1");
// // Get the bookmark by index
// let bookmark = doc.Bookmarks.get_Item(0);
// Remove the bookmark (keep its content)
doc.Bookmarks.Remove(bookmark);
// Save as a new .docx file
const outputFileName = "DeleteBookmark.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Read the generated file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
// Release document resources
doc.Dispose();
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Delete Bookmark in Word Document</h1>
<button onClick={deleteBookmark}>
Generate
</button>
</div>
);
}
export default App;
After the bookmark is removed, its markers disappear from the document, but the text within the bookmark range is preserved.

FAQ
Duplicate bookmark name error
Cause: Bookmark names must be unique within a Word document. Adding a bookmark with a duplicate name causes an error.
Solution: Check whether the name already exists before adding the bookmark:
if (document.Bookmarks.FindByName("MyBookmark") === null) {
paragraph.AppendBookmarkStart("MyBookmark");
paragraph.AppendText("Content");
paragraph.AppendBookmarkEnd("MyBookmark");
}
What is the difference between removing a bookmark and deleting its content?
Cause: Spire.Doc's Bookmarks.Remove only removes the bookmark markers (start and end), leaving the text content between them untouched.
Solution: Choose the appropriate operation based on your needs:
// Remove only the bookmark markers, keep the text
document.Bookmarks.Remove(bookmark);
// Remove the bookmark and its content (via BookmarksNavigator)
let navigator = new docModule.BookmarksNavigator(doc);
navigator.MoveToBookmark("MyBookmark");
navigator.DeleteBookmarkContent();
Do AppendBookmarkStart and AppendBookmarkEnd have to be on the same paragraph?
Cause: The start and end markers can be on different paragraphs — the "Bookmark1" example in the code above demonstrates cross-paragraph usage. The key constraint is that the document object structure within the bookmark range must remain intact. Bookmarks cannot span across table cells, since cells are independent containers and doing so may cause the bookmark to be unrecognized.
Solution: If the bookmark range crosses a table cell boundary, adjust the start or end position so that the bookmark closes within the same cell.
Get a Free License
Spire.Doc for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Replace Placeholders in Word Documents with HTML or Paragraphs from Another Document Using JavaScript in React
2026-07-14 03:05:11 Written by Amy ZhaoReplacing placeholders in documents with HTML content or paragraphs from another document is a highly practical need in document automation — for example, inserting rich HTML content authored in a WYSIWYG editor into placeholder positions in a Word template, or extracting specific paragraphs from a standard clause library and replacing corresponding placeholders in a contract template. Spire.Doc for JavaScript handles such replacement operations entirely in the browser via WebAssembly, using a virtual file system (VFS) to manage fonts and document files — no backend server required.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Replace Placeholder with HTML
Replacing a placeholder with HTML involves three stages: first, load the font files, the HTML file, and the target Word document into the WASM virtual file system via FetchFileToVFS; then, create a temporary Section, render the HTML string into document objects using AppendHTML, collect them into a replacement list, find all [#placeholder] occurrences with FindAllString, sort the matched positions, and insert the replacement content one by one via ChildObjects.Insert while removing the original text; finally, remove the temporary Section, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
import React, { useState } from 'react';
function App() {
// Define the placeholder replacement logic
function ReplacedWithHTML(location, replacement) {
let textRange = location.Text;
let index = location.Index;
let paragraph = location.Owner;
let sectionBody = paragraph.OwnerTextBody;
let paragraphIndex = sectionBody.ChildObjects.IndexOf(paragraph);
let replacementIndex = -1;
if (index === 0) {
paragraph.ChildObjects.RemoveAt(0);
replacementIndex = sectionBody.ChildObjects.IndexOf(paragraph);
} else if (index === paragraph.ChildObjects.Count - 1) {
paragraph.ChildObjects.RemoveAt(index);
replacementIndex = paragraphIndex + 1;
} else {
let paragraph1 = paragraph.Clone();
while (paragraph.ChildObjects.Count > index) {
paragraph.ChildObjects.RemoveAt(index);
}
let i = 0;
let count = index + 1;
while (i < count) {
paragraph1.ChildObjects.RemoveAt(0);
i += 1;
}
sectionBody.ChildObjects.Insert(paragraphIndex + 1, paragraph1);
replacementIndex = paragraphIndex + 1;
}
for (let i = 0; i <= replacement.length - 1; i++) {
sectionBody.ChildObjects.Insert(replacementIndex + i, replacement[i].Clone());
}
}
function TextRangeLocation(TextRange) {
this.Text = TextRange;
this.Owner = this.Text.OwnerParagraph;
this.Index = this.Owner.ChildObjects.IndexOf(this.Text);
this.CompareTo = function (other) {
return -(this.Index - other.Index);
};
}
const ReplaceWithHTML = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the font file into the virtual file system (VFS)
await window.spire.FetchFileToVFS('arial.ttf', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// Load the HTML file and Word document into VFS
let HTMLName = 'InputHtml.txt';
await window.spire.FetchFileToVFS(HTMLName, '', `${process.env.PUBLIC_URL}/data/`);
const HTML = window.dotnetRuntime.Module.FS.readFile(HTMLName);
let inputFileName = 'ReplaceWithHtml.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Load the document
let doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Create a temporary Section and render the HTML
let replacement = [];
let tempSection = doc.AddSection();
let par = tempSection.AddParagraph();
const decoder = new TextDecoder('utf-8');
const HTMLString = decoder.decode(HTML);
par.AppendHTML(HTMLString);
// Collect the rendered document objects
for (let i = 0; i < tempSection.Body.ChildObjects.Count; i++) {
let docObj = tempSection.Body.ChildObjects.get_Item(i);
replacement.push(docObj);
}
// Find all placeholders and sort
let selections = doc.FindAllString('[#placeholder]', false, true);
let locations = [];
for (let selection of selections) {
locations.push(new TextRangeLocation(selection.GetAsOneRange()));
}
locations.sort();
// Replace one by one
for (let location of locations) {
ReplacedWithHTML(location, replacement);
}
// Remove the temporary Section
doc.Sections.Remove(tempSection);
// Define the output file name and save
const outputFileName = 'ReplaceWithHtml_output.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Replace Placeholder with HTML in a Word Document</h1>
<button onClick={ReplaceWithHTML}>
Generate
</button>
</div>
);
}
export default App;
The [#placeholder] placeholders in the document are replaced with rich text content rendered from HTML
![The [#placeholder] placeholders in the document are replaced with rich text content rendered from HTML](https://cdn.e-iceblue.com/images/art_images/replace-placeholder-with-html-or-paragraph-en-1.webp)
Replace Placeholder with Paragraphs from Another Document
Replacing a placeholder with paragraphs from another document involves three stages: first, load the font files and two Word documents into the WASM virtual file system via FetchFileToVFS; then, load the main document and the source document separately, use FindAllPattern with a regular expression to find placeholders (such as [MY_DOCUMENT]), iterate through all Sections and Paragraphs of the source document, insert each paragraph into the corresponding position in the main document using ChildObjects.Insert, and finally remove the original placeholder text; lastly, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
import React, { useState } from 'react';
function App() {
const ReplaceContentWithDoc = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the two Word documents into VFS
let inputFileName1 = 'ReplaceContentWithDoc.docx';
await window.spire.FetchFileToVFS(inputFileName1, '', `${process.env.PUBLIC_URL}/data/`);
let inputFileName2 = 'Insert.docx';
await window.spire.FetchFileToVFS(inputFileName2, '', `${process.env.PUBLIC_URL}/data/`);
// Load the main document
let document1 = new docModule.Document();
document1.LoadFromFile(inputFileName1);
// Load the source document (contains paragraphs to insert)
let document2 = new docModule.Document();
document2.LoadFromFile(inputFileName2);
// Get the first Section of the main document
let section1 = document1.Sections.get_Item(0);
// Create a regex to find the placeholder
let regex = new docModule.Regex('\\[MY_DOCUMENT\\]', docModule.RegexOptions.None);
// Find all matching placeholders
let textSections = document1.FindAllPattern({ pattern: regex });
// Iterate through each match
for (let i = 0; i < textSections.length; i++) {
let selection = textSections[i];
let para = selection.GetAsOneRange().OwnerParagraph;
let textRange = selection.GetAsOneRange();
let index = section1.Body.ChildObjects.IndexOf(para);
// Insert all paragraphs from the source document at the placeholder position
for (let i = 0; i < document2.Sections.Count; i++) {
let section2 = document2.Sections.get_Item(i);
for (let j = 0; j < section2.Paragraphs.Count; j++) {
let paragraph = section2.Paragraphs.get_Item(j);
section1.Body.ChildObjects.Insert(index++, paragraph.Clone());
}
}
// Remove the original placeholder text
para.ChildObjects.Remove(textRange);
}
// Define the output file name and save
const outputFileName = 'ReplaceContentWithDoc_output.docx';
document1.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
document1.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Replace Placeholder with Paragraphs from Another Document</h1>
<button onClick={ReplaceContentWithDoc}>
Generate
</button>
</div>
);
}
export default App;
The [MY_DOCUMENT] placeholder in the main document is replaced with all paragraphs from the source document
![The [MY_DOCUMENT] placeholder in the main document is replaced with all paragraphs from the source document](https://cdn.e-iceblue.com/images/art_images/replace-placeholder-with-html-or-paragraph-en-2.webp)
FAQ
HTML content formatting is not displayed correctly
Cause: The AppendHTML method supports a limited range of HTML tags, only recognizing basic block-level and inline tags (such as <p>, <b>, <i>, <table>, etc.). Complex CSS styles, JavaScript code, or HTML5-specific tags are ignored.
Solution: Ensure the input HTML uses only basic tags and defines formatting through inline styles (such as style="color:red") rather than CSS class names:
<p style="font-size:14pt; color:#2E75B6;">This is blue heading text</p>
<ul><li>Item one</li><li>Item two</li></ul>
Inserted paragraph order does not match expectations
Cause: When replacing multiple placeholders, the matched positions are not sorted before processing. Replacing sequentially from beginning to end causes the indices of subsequent positions to shift, leading to paragraphs being inserted at incorrect locations.
Solution: Sort all matched positions in descending order by index (replacing from the end of the document backward), or track the original index offset for each position:
let locations = [];
for (let selection of selections) {
locations.push(new TextRangeLocation(selection.GetAsOneRange()));
}
locations.sort(); // Descending order, replace from back to front
Get a Free License
Spire.Doc for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Replace Text with Image or Table in Word with JavaScript in React
2026-07-14 03:03:05 Written by Amy ZhaoReplacing specific placeholder text with images or tables is a common requirement in real-world development — such as replacing a "(Seal)" marker at the end of a contract with a company stamp image, or swapping a data summary placeholder with a statistics table. Spire.Doc for JavaScript runs entirely in the browser via WebAssembly, using a virtual file system (VFS) to manage fonts, images, and document files — no backend server required.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Replace Text with Image
Replacing text with an image involves three steps: first, load the font files, the target image, and the Word document into the WASM virtual file system via FetchFileToVFS; then call FindAllString to locate all matching text, iterate through each match, load the image with DocPicture, insert it using ChildObjects.Insert, and remove the original text via ChildObjects.Remove; finally, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
import React, { useState } from 'react';
function App() {
const ReplaceWithImage = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the image and Word document into VFS
let pngName = 'E-iceblue.png';
await window.spire.FetchFileToVFS(pngName, '', `${process.env.PUBLIC_URL}/data/`);
let inputFileName = 'Template.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Load the document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Find all matching text
let selections = doc.FindAllString('E-iceblue', true, true);
// Iterate through each match and replace text with the image
for (let i = 0; i < selections.length; i++) {
// Create a DocPicture object and load the image
let pic = new docModule.DocPicture(doc);
pic.LoadImage(pngName);
let selection = selections[i];
// Get the current text range
let range = selection.GetAsOneRange();
// Get the index of the TextRange in its owner paragraph's ChildObjects
let index = range.OwnerParagraph.ChildObjects.IndexOf(range);
// Insert the image at the TextRange position
range.OwnerParagraph.ChildObjects.Insert(index, pic);
// Remove the original TextRange
range.OwnerParagraph.ChildObjects.Remove(range);
}
// Define the output file name and save
const outputFileName = 'ReplaceWithImage_output.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Replace text with image in Word document</h1>
<button onClick={ReplaceWithImage}>
Generate
</button>
</div>
);
}
export default App;
Target text in the document is found and replaced with the specified image

Replace Text with Table
Replacing text with a table involves three steps: first, load the font files and the target Word document into the WASM virtual file system via FetchFileToVFS; then call FindString to locate the target text, retrieve the text range with GetAsOneRange, get the paragraph index via OwnerTextBody.ChildObjects, create a new table, remove the original paragraph with ChildObjects.Remove, and insert the table at the same position with ChildObjects.Insert; finally, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
import React, { useState } from 'react';
function App() {
const ReplaceTextWithTable = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the font file into VFS
await window.spire.FetchFileToVFS('ARIALUNI.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// Load the Word document into VFS
let inputFileName = 'Template_Docx_1.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Load the document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Get the first section
let section = doc.Sections.get_Item(0);
// Find the target text
let selection = doc.FindString('Christmas Day, December 25', true, true);
// Get the text range and its owner paragraph
let range = selection.GetAsOneRange();
let paragraph = range.OwnerParagraph;
// Get the text body and calculate the paragraph index
let body = paragraph.OwnerTextBody;
let index = body.ChildObjects.IndexOf(paragraph);
// Create a 3x3 table
let table = section.AddTable(true);
table.ResetCells(3, 3);
// Remove the original paragraph and insert the table at the same position
body.ChildObjects.Remove(paragraph);
body.ChildObjects.Insert(index, table);
// Define the output file name and save
const outputFileName = 'ReplaceTextWithTable_output.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Replace text with table in Word document</h1>
<button onClick={ReplaceTextWithTable}>
Generate
</button>
</div>
);
}
export default App;
The target paragraph is removed and a table is inserted at the same position

FAQ
Image does not appear in the document after insertion
Cause: The image file was not loaded into the WASM virtual file system, or the FetchFileToVFS path is incorrect, causing DocPicture.LoadImage to fail when reading the image data from VFS.
Solution: Ensure the image file is properly loaded into VFS via FetchFileToVFS before calling LoadImage, and verify the file name and path match:
await window.spire.FetchFileToVFS(
'E-iceblue.png', '', `${process.env.PUBLIC_URL}/data/`
);
Table is inserted at the wrong position
Cause: The paragraph index obtained via OwnerTextBody.ChildObjects.IndexOf is inaccurate, or the selected text spans multiple paragraphs, causing an index offset that places the table in the wrong location.
Solution: Verify that the text searched by FindString resides within a single paragraph, then use GetAsOneRange to obtain the correct OwnerParagraph before retrieving its index in OwnerTextBody.ChildObjects:
let range = selection.GetAsOneRange();
let paragraph = range.OwnerParagraph;
let body = paragraph.OwnerTextBody;
let index = body.ChildObjects.IndexOf(paragraph);
Get a Free License
Spire.Doc for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Find and Replace Text in Word Documents with JavaScript in React
2026-07-14 03:01:11 Written by Amy ZhaoText replacement is one of the most common operations in Word document processing — whether it's batch-replacing placeholders in contracts, standardizing terminology, or normalizing text of a specific pattern, the find-and-replace feature handles it efficiently. Spire.Doc for JavaScript processes Word documents directly in the browser via WebAssembly, using a virtual file system (VFS) to manage fonts and file resources — no backend server required.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Replace Specific Text
Replacing specific text is the most basic text operation — it replaces a word or phrase in a document with another string, with options for case sensitivity and whole-word matching. The core process involves three steps: first, load font files and the target Word document into the WASM virtual file system via FetchFileToVFS; then instantiate a Document, load the file, and call the Replace method to match a specified string and replace it with new text, controlling the matching rules through caseSensitive and wholeWord parameters; finally, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
import React, { useState } from 'react';
function App() {
const ReplaceWithText = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample file into VFS
let inputFileName = 'Sample.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Create a new document
const doc = new docModule.Document();
// Load the document from the virtual file system
doc.LoadFromFile(inputFileName);
// Replace text: "word" → "ReplacedText", case-insensitive, whole-word match
doc.Replace({ matchString: 'word', newValue: 'ReplacedText', caseSensitive: false, wholeWord: true });
// Define the output file name and save
const outputFileName = 'ReplaceWithText_output.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Replace text in a Word document.</h1>
<button onClick={ReplaceWithText}>
Generate
</button>
</div>
);
};
export default App;
Target strings in the document are uniformly replaced with the new content after using the Replace method

Replace Text Using Regex
When you need to match text with variable formatting, regex is the most powerful tool — for example, replacing all hashtag labels starting with # with a fixed string. The core process involves three steps: first, load font files and the target Word document into the WASM virtual file system via FetchFileToVFS; then create a Regex object to define the matching pattern, and call the Replace method to uniformly replace all matched text with the specified content; finally, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
import React, { useState } from 'react';
function App() {
const ReplaceWithText = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample file into VFS
let inputFileName = 'Sample.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Create a new document
const doc = new docModule.Document();
// Load the document from the virtual file system
doc.LoadFromFile(inputFileName);
// Create a regex pattern to match whole words
let regex = new docModule.Regex('\\bword\\b', docModule.RegexOptions.None);
// Replace text using the regex
doc.Replace(regex, 'Spire.Doc');
// Define the output file name and save
const outputFileName = 'ReplaceTextByRegex_output.docx';
doc.SaveToFile({fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Replace text in a Word document.</h1>
<button onClick={ReplaceWithText}>
Generate
</button>
</div>
);
};
export default App;
All strings matching the pattern are uniformly replaced after regex-based text replacement

FAQ
Text replacement does not take effect (text is not replaced)
Cause: The caseSensitive or wholeWord parameters are set incorrectly, causing the match to fail — the actual text does not meet the matching criteria.
Solution: Check whether the case matches, or set caseSensitive to false to ignore case, and wholeWord to false to match partial words:
doc.Replace({ matchString: 'word', newValue: 'ReplacedText', caseSensitive: false, wholeWord: false });
Regex pattern does not match the target content
Cause: Special characters (such as #, \) in the regex pattern are not properly escaped, causing the match to fail.
Solution: Ensure that special characters in the regex pattern are correctly escaped. For example, when matching #tag-style text:
let regex = new wasmModule.Regex('#\\S+', wasmModule.RegexOptions.None);
Get a Free License
Spire.Doc for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Replace Text with Field or Another Document in Word with JavaScript in React
2026-07-14 02:58:48 Written by Amy ZhaoReplacing specific text with field codes or another document's content is a highly practical need in document automation — such as replacing a "current date" placeholder with a DATE field that automatically updates to the system date each time the document is opened, or swapping a "terms" placeholder in a contract template with detailed clause content from another Word document for modular document assembly. Spire.Doc for JavaScript runs entirely in the browser via WebAssembly, using a virtual file system (VFS) to manage fonts and document files — no backend server required.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Replace Text with a Field
Replacing text with a field involves three steps: first, load the font files and the target Word document into the WASM virtual file system via FetchFileToVFS; then call FindString to locate the target text, retrieve its paragraph and position index, create a Field object with the desired field type (such as FieldDate), sequentially insert Field, FieldMark(FieldSeparator), and FieldMark(FieldEnd) into the paragraph to construct a complete field structure, and finally remove the original text; finally, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
import React, { useState } from 'react';
function App() {
const ReplaceTextWithField = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the Word document into VFS
let inputFileName = 'ReplaceTextWithField.docx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Load the document
const doc = new docModule.Document();
doc.LoadFromFile(inputFileName);
// Find the target text
let selection = doc.FindString({
stringValue: 'summary',
caseSensitive: false,
wholeWord: true,
});
// Get the text range and its owner paragraph
let textRange = selection.GetAsOneRange();
let ownParagraph = textRange.OwnerParagraph;
let rangeIndex = ownParagraph.ChildObjects.IndexOf(textRange);
// Create a DATE field
let eqField = new docModule.Field(doc);
eqField.Type = docModule.FieldType.FieldDate;
eqField.Code = 'DATE \\@ "yyyyMMdd "';
// Insert Field, FieldSeparator, and FieldEnd in sequence
ownParagraph.ChildObjects.Insert(rangeIndex, eqField);
let mark = new docModule.FieldMark(doc, docModule.FieldMarkType.FieldSeparator);
ownParagraph.ChildObjects.Insert(rangeIndex + 1, mark);
let end = new docModule.FieldMark(doc, docModule.FieldMarkType.FieldEnd);
ownParagraph.ChildObjects.Insert(rangeIndex + 2, end);
// Remove the original text
ownParagraph.ChildObjects.Remove(textRange);
// Define the output file name and save
const outputFileName = 'ReplaceTextWithField_output.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Replace text with field in Word document</h1>
<button onClick={ReplaceTextWithField}>
Generate
</button>
</div>
);
}
export default App;
The target text is replaced with a DATE field that automatically displays the current system date when the document is opened

Replace Text with Another Document
Replacing text with another document involves three steps: first, load the font files and two Word documents (the main document and the replacement content document) into the WASM virtual file system via FetchFileToVFS; then instantiate two Document objects to load both documents, call the Replace method on the main document with the matchDoc parameter pointing to the replacement document object, substituting the matching text with the full content of that document; finally, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
import React, { useState } from 'react';
function App() {
const ReplaceWithDocument = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the two Word documents into VFS
let inputFileName1 = 'Text2.docx';
await window.spire.FetchFileToVFS(inputFileName1, '', `${process.env.PUBLIC_URL}/data/`);
let inputFileName2 = 'Text1.docx';
await window.spire.FetchFileToVFS(inputFileName2, '', `${process.env.PUBLIC_URL}/data/`);
// Load the main document
let doc = new docModule.Document();
doc.LoadFromFile(inputFileName1);
// Load the replacement document
let replaceDoc = new docModule.Document();
replaceDoc.LoadFromFile(inputFileName2);
// Replace the specified text with the content of another document
doc.Replace({
matchString: 'Document1',
matchDoc: replaceDoc,
caseSensitive: false,
wholeWord: true,
});
// Define the output file name and save
const outputFileName = 'ReplaceWithDocument_output.docx';
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Replace text with another document in Word</h1>
<button onClick={ReplaceWithDocument}>
Generate
</button>
</div>
);
}
export default App;
The placeholder text in the main document is replaced with the full content of another document

FAQ
Field value does not appear in the document after insertion
Cause: The Field, FieldMark(FieldSeparator), and FieldMark(FieldEnd) are not inserted in the correct order, breaking the integrity of the field structure and preventing Word from properly recognizing and evaluating the field value.
Solution: Ensure that Field, FieldSeparator, and FieldEnd are inserted sequentially with consecutive indices:
ownParagraph.ChildObjects.Insert(rangeIndex, eqField);
ownParagraph.ChildObjects.Insert(rangeIndex + 1, mark);
ownParagraph.ChildObjects.Insert(rangeIndex + 2, end);
Replacement with another document does not work
Cause: The document object passed via the matchDoc parameter in the Replace method was not properly loaded into VFS, or the file path/name does not match what was used in FetchFileToVFS, causing LoadFromFile to fail to locate the target file.
Solution: Ensure both documents are loaded into VFS via FetchFileToVFS, and create separate Document objects that successfully load before calling Replace:
let doc = new docModule.Document();
doc.LoadFromFile('Text2.docx');
let replaceDoc = new docModule.Document();
replaceDoc.LoadFromFile('Text1.docx');
doc.Replace({
matchString: 'Document1',
matchDoc: replaceDoc,
caseSensitive: false,
wholeWord: true,
});
Get a Free License
Spire.Doc for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Insert Images and Tables into a Word Textbox with JavaScript in React
2026-07-08 06:32:11 Written by Amy ZhaoIn practical document layout, a textbox is an ideal container for standalone content — it can be positioned freely without being constrained by the page flow, making it perfect for sidebars, pull quotes, product diagrams, and more. Inserting images or tables into a textbox is a common requirement for achieving rich layouts. Spire.Doc for JavaScript processes Word documents directly in the browser via WebAssembly, using a virtual file system (VFS) to manage fonts and file resources — no backend server required.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Insert Image into Textbox
Filling a textbox with a picture is a common technique for creating product labels, business cards, or promotional materials. Spire.Doc creates a textbox via the AppendTextBox method, then fills its background with a picture using FillEfects.SetPicture. The core process involves three steps: first, load font files and the target image into the WASM virtual file system via FetchFileToVFS; then create a document, add a textbox with position properties, and apply the picture to the textbox through fill effects; finally, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
function App() {
const InsertImageIntoTextBox = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load fonts and the image file into VFS
const imageFileName = 'Spire.Doc.png';
await window.spire.FetchFileToVFS(imageFileName, '', `${process.env.PUBLIC_URL}/data/`);
// Create a document
const doc = new docModule.Document();
// Add a section
let section = doc.AddSection();
// Add a paragraph
let paragraph = section.AddParagraph();
// Append a 220x220 textbox to the paragraph
let tb = paragraph.AppendTextBox(220, 220);
// Set textbox position
tb.Format.HorizontalOrigin = docModule.HorizontalOrigin.Page;
tb.Format.HorizontalPosition = 50;
tb.Format.VerticalOrigin = docModule.VerticalOrigin.Page;
tb.Format.VerticalPosition = 50;
// Set the textbox fill type to Picture
tb.Format.FillEfects.Type = docModule.BackgroundType.Picture;
// Fill the textbox with the image
tb.Format.FillEfects.SetPicture(imageFileName);
// Define output file name and save
const outputFileName = "InsertImageIntoTextBox_output.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
doc.Close();
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Insert Image into a Word Textbox</h1>
<button onClick={InsertImageIntoTextBox}>
Generate
</button>
</div>
);
}
export default App;
Image filled into the textbox, automatically scaled to fit

Insert Table into Textbox
Embedding structured table data in sidebars or reference areas is a common requirement in technical documents and reports. Spire.Doc supports creating tables within a textbox and adding them directly to the textbox body via the textbox.Body.AddTable method. Compared to creating tables in the main document body, tables inside a textbox can be positioned independently without being affected by page layout. The core process involves three steps: first, load font files into the WASM virtual file system via FetchFileToVFS; then create a document and a textbox, add a table via textbox.Body.AddTable with specified row and column counts, fill data row by row, and apply styles; finally, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
function App() {
const InsertTableIntoTextBox = async () => {
// Get the Spire.Doc WASM module
const docModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!docModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load font files into VFS
await window.spire.FetchFileToVFS('msyh.ttc', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// Create a document
const doc = new docModule.Document();
// Add a section
let section = doc.AddSection();
// Add a paragraph
let paragraph = section.AddParagraph();
// Add a 300x150 textbox
let textbox = paragraph.AppendTextBox(300, 150);
// Set textbox position
textbox.Format.HorizontalOrigin = docModule.HorizontalOrigin.Page;
textbox.Format.HorizontalPosition = 140;
textbox.Format.VerticalOrigin = docModule.VerticalOrigin.Page;
textbox.Format.VerticalPosition = 50;
// Add a title paragraph in the textbox
let textboxParagraph = textbox.Body.AddParagraph();
let textboxRange = textboxParagraph.AppendText("Table 1");
textboxRange.CharacterFormat.FontName = "Microsoft YaHei";
// Insert a table into the textbox
let table = textbox.Body.AddTable({ showBorder: true });
// Specify the number of rows and columns
table.ResetCells(4, 4);
let data = [
["Name", "Age", "Gender", "ID"],
["John", "28", "Male", "0023"],
["Jane", "30", "Male", "0024"],
["Wang Wu", "26", "Female", "0025"]
];
// Populate data into the table
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
let tableRange = table.Rows.get_Item(i).Cells.get_Item(j).AddParagraph().AppendText(data[i][j]);
tableRange.CharacterFormat.FontName = "Microsoft YaHei";
}
}
// Apply table style
table.ApplyStyle({ builtinTableStyle: docModule.DefaultTableStyle.TableColorful2 });
// Define output file name and save
const outputFileName = "InsertTableIntoTextBox_output.docx";
doc.SaveToFile({ fileName: outputFileName, fileFormat: docModule.FileFormat.Docx2013 });
// Release resources
doc.Close();
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Insert Table into a Word Textbox</h1>
<button onClick={InsertTableIntoTextBox}>
Generate
</button>
</div>
);
}
export default App;
Table created inside the textbox, contained within the textbox and freely positionable

FAQ
Image in the textbox is truncated or not fully displayed
Cause: The textbox size does not match the image aspect ratio, so the dimensions specified when creating the textbox cannot fully accommodate the image.
Solution: Adjust the textbox size to match the image proportions, or choose an image that fits the textbox dimensions:
let tb = paragraph.AppendTextBox(400, 300);
Table in the textbox has no visible borders
Cause: The showBorder parameter was not set or was set to false when creating the table, resulting in a borderless table.
Solution: Confirm the showBorder parameter is set to true when creating the table:
let table = textbox.Body.AddTable({ showBorder: true });
Textbox position is not as expected after saving
Cause: The HorizontalOrigin or VerticalOrigin values were configured incorrectly, causing the positioning reference point to differ from what was expected.
Solution: Choose the appropriate origin type based on your requirements, and fine-tune the position using HorizontalPosition / VerticalPosition:
tb.Format.HorizontalOrigin = docModule.HorizontalOrigin.Page;
tb.Format.HorizontalPosition = 50;
tb.Format.VerticalOrigin = docModule.VerticalOrigin.Page;
tb.Format.VerticalPosition = 50;
Get a Free License
Spire.Doc for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Add and Set Headers and Footers in Word with JavaScript in React
2026-07-07 03:40:23 Written by Amy ZhaoHeaders and footers are essential parts of any Word document — headers typically hold a company logo or document title, while footers display page numbers, copyright notices, and other supplementary information. Spire.Doc for JavaScript leverages WebAssembly to create and edit Word documents directly in the browser, managing fonts and file resources through a virtual file system (VFS) with no backend server required.
This article covers three core features:
- Add headers and footers (image, text, page number)
- Set a different header/footer for the first page
- Set different headers and footers for odd and even pages
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Add Headers and Footers (Image, Text, Page Number)
In real-world development, the most common requirement is adding headers and footers to a document: inserting a company logo and document title in the header, and page numbers with copyright information in the footer. Spire.Doc provides the HeadersFooters.Header and HeadersFooters.Footer properties to access header and footer objects, then uses AppendPicture to insert images, AppendText to insert text, and AppendField to insert page number fields. The core workflow has three phases: first, load font files and the target Word document into the WASM virtual file system via FetchFileToVFS; then instantiate a Document, load the file, retrieve the section, and call a custom function to populate the header and footer content; finally, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
function InsertHeaderAndFooter(section, inputImgFileName, inputImgFileName_1) {
let wasmModule = window.wasmModule.spiredoc;
let header = section.HeadersFooters.Header;
let footer = section.HeadersFooters.Footer;
// Insert an image and text in the header
let headerParagraph = header.AddParagraph();
let headerPicture = headerParagraph.AppendPicture({ imgFile: inputImgFileName });
// Header text
let text = headerParagraph.AppendText("Demo of Spire.Doc");
text.CharacterFormat.FontName = "Arial";
text.CharacterFormat.FontSize = 10;
text.CharacterFormat.Italic = true;
headerParagraph.Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Right;
// Bottom border for the header
headerParagraph.Format.Borders.Bottom.BorderType = wasmModule.BorderStyle.Single;
headerParagraph.Format.Borders.Bottom.Space = 0.05;
// Header image layout - text wrapping
headerPicture.TextWrappingStyle = wasmModule.TextWrappingStyle.Behind;
// Header image layout - position
headerPicture.HorizontalOrigin = wasmModule.HorizontalOrigin.Page;
headerPicture.HorizontalAlignment = wasmModule.ShapeHorizontalAlignment.Left;
headerPicture.VerticalOrigin = wasmModule.VerticalOrigin.Page;
headerPicture.VerticalAlignment = wasmModule.ShapeVerticalAlignment.Top;
// Insert an image in the footer
let footerParagraph = footer.AddParagraph();
let footerPicture = footerParagraph.AppendPicture({ imgFile: inputImgFileName_1 });
// Footer image layout
footerPicture.TextWrappingStyle = wasmModule.TextWrappingStyle.Behind;
footerPicture.HorizontalOrigin = wasmModule.HorizontalOrigin.Page;
footerPicture.HorizontalAlignment = wasmModule.ShapeHorizontalAlignment.Left;
footerPicture.VerticalOrigin = wasmModule.VerticalOrigin.Page;
footerPicture.VerticalAlignment = wasmModule.ShapeVerticalAlignment.Bottom;
// Insert page number
footerParagraph.AppendField("page number", wasmModule.FieldType.FieldPage);
footerParagraph.AppendText(" of ");
footerParagraph.AppendField("number of pages", wasmModule.FieldType.FieldNumPages);
footerParagraph.Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Right;
// Top border for the footer
footerParagraph.Format.Borders.Top.BorderType = wasmModule.BorderStyle.Single;
footerParagraph.Format.Borders.Top.Space = 0.05;
}
function App() {
const AddHeaderAndFooter = async () => {
// Get the Spire.Doc WASM module
const wasmModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample Word file into VFS
const inputFileName = "Sample.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
const inputImgFileName = "Header.png";
await window.spire.FetchFileToVFS(inputImgFileName, "", `${process.env.PUBLIC_URL}/data/`);
const inputImgFileName_1 = "Footer.png";
await window.spire.FetchFileToVFS(inputImgFileName_1, "", `${process.env.PUBLIC_URL}/data/`);
// Load the document
let doc = new wasmModule.Document();
doc.LoadFromFile(inputFileName);
let section = doc.Sections.get_Item(0);
// Insert header and footer
InsertHeaderAndFooter(section, inputImgFileName, inputImgFileName_1);
// Define the output file name
const outputFileName = "HeaderAndFooter.docx";
// Save the document
doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2013 });
// Release resources
doc.Close();
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Add Headers And Footers To Word Document</h1>
<button onClick={AddHeaderAndFooter}>
Generate
</button>
</div>
);
}
export default App;
Header and footer with image, text, and page numbers applied

Set a Different Header/Footer for the First Page
In many real-world scenarios, the first page (cover page) of a document needs different headers and footers than the rest of the pages, or even no headers and footers at all. Spire.Doc enables this by setting PageSetup.DifferentFirstPageHeaderFooter = true. The first page content is configured via HeadersFooters.FirstPageHeader / FirstPageFooter, while the remaining pages use HeadersFooters.Header / Footer.
function App() {
const DifferentFirstPage = async () => {
// Get the Spire.Doc WASM module
const wasmModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample file into VFS
let inputFileName = "MultiplePages.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
let inputImgFileName = "E-iceblue.png";
await window.spire.FetchFileToVFS(inputImgFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Load the document
let doc = new wasmModule.Document();
doc.LoadFromFile(inputFileName);
// Get the section and enable a different first-page header/footer
let section = doc.Sections.get_Item(0);
section.PageSetup.DifferentFirstPageHeaderFooter = true;
// Set the first page header: insert an image aligned to the right
let paragraph1 = section.HeadersFooters.FirstPageHeader.AddParagraph();
paragraph1.Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Right;
let headerimage = paragraph1.AppendPicture({ imgFile: inputImgFileName });
// Set the first page footer: centered text
let paragraph2 = section.HeadersFooters.FirstPageFooter.AddParagraph();
paragraph2.Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Center;
let FF = paragraph2.AppendText("First Page Footer");
FF.CharacterFormat.FontSize = 10;
// Set headers and footers for the other pages
let paragraph3 = section.HeadersFooters.Header.AddParagraph();
paragraph3.Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Center;
let NH = paragraph3.AppendText("Spire.Doc for JavaScript");
NH.CharacterFormat.FontSize = 10;
let paragraph4 = section.HeadersFooters.Footer.AddParagraph();
paragraph4.Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Center;
let NF = paragraph4.AppendText("E-iceblue");
NF.CharacterFormat.FontSize = 10;
// Define the output file name
const outputFileName = "DifferentFirstPage.docx";
// Save the document
doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2013 });
// Release resources
doc.Close();
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Set Different First Page Header And Footer</h1>
<button onClick={DifferentFirstPage}>
Generate
</button>
</div>
);
}
export default App;
The first page displays separate header and footer content, while the other pages use unified headers and footers.

Set Different Headers and Footers for Odd and Even Pages
For documents intended for duplex printing or book layout, it is common to use different headers and footers for odd and even pages — for example, odd-page headers show the chapter name aligned to the right, while even-page headers show the book title aligned to the left. Spire.Doc enables this by setting PageSetup.DifferentOddAndEvenPagesHeaderFooter = true, then configuring content via OddHeader / OddFooter and EvenHeader / EvenFooter respectively.
function App() {
const OddAndEvenHeaderFooter = async () => {
// Get the Spire.Doc WASM module
const wasmModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample file into VFS
let inputFileName = "MultiplePages.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Load the document
let doc = new wasmModule.Document();
doc.LoadFromFile(inputFileName);
// Get the first section
let section = doc.Sections.get_Item(0);
// Enable different odd and even page headers/footers
section.PageSetup.DifferentOddAndEvenPagesHeaderFooter = true;
// Add odd page header
let P3 = section.HeadersFooters.OddHeader.AddParagraph();
let OH = P3.AppendText("Odd Header");
P3.Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Center;
OH.CharacterFormat.FontName = "Arial";
OH.CharacterFormat.FontSize = 10;
// Add even page header
let P4 = section.HeadersFooters.EvenHeader.AddParagraph();
let EH = P4.AppendText("Even Header from E-iceblue Using Spire.Doc");
P4.Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Center;
EH.CharacterFormat.FontName = "Arial";
EH.CharacterFormat.FontSize = 10;
// Add odd page footer
let P2 = section.HeadersFooters.OddFooter.AddParagraph();
let OF = P2.AppendText("Odd Footer");
P2.Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Center;
OF.CharacterFormat.FontName = "Arial";
OF.CharacterFormat.FontSize = 10;
// Add even page footer
let P1 = section.HeadersFooters.EvenFooter.AddParagraph();
let EF = P1.AppendText("Even Footer from E-iceblue Using Spire.Doc");
EF.CharacterFormat.FontName = "Arial";
EF.CharacterFormat.FontSize = 10;
P1.Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Center;
// Define the output file name
const outputFileName = "OddAndEvenHeaderFooter_output.docx";
// Save the document
doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2013 });
// Release resources
doc.Close();
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Set Odd And Even Page Headers And Footers</h1>
<button onClick={OddAndEvenHeaderFooter}>
Generate
</button>
</div>
);
}
export default App;
Different header and footer text is applied to odd and even pages.

FAQ
First-page header/footer does not display as expected
Cause: The DifferentFirstPageHeaderFooter property defaults to false. Editing FirstPageHeader or FirstPageFooter directly without enabling it has no effect.
Solution: Set the property to true before editing the first-page header/footer:
section.PageSetup.DifferentFirstPageHeaderFooter = true;
// Then edit FirstPageHeader / FirstPageFooter
Odd/even page settings do not take effect
Cause: The DifferentOddAndEvenPagesHeaderFooter property defaults to false. Editing OddHeader / EvenHeader directly without enabling it has no effect.
Solution: Enable the property before editing odd/even page content:
section.PageSetup.DifferentOddAndEvenPagesHeaderFooter = true;
// Then edit OddHeader / EvenHeader / OddFooter / EvenFooter
Get a Free License
If you wish to remove the evaluation message from the resulting document, or to eliminate functional limitations, please contact our sales team to request a 30-day temporary license.
Merging and splitting table cells is one of the most common table editing operations in Word document development — whether creating report headers with cross-column titles or grouping products across rows, cell merging makes table structures clearer and more organized. Spire.Doc for JavaScript runs entirely in the browser via WebAssembly, using a virtual file system (VFS) to manage fonts and file resources — no backend server required.
This article covers three core features:
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Merge and Split Cells
A common task in real-world development is adjusting the structure of an existing table: merging adjacent cells into one, or splitting a single cell into multiple rows and columns. Spire.Doc provides ApplyHorizontalMerge, ApplyVerticalMerge, and SplitCell methods for horizontal merging, vertical merging, and splitting respectively. The workflow involves three steps: first, load font files and the target Word file into the WASM virtual file system via FetchFileToVFS; then instantiate a Document, load the file, retrieve the target table, and call the merge or split methods; finally, save the document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
function App() {
const MergeAndSplitTableCell = async () => {
// Get the Spire.Doc WASM module
const wasmModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample Word file into VFS
let inputFileName = "TableSample.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Load the document
let doc = new wasmModule.Document();
doc.LoadFromFile(inputFileName);
let section = doc.Sections.get_Item(0);
let table = section.Tables.get_Item(0);
// Horizontal merge: merge columns 2 and 3 in row 6
table.ApplyHorizontalMerge(6, 2, 3);
// Vertical merge: merge rows 4 and 5 in column 2
table.ApplyVerticalMerge(2, 4, 5);
// Split cell: split the cell at row 8, column 3 into 2 rows and 2 columns
table.Rows.get_Item(8).Cells.get_Item(3).SplitCell(2, 2);
// Define the output file name
const outputFileName = "MergeAndSplitTableCell_output.docx";
// Save the document
doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2013 });
// Release resources
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Merge and Split Table Cells</h1>
<button onClick={MergeAndSplitTableCell}>
Generate
</button>
</div>
);
}
export default App;

Format Merged Cells
After merging cells, you typically need to format the merged area — setting font styles, alignment, and background colors — to improve table readability and visual appeal. The following example demonstrates how to create a product price table, merge the "Product" header cell and the version category cells on the left, and apply custom styling.
function AddTable(section) {
let wasmModule = window.wasmModule.spiredoc;
let table = section.AddTable({ showBorder: true });
table.ResetCells(4, 3);
// Table data
let dt = [["Product", "", "Inventory(kg)"],
["Fruit", "Apples", "150"],
["", "Grapes", "200"],
["", "Lemons", "100"]];
for (let r = 0; r < dt.length; r++) {
let dataRow = table.Rows.get_Item(r);
dataRow.Height = 20;
dataRow.HeightType = wasmModule.TableRowHeightType.Exactly;
for (let i = 0; i < dataRow.Cells.Count; i++) {
dataRow.Cells.get_Item(i).CellFormat.Shading.BackgroundPatternColor = wasmModule.Color.Empty;
}
for (let c = 0; c < dataRow.Cells.Count; c++) {
if (dt[r][c] !== "") {
let range = dataRow.Cells.get_Item(c).AddParagraph().AppendText(dt[r][c]);
range.CharacterFormat.FontName = "Arial";
}
}
}
return table;
}
function App() {
const FormatMergedCells = async () => {
// Get the Spire.Doc WASM module
const wasmModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Create a Word document
let doc = new wasmModule.Document();
let section = doc.AddSection();
// Add a table
let table = AddTable(section);
// Create a custom style
let style = new wasmModule.ParagraphStyle(doc);
style.Name = "Style";
style.CharacterFormat.TextColor = wasmModule.Color.get_DeepSkyBlue();
style.CharacterFormat.Italic = true;
style.CharacterFormat.Bold = true;
style.CharacterFormat.FontSize = 13;
doc.Styles.Add(style);
// Horizontal merge: merge columns 0 and 1 in row 0
table.ApplyHorizontalMerge(0, 0, 1);
// Apply the style
table.Rows.get_Item(0).Cells.get_Item(0).Paragraphs.get_Item(0).ApplyStyle(style.Name);
// Set vertical and horizontal alignment
table.Rows.get_Item(0).Cells.get_Item(0).CellFormat.VerticalAlignment = wasmModule.VerticalAlignment.Middle;
table.Rows.get_Item(0).Cells.get_Item(0).Paragraphs.get_Item(0).Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Center;
// Vertical merge: merge rows 1, 2, and 3 in column 0
table.ApplyVerticalMerge(0, 1, 3);
// Apply the style
table.Rows.get_Item(1).Cells.get_Item(0).Paragraphs.get_Item(0).ApplyStyle(style.Name);
// Set vertical and horizontal alignment
table.Rows.get_Item(1).Cells.get_Item(0).CellFormat.VerticalAlignment = wasmModule.VerticalAlignment.Middle;
table.Rows.get_Item(1).Cells.get_Item(0).Paragraphs.get_Item(0).Format.HorizontalAlignment = wasmModule.HorizontalAlignment.Left;
// Set column width
table.Rows.get_Item(1).Cells.get_Item(0).SetCellWidth(20, wasmModule.CellWidthType.Percentage);
// Define the output file name
const outputFileName = "FormatMergedCells_output.docx";
// Save the document
doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2013 });
// Release resources
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Format Merged Cells</h1>
<button onClick={FormatMergedCells}>
Generate
</button>
</div>
);
}
export default App;

Check Cell Merge Status
When working with tables created by others or generated by automated processes, you often need to identify which cells have been merged to avoid index-out-of-bounds errors. Spire.Doc provides two properties — CellFormat.VerticalMerge and Cell.GridSpan — to detect cell merge status: VerticalMerge indicates vertical merging, and GridSpan indicates the number of columns a cell spans horizontally.
function App() {
const CellMergeStatus = async () => {
// Get the Spire.Doc WASM module
const wasmModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load the sample file into VFS
let inputFileName = "CellMergeStatus.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Load the document
let doc = new wasmModule.Document();
doc.LoadFromFile(inputFileName);
// Get the first section and first table
let section = doc.Sections.get_Item(0);
let table = section.Tables.get_Item(0);
// Iterate through all cells to detect merge status
let stringBuidler = [];
for (let i = 0; i < table.Rows.Count; i++) {
let tableRow = table.Rows.get_Item(i);
for (let j = 0; j < tableRow.Cells.Count; j++) {
let tableCell = tableRow.Cells.get_Item(j);
let verticalMerge = tableCell.CellFormat.VerticalMerge;
let horizontalMerge = tableCell.GridSpan;
if (verticalMerge === wasmModule.CellMerge.None && horizontalMerge === 1) {
stringBuidler.push("Row " + i + ", cell " + j + ": ");
stringBuidler.push("This cell isn't merged.\n");
} else {
stringBuidler.push("Row " + i + ", cell " + j + ": ");
stringBuidler.push("This cell is merged.\n");
}
}
stringBuidler.push("\n");
}
// Define the output file name
const outputFileName = "CellMergeStatus_output.txt";
// Write the detection result to a text file
window.dotnetRuntime.Module.FS.writeFile(outputFileName, stringBuidler.join('\n'));
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Check Cell Merge Status</h1>
<button onClick={CellMergeStatus}>
Generate
</button>
</div>
);
}
export default App;

FAQ
How to verify if a cell merge was successful
Cause: Merge operations do not return a status value — you need to read cell properties to confirm.
Solution: Use CellFormat.VerticalMerge to check the vertical merge type (CellMerge.None means not merged), and Cell.GridSpan to check the number of columns spanned horizontally (a value of 1 means not merged):
let verticalMerge = tableCell.CellFormat.VerticalMerge;
let horizontalMerge = tableCell.GridSpan;
if (verticalMerge === wasmModule.CellMerge.None && horizontalMerge === 1) {
// Not merged
} else {
// Merged
}
Content lost after splitting a cell
Cause: When SplitCell splits a cell into multiple sub-cells, the original content remains in the first sub-cell by default.
Solution: Manually iterate through the sub-cells to redistribute content after splitting, or back up the cell text via the Paragraphs collection beforehand:
// Back up the content
let cell = table.Rows.get_Item(row).Cells.get_Item(col);
let text = cell.Paragraphs.get_Item(0).Text;
// Split into 2 rows and 2 columns
cell.SplitCell(2, 2);
// Write the content to the new cell
table.Rows.get_Item(row).Cells.get_Item(col).Paragraphs.get_Item(0).AppendText(text);
Index out of range when merging cells
Cause: ApplyHorizontalMerge(row, startCol, endCol) and ApplyVerticalMerge(col, startRow, endRow) use zero-based indexing. Passing indices that exceed the table's actual row or column count will throw an error.
Solution: Check the table dimensions before merging to ensure the end index does not exceed Rows.Count - 1 and Cells.Count - 1:
if (endCol < table.Rows.get_Item(row).Cells.Count && endRow < table.Rows.Count) {
table.ApplyHorizontalMerge(row, startCol, endCol);
}
Get a Free License
Spire.Doc for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Copy, Remove, and Lock Headers and Footers in Word with JavaScript in React
2026-07-06 08:33:20 Written by Amy ZhaoIn real-world document development workflows, maintaining headers and footers is just as important as adding them — copying headers and footers from a template document for quick reuse, removing old headers and footers for document cleanup, and locking headers to prevent content tampering are all common daily requirements. Spire.Doc for JavaScript leverages WebAssembly to process Word documents directly in the browser, managing fonts and file resources through a virtual file system (VFS) with no backend server required.
This article covers three core features:
For installation and project setup, refer to Integrating Spire.Doc for JavaScript in a React Project. The examples below assume Spire.Doc is installed and the WebAssembly module is initialized.
Copy Headers and Footers
In enterprise document production, a standard template document typically defines unified headers (company logo + document title) and footers (page number + copyright notice). When creating new documents, the headers and footers from the template need to be copied over to maintain consistent corporate document styling. Spire.Doc uses the ChildObjects collection and the Clone method to copy header objects across documents. The core workflow has three phases: first, load font files and two Word files (source and destination documents) into the WASM virtual file system via FetchFileToVFS; then instantiate two Document objects, retrieve the header's child objects from the source document, iterate and clone them into each section's header of the destination document; finally, save the destination document, read the generated file from VFS, wrap it as a Blob, and trigger a browser download.
function App() {
const CopyHeaderAndFooter = async () => {
// Get the Spire.Doc WASM module
const wasmModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load fonts and the document files into VFS
await window.spire.FetchFileToVFS('ARIALUNI.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// Load the source and destination files into VFS
let inputFileName = "HeaderAndFooter.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
const inputFileName_1 = "Template.docx";
await window.spire.FetchFileToVFS(inputFileName_1, "", `${process.env.PUBLIC_URL}/data/`);
// Load the source document
let doc1 = new wasmModule.Document();
doc1.LoadFromFile(inputFileName);
// Get the header from the source document
let header = doc1.Sections.get_Item(0).HeadersFooters.Header;
// Load the destination document
let doc2 = new wasmModule.Document();
doc2.LoadFromFile(inputFileName_1);
// Clone each child object from the source header into all sections of the destination document
for (let i = 0; i < doc2.Sections.Count; i++) {
let section = doc2.Sections.get_Item(i);
for (let j = 0; j < header.ChildObjects.Count; j++) {
let obj = header.ChildObjects.get_Item(j);
section.HeadersFooters.Header.ChildObjects.Add(obj.Clone());
}
}
// Define the output file name
const outputFileName = "CopyHeaderAndFooter_output.docx";
// Save the document
doc2.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2013 });
// Release resources
doc1.Close();
doc2.Close();
doc1.Dispose();
doc2.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Copy Headers And Footers To Another Word Document</h1>
<button onClick={CopyHeaderAndFooter}>
Generate
</button>
</div>
);
}
export default App;
The code above clones the header content from the source document into all sections of the destination document.

Remove Headers and Footers
In document cleanup or template replacement scenarios, it is often necessary to remove existing headers or footers from a document. For example, when taking over someone else's document and needing to redesign the headers and footers, clearing the original content first; or when documents exported from a customer system contain default headers that need to be removed before replacing with corporate templates. Spire.Doc uses HeadersFooters.get_Item to retrieve header or footer objects by type (first page, odd page, even page), and then calls ChildObjects.Clear() to remove all their content.
function App() {
const RemoveHeaderFooter = async () => {
// Get the Spire.Doc WASM module
const wasmModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load fonts and the document file into VFS
await window.spire.FetchFileToVFS('ARIALUNI.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// Load the sample file into VFS
let inputFileName = "HeaderAndFooter.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Load the document
let doc = new wasmModule.Document();
doc.LoadFromFile(inputFileName);
// Get the first section
let section = doc.Sections.get_Item(0);
// Clear all types of header content (first page, odd page, even page)
let header;
header = section.HeadersFooters.get_Item({ hfType: wasmModule.HeaderFooterType.HeaderFirstPage });
if (header != null)
header.ChildObjects.Clear();
header = section.HeadersFooters.get_Item({ hfType: wasmModule.HeaderFooterType.HeaderOdd });
if (header != null)
header.ChildObjects.Clear();
header = section.HeadersFooters.get_Item({ hfType: wasmModule.HeaderFooterType.HeaderEven });
if (header != null)
header.ChildObjects.Clear();
// Clear all types of footer content (first page, odd page, even page)
let footer;
footer = section.HeadersFooters.get_Item({ hfType: wasmModule.HeaderFooterType.FooterFirstPage });
if (footer != null)
footer.ChildObjects.Clear();
footer = section.HeadersFooters.get_Item({ hfType: wasmModule.HeaderFooterType.FooterOdd });
if (footer != null)
footer.ChildObjects.Clear();
footer = section.HeadersFooters.get_Item({ hfType: wasmModule.HeaderFooterType.FooterEven });
if (footer != null)
footer.ChildObjects.Clear();
// Define the output file name
const outputFileName = "RemoveHeaderFooter_output.docx";
// Save the document
doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2013 });
// Release resources
doc.Close();
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Remove Headers And Footers From Word Document</h1>
<button onClick={RemoveHeaderFooter}>
Generate
</button>
</div>
);
}
export default App;
The document after removing the header.

Lock Headers to Prevent Editing
When distributing documents to clients or team members, it is often desirable to prevent fixed information such as the company logo and document number in the header from being modified, while allowing the body text to remain editable. Spire.Doc achieves this through document protection: set the protection type to AllowOnlyFormFields, then set the section's ProtectForm property to false, so the body area stays editable while the header area is protected from modification.
function App() {
const LockHeader = async () => {
// Get the Spire.Doc WASM module
const wasmModule = window.wasmModule?.spiredoc;
// Check if the module is ready
if (!wasmModule) {
alert('Spire.Doc is not ready yet');
return;
}
// Load fonts and the document file into VFS
await window.spire.FetchFileToVFS('ARIALUNI.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// Load the sample file into VFS
let inputFileName = "HeaderAndFooter.docx";
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Load the document
let doc = new wasmModule.Document();
doc.LoadFromFile(inputFileName);
// Get the first section
let section = doc.Sections.get_Item(0);
// Protect the document with AllowOnlyFormFields type
doc.Protect({ type: wasmModule.ProtectionType.AllowOnlyFormFields, password: "123" });
// Set the section as editable, so the body area is not locked
section.ProtectForm = false;
// Define the output file name
const outputFileName = "LockHeader_output.docx";
// Save the document
doc.SaveToFile({ fileName: outputFileName, fileFormat: wasmModule.FileFormat.Docx2013 });
// Release resources
doc.Close();
doc.Dispose();
// Read the generated file from VFS and trigger download
const modifiedFileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([modifiedFileArray], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Lock Header In Word Document</h1>
<button onClick={LockHeader}>
Generate
</button>
</div>
);
}
export default App;
When the header is locked, the header area cannot be edited when opening the document in Word, while the body area remains modifiable.

FAQ
Copied header content does not display in the destination document
Cause: The destination document contains multiple sections, but the copy operation only processes the first section's header, leaving headers in other sections unchanged.
Solution: Iterate through all sections of the destination document and copy the source header content to each section:
for (let i = 0; i < doc2.Sections.Count; i++) {
let section = doc2.Sections.get_Item(i);
for (let j = 0; j < header.ChildObjects.Count; j++) {
let obj = header.ChildObjects.get_Item(j);
section.HeadersFooters.Header.ChildObjects.Add(obj.Clone());
}
}
The entire document becomes uneditable after locking the header
Cause: doc.Protect({ type: AllowOnlyFormFields }) locks the entire document by default, including the body area.
Solution: After applying protection, set the section's ProtectForm property to false to keep the body area editable:
doc.Protect({ type: wasmModule.ProtectionType.AllowOnlyFormFields, password: "123" });
section.ProtectForm = false;
Footer content is also cleared when removing headers
Cause: The header removal logic is mistakenly applied to the footer, or the same ChildObjects.Clear() operation is used on the wrong object.
Solution: Use different HeaderFooterType parameters for removing headers versus removing footers, ensuring the correct object is targeted:
// Use Header type when removing headers
section.HeadersFooters.get_Item({ hfType: wasmModule.HeaderFooterType.HeaderFirstPage });
// Use Footer type when removing footers
section.HeadersFooters.get_Item({ hfType: wasmModule.HeaderFooterType.FooterFirstPage });
Get a Free License
If you wish to remove the evaluation message from the resulting document, or to eliminate functional limitations, please contact our sales team to request a 30-day temporary license.