JavaScript (260)
Add, Read, and Delete Excel Shapes with JavaScript in React
2026-08-14 07:40:40 Written by zaki zakiShapes are graphic elements in Excel that enhance the visual appeal of a worksheet and convey information intuitively, such as arrows, rectangles, ovals, and stars. With shapes, you can add annotations, process-flow indicators, or decorative elements next to your data, making reports more vivid and easier to read. Spire.XLS for JavaScript runs entirely in the browser via WebAssembly, using a virtual file system (VFS) to manage input and output files — no backend server required. It provides a complete API for adding shapes and customizing their appearance (such as fill, rotation angle, text, and shadow), reading text and images from shapes, and deleting specified or all shapes.
This article covers three core features:
For installation and project setup, refer to Integrating Spire.XLS for JavaScript in a React Project. The examples below assume Spire.XLS is installed and the WebAssembly module is initialized.
Add Shapes to Excel
Adding shapes to Excel can highlight key data and beautify the layout of a worksheet. With Spire.XLS for JavaScript, you can add a shape and set its position (row, column) and size (width, height) at once using the PrstGeomShapes.AddPrstGeomShape() method, and then customize its appearance through the shape's properties — set solid, gradient, texture, or picture fill via Fill, add text via Text, set the rotation angle via Rotation, apply a shadow effect via Shadow, and control visibility via Visible. The steps are as follows:
- Create a
Workbookobject and get the default worksheet. - Add shapes using
PrstGeomShapes.AddPrstGeomShape(), setting the shape type, position, and size through the parameters. - Set solid, gradient, texture, or picture fill for the shapes via the
Fillproperty. - Add text to a shape via the
Textproperty, and set the rotation angle via theRotationproperty. - Set a shadow effect for a shape via the
Shadowproperty. - Save the workbook to an Excel file using
SaveToFile().
Below is a complete code example demonstrating how to add and customize various shapes in React:
function App() {
const addShapes = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the picture into the virtual file system (VFS)
await window.spire.FetchFileToVFS('SpireXls.png', '', `${process.env.PUBLIC_URL}/image/`);
// Create a new workbook and get the default worksheet
const workbook = new xlsModule.Workbook();
let sheet = workbook.Worksheets.get(0);
// Add a triangle shape and fill it with a solid color
let triangle = sheet.PrstGeomShapes.AddPrstGeomShape(2, 2, 100, 100, xlsModule.PrstGeomShapeType.Triangle);
triangle.Fill.ForeColor = xlsModule.Color.get_Yellow();
triangle.Fill.FillType = xlsModule.ShapeFillType.SolidColor;
// Add text to the triangle and set its rotation angle
triangle.Text = 'Triangle';
triangle.Rotation = 45;
// Add a heart shape and fill it with a gradient color
let heart = sheet.PrstGeomShapes.AddPrstGeomShape(2, 5, 100, 100, xlsModule.PrstGeomShapeType.Heart);
heart.Fill.ForeColor = xlsModule.Color.get_Red();
heart.Fill.FillType = xlsModule.ShapeFillType.Gradient;
// Set the shadow style for the heart
heart.Shadow.Angle = 90;
heart.Shadow.Distance = 10;
heart.Shadow.Size = 150;
heart.Shadow.Color = xlsModule.Color.get_Gray();
heart.Shadow.Blur = 30;
heart.Shadow.Transparency = 1;
heart.Shadow.HasCustomStyle = true;
// Add an arrow shape
let arrow = sheet.PrstGeomShapes.AddPrstGeomShape(10, 2, 100, 100, xlsModule.PrstGeomShapeType.CurvedRightArrow);
// Add a cloud shape and fill it with a picture
let cloud = sheet.PrstGeomShapes.AddPrstGeomShape(10, 5, 100, 100, xlsModule.PrstGeomShapeType.Cloud);
cloud.Fill.CustomPicture({ im: new xlsModule.Stream('SpireXls.png'), name: 'SpireXls.png' });
// Save the workbook
const outputFileName = 'AddShapes.xlsx';
workbook.SaveToFile(outputFileName);
workbook.Dispose();
// 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.spreadsheetml.sheet' });
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 Shapes</h1>
<button onClick={addShapes}>
Generate
</button>
</div>
);
}
export default App;
Shapes added to Excel with Spire.XLS for JavaScript

Read Text and Images from Excel Shapes
Reading the text and images from shapes helps you extract the data inside shapes in batch, or reuse and archive shape resources. With Spire.XLS for JavaScript, you can load an Excel file containing shapes, get a specified shape by index via PrstGeomShapes.get(), then read its text content via the Text property and get its fill picture via Fill.Picture. The steps are as follows:
- Create a
Workbookobject and load an existing Excel file containing shapes. - Get the worksheet via
workbook.Worksheets.get(). - Get a specified shape by index using
sheet.PrstGeomShapes.get(). - Read the text in the shape via the
Textproperty. - Read the fill picture in the shape via the
Fill.Pictureproperty. - Save the read text and image as txt and png files.
Below is a complete code example demonstrating how to read text and images from shapes in React (the example loads the AddShapes.xlsx file generated in the previous section):
function App() {
const readShapes = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the sample file containing shapes into the virtual file system (VFS)
let excelFileName = 'AddShapes.xlsx';
await window.spire.FetchFileToVFS(excelFileName, '', `${process.env.PUBLIC_URL}data/`);
// Create a workbook object and load the existing file
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: excelFileName });
// Get the first worksheet
let sheet = workbook.Worksheets.get(0);
// Get the first shape (triangle) and read the text inside it
let triangle = sheet.PrstGeomShapes.get(0);
let text = triangle.Text;
// Get the fourth shape (cloud) and read the picture inside it
let cloud = sheet.PrstGeomShapes.get(3);
let image = cloud.Fill.Picture;
const imageFileName = 'ExtractImageFromShape.png';
image.Save(imageFileName);
workbook.Dispose();
// Save the read text to a txt file and trigger download
const textFileName = 'ExtractTextFromShape.txt';
const textBlob = new Blob([`The text in the first shape is: ${text}`], { type: 'text/plain;charset=utf-8' });
const textUrl = URL.createObjectURL(textBlob);
const a1 = document.createElement('a');
a1.href = textUrl;
a1.download = textFileName;
a1.click();
URL.revokeObjectURL(textUrl);
// Read the image file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(imageFileName);
const blob = new Blob([fileArray], { type: 'application/png' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = imageFileName;
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Read Text and Image from Shapes</h1>
<button onClick={readShapes}>
Generate
</button>
</div>
);
}
export default App;
Text and images read from Excel shapes with Spire.XLS for JavaScript

Delete Shapes in Excel
When shapes are no longer needed, deleting them in time keeps the worksheet clean and reduces the file size. With Spire.XLS for JavaScript, you can delete a specified shape via the Remove() method, or iterate through the shape collection and call Remove() on each shape to clear all shapes in a worksheet. The steps are as follows:
- Create a
Workbookobject and load an existing Excel file containing shapes. - Get the worksheet via
workbook.Worksheets.get(). - Get a specified shape using
sheet.PrstGeomShapes.get(), and call itsRemove()method to delete the shape. - Save the workbook to an Excel file using
SaveToFile().
Below is a complete code example demonstrating how to delete shapes in React (the example loads the AddShapes.xlsx file generated in the previous section):
function App() {
const deleteShapes = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the sample file containing shapes into the virtual file system (VFS)
let excelFileName = 'AddShapes.xlsx';
await window.spire.FetchFileToVFS(excelFileName, '', `${process.env.PUBLIC_URL}data/`);
// Create a workbook object and load the existing file
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: excelFileName });
// Get the first worksheet
let sheet = workbook.Worksheets.get(0);
// Delete the first shape in the worksheet
sheet.PrstGeomShapes.get(0).Remove();
// Delete all the shapes in the worksheet
// for (let i = sheet.PrstGeomShapes.Count - 1; i >= 0; i--) {
// sheet.PrstGeomShapes.get(i).Remove();
// }
// Save the workbook
const outputFileName = 'DeleteShapes.xlsx';
workbook.SaveToFile(outputFileName);
workbook.Dispose();
// 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.spreadsheetml.sheet' });
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>Delete Shapes</h1>
<button onClick={deleteShapes}>
Generate
</button>
</div>
);
}
export default App;
Specified shape deleted from Excel with Spire.XLS for JavaScript

FAQ
How to get the name and type of a shape?
Cause: When a worksheet contains many shapes, you may need to identify and locate shapes by their name or type rather than by index.
Solution: Read the Name and PrstShapeType properties of the shape to get its name and type:
// Get the worksheet
let sheet = workbook.Worksheets.get(0);
// Get the first shape
let shape = sheet.PrstGeomShapes.get(0);
// Get the name of the shape
let shapeName = shape.Name;
// Get the type of the shape
let shapeType = shape.PrstShapeType;
How to check whether a shape is currently visible?
Cause: After loading shapes from a file, you may need to determine whether a shape is hidden so that you can decide whether to process it further.
Solution: Read the Visible property of the shape to know its visibility state:
// Get the worksheet
let sheet = workbook.Worksheets.get(0);
// Get the first shape
let shape = sheet.PrstGeomShapes.get(0);
// Check whether the shape is visible
let isVisible = shape.Visible;
Get a Free License
Spire.XLS for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Freeze, Query, and Unfreeze Excel Worksheet Panes with JavaScript in React
2026-08-14 05:35:36 Written by Lisa LiWhen browsing an Excel worksheet that contains a large amount of data, pinning the header or key columns can significantly improve the efficiency of data viewing. The freeze panes feature keeps the specified rows or columns visible while scrolling. Querying the frozen pane range confirms which areas of the current worksheet are frozen. Unfreezing panes restores the normal browsing mode when the fixed display is no longer needed. Spire.XLS for JavaScript completes these operations directly in the browser based on WebAssembly, and manages input and output files through the virtual file system (VFS), without requiring backend service support.
This article introduces three core feature points:
For installation and project configuration, refer to Integrate Spire.XLS for JavaScript in a React Project. The following examples assume that Spire.XLS is installed and the WebAssembly module has been initialized.
Freeze Panes
When a worksheet contains a large amount of data, freezing panes can pin the header or a specific area so that you can always see the key rows or columns while scrolling through the data. Spire.XLS for JavaScript freezes the panes above and to the left of the specified position through the FreezePanes method. For example, FreezePanes(2, 1) freezes the first row, keeping it visible when scrolling vertically.
function App() {
const sheetToSVG = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check whether the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the font and the Excel file into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'FreezePanes.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// Load the workbook
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
// Get the first worksheet
const sheet = workbook.Worksheets.get(0);
// Freeze the first row
sheet.FreezePanes(2, 1);
// Set the width of the second column
sheet.SetColumnWidth(2, 10);
const outputFileName = "FreezePanes_output.xlsx";
workbook.SaveToFile({ fileName: outputFileName });
// Dispose of the workbook object to release resources
workbook.Dispose();
// Read the converted file from the VFS and trigger the download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
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>Freeze Panes</h1>
<button onClick={sheetToSVG}>
Start
</button>
</div>
);
}
export default App;
Original document
After freezing the first row 
Get the Freeze Pane Range
When working with frozen panes, sometimes you need to confirm the position of the frozen panes in the current worksheet. Spire.XLS for JavaScript obtains the row index and column index of the frozen panes through the GetFreezePanes method, and a return value of 0 indicates that the corresponding direction is not frozen.
function App() {
const sheetToSVG = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check whether the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the font and the Excel file into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'GetFreezePaneRange.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// Load the workbook
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
// Get the first worksheet
const sheet = workbook.Worksheets.get(0);
// Get the row index and column index of the frozen panes
const indexs = sheet.GetFreezePanes();
const rowIndex = indexs[0];
const colIndex = indexs[1];
// Write the query result to a text file
const outputFileName = "GetFreezePaneRange_output.txt";
window.dotnetRuntime.Module.FS.writeFile(outputFileName, `Row index: ${rowIndex}, column index: ${colIndex}`);
// Dispose of the workbook object to release resources
workbook.Dispose();
// Read the converted file from the VFS and trigger the download
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);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Get Freeze Pane Range</h1>
<button onClick={sheetToSVG}>
Start
</button>
</div>
);
}
export default App;
Original document with frozen panes
Query result 
Unfreeze Panes
When the fixed display is no longer needed, you can cancel the frozen panes that have been set in the worksheet through the RemovePanes method and restore normal scrolling.
function App() {
const sheetToSVG = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check whether the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the font and the Excel file into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'Template_Xls_2.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// Load the workbook
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
// Get the first worksheet
const sheet = workbook.Worksheets.get(0);
// Unfreeze the panes
sheet.RemovePanes();
const outputFileName = "UnfreezeExcelPanes_output.xlsx";
workbook.SaveToFile({ fileName: outputFileName });
// Dispose of the workbook object to release resources
workbook.Dispose();
// Read the converted file from the VFS and trigger the download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
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>Unfreeze Panes</h1>
<button onClick={sheetToSVG}>
Start
</button>
</div>
);
}
export default App;
Before unfreezing
After unfreezing 
FAQ
The first row still scrolls after freezing panes
Reason: The parameters of the FreezePanes method are set incorrectly, so the frozen area is not the expected row or column.
Solution: The FreezePanes method uses the specified position as the boundary and freezes the panes above and to the left of that position. For example, use FreezePanes(2, 1) to freeze the first row, FreezePanes(3, 1) to freeze the first two rows, and FreezePanes(2, 2) to freeze both the first row and the first column.
Querying the freeze pane range returns 0
Reason: The worksheet has not set any frozen panes, so the queried row and column indexes are 0.
Solution: Call the FreezePanes method to set frozen panes first, and then call GetFreezePanes to query the frozen range.
The freeze effect still shows after unfreezing panes
Reason: The workbook was not saved correctly after unfreezing, or the file opened is the one before the modification.
Solution: After calling the RemovePanes method, be sure to save the workbook with SaveToFile and open the output file to confirm the unfreeze effect.
Get a Free License
If you want to remove the evaluation message in the result documents or get rid of the feature limitations, please contact sales to obtain a 30-day temporary license.
Convert PDF to Images and Vice Versa with JavaScript in React
2026-08-13 02:44:20 Written by Nina TangImages are one of the most intuitive forms of content presentation and distribution, while PDF documents preserve the original layout and are widely used for the storage and transmission of formal files. When displaying PDF content on web pages, mini programs, social platforms, or emails, distributing PDF files directly is often inconvenient — converting them to image formats such as PNG or JPEG first enables quick preview and sharing. Conversely, consolidating scanned documents or image assets into PDF makes batch archiving and cross-platform distribution easier. Real-world business often requires flexible switching between the two forms: converting PDF contracts to images for online preview and quick sharing, or converting scanned image assets to PDF for unified archiving and circulation.
Spire.PDF for JavaScript performs bidirectional conversion between PDF and images entirely in the browser via WebAssembly, managing input and output files through a virtual file system (VFS) with no backend server required.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.PDF for JavaScript in a React Project. The examples below assume Spire.PDF is installed and the WebAssembly module is initialized.
Convert PDF to Image
The core of PDF-to-image conversion is to render the content, fonts, and graphics elements of every page in a PDF document into independent bitmap data. Spire.PDF for JavaScript generates an image stream for each page through the PdfDocument object's SaveAsImage method, loops through all Pages.Count pages and saves each page as a PNG image with stream.Save, then bundles the images into a ZIP file with JSZip for a one-click download, without needing to handle pixel and page coordinate mapping manually.
import JSZip from "jszip";
function App() {
const convertToImage = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check if the WASM module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load the PDF file and fonts into VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'Flowers.pdf';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Create PdfDocument object and load the PDF document
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// Create an output directory to hold the converted images
let outputDirectoryName = "ImagesFolders/";
window.dotnetRuntime.Module.FS.mkdirTree(outputDirectoryName);
// Loop through each page and save it as an image
for (let i = 0; i < doc.Pages.Count; i++) {
const outputFileName = outputDirectoryName + "ConvertedImages_" + i + ".png";
let stream = doc.SaveAsImage({ pageIndex: i });
stream.Save(outputFileName);
stream.Dispose();
}
doc.Dispose();
// Read the converted files from VFS and trigger download
const zip = new JSZip();
let items = await window.dotnetRuntime.Module.FS.readdir(outputDirectoryName);
items = items.filter((item) => item !== "."
&& item !== "..");
for (const item of items) {
const itemPath = `${outputDirectoryName}/${item}`;
const fileData = await window.dotnetRuntime.Module.FS.readFile(itemPath);
zip.file(item, fileData);
}
// Convert the ZIP to a Blob and trigger the browser download
const zipBlob = await zip.generateAsync({ type: "blob" });
const url = URL.createObjectURL(zipBlob);
const a = document.createElement('a');
a.href = url;
a.download = 'ImagesFolders';
a.click();
URL.revokeObjectURL(url);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Convert PDF To Image</h1>
<button onClick={convertToImage}>
Generate
</button>
</div>
);
}
export default App;
Each page of the PDF exported as a PNG image via SaveAsImage and bundled into a ZIP file for download

Adjust the DPI Resolution of Exported Images
When exporting images with the
SaveAsImagemethod, the default resolution is 96 DPI, which is suitable for screen preview, but text and lines may appear jagged or blurry when zoomed in. For sharper images, specify the resolution via thedpiXanddpiYparameters ofSaveAsImage, for example set it to 150 DPI:
// Export each page as an image at 150 DPI
for (let i = 0; i < doc.Pages.Count; i++) {
let stream = doc.SaveAsImage({ pageIndex: i, dpiX: 150, dpiY: 150 });
stream.Save(outputDirectoryName + "highres_" + i + ".png");
stream.Dispose();
}
The higher the DPI value, the sharper the exported image, but the larger the file size. Choose a balance between clarity and file size based on your actual use case.
Convert Image to PDF
Image-to-PDF conversion is commonly used to consolidate scanned documents or design assets into PDF for archiving. Spire.PDF for JavaScript creates a new document with the PdfDocument object, loads the image with the PdfImage.FromFile method, adds a page via Pages.Add, draws the image onto the page at its original size with the Canvas.DrawImage method, and finally saves it as a standard PDF with the SaveToFile method using the FileFormat.PDF enum value.
function App() {
const convertImageToPDF = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check if the WASM module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load the image file into VFS
const inputFileName = 'Scenery.png';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Create a PdfDocument object
let doc = new pdfModule.PdfDocument();
// Add a page
let page = doc.Pages.Add();
// Load the image
let image = pdfModule.PdfImage.FromFile(inputFileName);
// Calculate the scale ratio so the image fits the page completely
let widthFitRate = image.PhysicalDimension.Width / page.Canvas.ClientSize.Width;
let heightFitRate = image.PhysicalDimension.Height / page.Canvas.ClientSize.Height;
let fitRate = Math.max(widthFitRate, heightFitRate);
// Calculate the scaled dimensions of the image
let fitWidth = image.PhysicalDimension.Width / fitRate;
let fitHeight = image.PhysicalDimension.Height / fitRate;
// Draw the image onto the page
page.Canvas.DrawImage({ image: image, x: 0, y: 30, width: fitWidth, height: fitHeight });
const outputFileName = 'ImageToPDF.pdf';
// Save as PDF format
doc.SaveToFile({ fileName: outputFileName, fileFormat: pdfModule.FileFormat.PDF });
doc.Close();
// Read the converted file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
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>Convert Image To PDF</h1>
<button onClick={convertImageToPDF}>
Generate
</button>
</div>
);
}
export default App;
PDF document generated after loading an image via PdfImage.FromFile and drawing it with Canvas.DrawImage

Load Images from a Memory Stream
Besides loading directly from a file with
PdfImage.FromFile, images can also be loaded from a memory stream via thePdfImage.FromStreammethod. This approach suits scenarios where the image data comes from an API response or a database field, or where bytes need to be read before processing. See the code below:
// Read image bytes from VFS and build a memory stream
let bytes = window.dotnetRuntime.Module.FS.readFile(inputFileName);
let stream = new pdfModule.Stream(bytes);
// Load the image from the memory stream
let image = pdfModule.PdfImage.FromStream(stream);
The image can then be drawn onto a PDF page with the page.Canvas.DrawImage method and saved as a standard PDF using SaveToFile.
FAQ
Garbled text in the converted image
Reason: PDF relies on font embedding to ensure consistent cross-platform rendering. If the input PDF uses non-embedded fonts and the corresponding font files are not loaded in the VFS, text may appear garbled after conversion.
Solution: Make sure the required TrueType font files (e.g., ARIALUNI.TTF) are loaded into the /Library/Fonts/ directory in VFS before calling the conversion. ARIALUNI.TTF covers common CJK characters and is the recommended font for ensuring conversion quality.
Which image formats are supported for conversion?
Reason: Different business scenarios require different bitmap formats. For example, PNG is commonly used for web preview and JPEG for photos.
Solution: Spire.PDF for JavaScript can render PDF pages to common bitmap formats such as PNG, JPEG, and BMP. After generating the image stream with SaveAsImage, simply replace the file extension of the output file name with the target format (e.g., .jpg, .bmp, .png) in stream.Save to output the corresponding image format.
Get a Free License
If you want to remove the evaluation messages in the resulting documents or get rid of functional limitations, contact sales to obtain a 30-day temporary license.
XPS (XML Paper Specification) is a fixed-layout document format introduced by Microsoft, widely used in electronic document printing, archiving, and distribution scenarios, with native support in the Windows platform ecosystem. XPS describes document structure based on XML, offering advantages such as clear structure, easy validation, and digital signing. Meanwhile, PDF remains indispensable as an internationally recognized document format for cross-platform distribution. Real-world business often requires flexible switching between the two formats: converting existing PDF contracts to XPS for printing and archiving in Windows environments, or converting XPS documents to PDF for cross-platform distribution and collaboration.
Spire.PDF for JavaScript performs bidirectional conversion between PDF and XPS entirely in the browser via WebAssembly, managing input and output files through a virtual file system (VFS) with no backend server required.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.PDF for JavaScript in a React Project. The examples below assume Spire.PDF is installed and the WebAssembly module is initialized.
Convert PDF to XPS
The core of PDF-to-XPS conversion is to re-encode the page content, fonts, and graphics elements from a PDF document into an XML description structure compliant with the XPS standard. Spire.PDF for JavaScript accomplishes this in one step through the PdfDocument object's SaveToFile method with the FileFormat.XPS enum value, eliminating the need to handle underlying format differences manually.
function App() {
const convertToXPS = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check if the WASM module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load fonts and PDF file into VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'Reading_EN.pdf';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Create PdfDocument object and load the PDF document
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// Define the output file name for XPS format
const outputFileName = 'OutputXPS.xps';
// Save as XPS format
doc.SaveToFile({ fileName: outputFileName, fileFormat: pdfModule.FileFormat.XPS });
doc.Close();
// Read the converted file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/vnd.ms-xpsdocument' });
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>Convert PDF To XPS</h1>
<button onClick={convertToXPS}>
Generate
</button>
</div>
);
}
export default App;
XPS output generated after conversion via SaveToFile with FileFormat.XPS

Convert XPS to PDF
XPS-to-PDF conversion is a common requirement in document cross-platform distribution scenarios. Spire.PDF for JavaScript loads XPS fixed-layout documents through the PdfDocument object's LoadFromXPS method and then exports them as standard PDF files via the SaveToFile method with the FileFormat.PDF enum value, preserving the original document's layout and visual appearance.
function App() {
const convertXPSToPDF = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check if the WASM module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load the XPS file into VFS
const inputFileName = 'Lease_Agreement_EN.xps';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Create PdfDocument object and load the XPS document
let doc = new pdfModule.PdfDocument();
doc.LoadFromXPS(inputFileName);
// Define the output file name for PDF format
const outputFileName = 'OutputPDF.pdf';
// Save as PDF format
doc.SaveToFile({ fileName: outputFileName, fileFormat: pdfModule.FileFormat.PDF });
doc.Close();
// Read the converted file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
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>Convert XPS To PDF</h1>
<button onClick={convertXPSToPDF}>
Generate
</button>
</div>
);
}
export default App;
PDF document generated after loading XPS via the PdfDocument LoadFromXPS method and converting

FAQ
Can encrypted PDFs be converted to XPS?
Password-protected encrypted PDFs cannot be saved as XPS directly via SaveToFile — the document must be decrypted first.
Solution: Provide the password when loading the PDF via the second parameter of LoadFromFile, then save as XPS:
// Load a password-protected PDF document
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName, "password");
// Save as XPS format
doc.SaveToFile({ fileName: outputFileName, fileFormat: pdfModule.FileFormat.XPS });
doc.Close();
Get a Free License
If you want to remove the evaluation messages in the resulting documents or get rid of functional limitations, contact sales to obtain a 30-day temporary license.
Add, Preview, and Remove Excel Page Breaks with JavaScript in React
2026-08-12 06:20:20 Written by Lisa LiPage breaks are an important tool for controlling the print layout of Excel. They determine where data is divided across printed pages. Setting page breaks properly prevents data from being broken apart pointlessly when printing, resulting in clean, readable paper or PDF reports. Spire.XLS for JavaScript uses WebAssembly to add, preview, and remove page breaks directly in the browser, managing input and output files through a virtual file system (VFS) — no backend server required.
This article covers three core features:
For installation and project configuration, refer to Integrating Spire.XLS for JavaScript in a React Project. The examples below assume Spire.XLS is installed and the WebAssembly module is initialized.
Add Page Breaks
When printing reports, we often want to split data by a fixed number of rows and columns, for example printing a fixed number of data rows per page. Spire.XLS for JavaScript adds horizontal page breaks using the HPageBreaks.Add method and vertical page breaks using the VPageBreaks.Add method, enabling precise page break control.
function App() {
const sheetToSVG = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load fonts and the Excel file into VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'Template_Xls_4.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// Load the workbook
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
// Get the first worksheet
const sheet = workbook.Worksheets.get(0);
// Add a horizontal page break at row E4
sheet.HPageBreaks.Add(sheet.Range.get("E4"));
// Add a vertical page break at column C4
sheet.VPageBreaks.Add(sheet.Range.get("C4"));
const outputFileName = "AddPageBreakInXlsFile.xlsx";
workbook.SaveToFile({ fileName: outputFileName });
// Release the workbook object to free resources
workbook.Dispose();
// Read the converted file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
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 Page Break</h1>
<button onClick={sheetToSVG}>
Start
</button>
</div>
);
}
export default App;
Original document
Add page break 
Page Break View Zoom Scale Setting
When viewing page break positions in the view mode, Spire.XLS for JavaScript supports setting the zoom scale of the page break preview view through the ZoomScalePageBreakView property.
function App() {
const sheetToSVG = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load fonts and the Excel file into VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'Template_Xls_4.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// Load the workbook
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
// Get the first worksheet
const sheet = workbook.Worksheets.get(0);
// Set the zoom scale of the page break preview view
sheet.ZoomScalePageBreakView = 80;
const outputFileName = "PageBreakPreview.xlsx";
workbook.SaveToFile({ fileName: outputFileName });
// Release the workbook object to free resources
workbook.Dispose();
// Read the converted file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
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>Page Break Preview</h1>
<button onClick={sheetToSVG}>
Start
</button>
</div>
);
}
export default App;
Before setting the zoom scale
After setting the zoom scale 
Remove Page Breaks
When page breaks are no longer needed, you can clear all page breaks in a specific direction using the Clear method, or delete the page break at a specific position by index using the RemoveAt method. After removal, you can also switch the worksheet to the page break preview view via the ViewMode property to visually confirm the page break effect.
function App() {
const sheetToSVG = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load fonts and the Excel file into VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'PageBreak.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}/static/data/`);
// Load the workbook
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
// Get the first worksheet
const sheet = workbook.Worksheets.get(0);
// Clear all vertical page breaks
sheet.VPageBreaks.Clear();
// Remove the first horizontal page break
sheet.HPageBreaks.RemoveAt(0);
// Set the view mode to page break preview to check the page break effect
sheet.ViewMode = xlsModule.ViewMode.Preview;
const outputFileName = "RemovePageBreak_output.xlsx";
workbook.SaveToFile({ fileName: outputFileName });
// Release the workbook object to free resources
workbook.Dispose();
// Read the converted file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" });
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 Page Break</h1>
<button onClick={sheetToSVG}>
Start
</button>
</div>
);
}
export default App;
Before removing the page break
After removing the page break 
FAQ
Page breaks do not take effect when printing after being added
Cause: The page break was added to a blank area, or the worksheet has a fixed print zoom scale set, causing the actual page break positions during printing to differ from what was expected.
Solution: Confirm that the page break is added on the row or column of a cell containing data, and check the worksheet's print zoom settings. If necessary, adjust the zoom scale through properties such as ZoomScalePageBreakView so the page breaks take effect as expected.
Page break lines still display after removal
Cause: The worksheet is still in page break preview view mode, or there are automatic page breaks that are generated automatically based on the amount of data.
Solution: Automatic page breaks cannot be removed directly by programming; automatic page breaks are determined by the number of data rows, columns, and the page size. They can be eliminated by adjusting row heights, column widths, or the print zoom scale.
Get a Free License
If you want to remove the evaluation messages in the resulting documents, or get rid of functional limitations, please contact sales to obtain a temporary license valid for 30 days.
A pivot chart is a graphical representation of the summarized results of a pivot table, making data comparisons and trends immediately visible. It is an essential tool for data analysis and report presentation. Spire.XLS for JavaScript runs entirely in the browser via WebAssembly, using a virtual file system (VFS) to manage input and output files — no backend server required. It provides a complete API for creating pivot charts based on pivot tables, controlling the display of pivot chart field buttons, and customizing the appearance of pivot chart series.
This article covers three core features:
- Create a Pivot Chart in Excel
- Show or Hide Field Buttons of an Excel Pivot Chart
- Set the Format of Excel Pivot Chart Series
For installation and project setup, refer to Integrating Spire.XLS for JavaScript in a React Project. The examples below assume Spire.XLS is installed and the WebAssembly module is initialized.
Create a Pivot Chart in Excel
A pivot chart must be created based on a pivot table. With Spire.XLS for JavaScript, you can first create a pivot table in a worksheet, and then use the Charts.Add() method with the pivotChartType and pivotTable parameters to generate a corresponding pivot chart directly from the pivot table. The steps are as follows:
- Create a
Workbookobject and get the default worksheet. - Populate the worksheet with the source data required for the pivot table.
- Create a pivot table cache using
PivotCaches.Add(). - Add a pivot table using
PivotTables.Add(), and drag fields to the row area and the data area. - Add a chart using
sheet.Charts.Add(), and create a pivot chart based on the pivot table via thepivotChartTypeandpivotTableparameters. - Set the position and title of the pivot chart.
- Save the workbook to an Excel file using
SaveToFile().
Below is a complete code example demonstrating how to create a pivot chart based on a pivot table in React:
function App() {
const createPivotChart = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the font into the virtual file system (VFS)
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// Create a new workbook and get the default worksheet
const workbook = new xlsModule.Workbook();
let sheet = workbook.Worksheets.get(0);
// Populate the source data for the pivot table
sheet.Range.get('A1').Value = 'Product';
sheet.Range.get('B1').Value = 'Month';
sheet.Range.get('C1').Value = 'Sales';
sheet.Range.get('A2').Value = 'Apple';
sheet.Range.get('A3').Value = 'Apple';
sheet.Range.get('A4').Value = 'Banana';
sheet.Range.get('A5').Value = 'Apple';
sheet.Range.get('A6').Value = 'Banana';
sheet.Range.get('A7').Value = 'Banana';
sheet.Range.get('B2').Value = 'January';
sheet.Range.get('B3').Value = 'February';
sheet.Range.get('B4').Value = 'January';
sheet.Range.get('B5').Value = 'January';
sheet.Range.get('B6').Value = 'February';
sheet.Range.get('B7').Value = 'February';
sheet.Range.get('C2').Value = '10';
sheet.Range.get('C3').Value = '15';
sheet.Range.get('C4').Value = '9';
sheet.Range.get('C5').Value = '7';
sheet.Range.get('C6').Value = '8';
sheet.Range.get('C7').Value = '10';
// Create a pivot table
let dataRange = sheet.Range.get('A1:C7');
let cache = workbook.PivotCaches.Add({ range: dataRange });
let pivotTable = sheet.PivotTables.Add('Pivot Table', sheet.Range.get({ row: 1, column: 5 }), cache);
// Drag fields to the row area
let pf = pivotTable.PivotFields.get_Item('Product');
pf.Axis = xlsModule.AxisTypes.Row;
let pf2 = pivotTable.PivotFields.get_Item('Month');
pf2.Axis = xlsModule.AxisTypes.Row;
// Drag a field to the data area
pivotTable.DataFields.Add(pivotTable.PivotFields.get_Item('Sales'), 'Sum of Sales', xlsModule.SubtotalTypes.Sum);
// Set the pivot table style and calculate the data
pivotTable.BuiltInStyle = xlsModule.PivotBuiltInStyles.PivotStyleMedium12;
pivotTable.CalculateData();
// Create a clustered column chart based on the pivot table
let chart = sheet.Charts.Add({ pivotChartType: xlsModule.ExcelChartType.ColumnClustered, pivotTable: pivotTable });
// Set the pivot chart position
chart.TopRow = 9;
chart.LeftColumn = 1;
chart.RightColumn = 9;
chart.BottomRow = 25;
// Set the pivot chart title
chart.ChartTitle = "Pivot Chart";
// Save the workbook
const outputFileName = 'PivotChart.xlsx';
workbook.SaveToFile(outputFileName);
workbook.Dispose();
// 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.spreadsheetml.sheet' });
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>Create Pivot Chart</h1>
<button onClick={createPivotChart}>
Generate
</button>
</div>
);
}
export default App;
Pivot chart created in Excel with Spire.XLS for JavaScript

Show or Hide Field Buttons of an Excel Pivot Chart
By default, a pivot chart displays field buttons, allowing users to interactively filter and switch field data. When generating reports, you may want to hide some or all of the field buttons to make the chart cleaner. Spire.XLS for JavaScript provides properties such as DisplayEntireFieldButtons, DisplayValueFieldButtons, DisplayAxisFieldButtons, DisplayLegendFieldButtons, and ShowReportFilterFieldButtons to flexibly control the display of each type of field button. The steps are as follows:
- Create a
Workbookobject and load an existing Excel file containing a pivot chart. - Get the worksheet via
workbook.Worksheets.get(). - Get the pivot chart object using
sheet.Charts.get(). - Control whether to display all field buttons via
DisplayEntireFieldButtons. - Control the display of each type of field button via
DisplayValueFieldButtons,DisplayAxisFieldButtons,DisplayLegendFieldButtons, andShowReportFilterFieldButtons. - Save the workbook to an Excel file using
SaveToFile().
Below is a complete code example demonstrating how to show or hide pivot chart field buttons in React (the example loads the PivotChart.xlsx file generated in the previous section):
function App() {
const showHideFieldButtons = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the sample file containing a pivot chart into the virtual file system (VFS)
let excelFileName = 'PivotChart.xlsx';
await window.spire.FetchFileToVFS(excelFileName, '', `${process.env.PUBLIC_URL}data/`);
// Create a workbook object and load the existing file
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: excelFileName });
// Get the first worksheet
let sheet = workbook.Worksheets.get(0);
// Get the pivot chart
let chart = sheet.Charts.get(0);
// Control the display of all field buttons
chart.DisplayEntireFieldButtons = true;
// Hide the value field buttons
chart.DisplayValueFieldButtons = false;
// Hide the axis field buttons
chart.DisplayAxisFieldButtons = false;
// Hide the legend field buttons
//chart.DisplayLegendFieldButtons = false;
// Show the report filter field buttons
//chart.ShowReportFilterFieldButtons = true;
// Save the workbook
const outputFileName = 'PivotChartFieldButtons.xlsx';
workbook.SaveToFile(outputFileName);
workbook.Dispose();
// 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.spreadsheetml.sheet' });
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>Show/Hide PivotChart Field Buttons</h1>
<button onClick={showHideFieldButtons}>
Generate
</button>
</div>
);
}
export default App;
Pivot chart field buttons shown or hidden with Spire.XLS for JavaScript

Set the Format of Excel Pivot Chart Series
Formatting the series of a pivot chart can make the chart more visually appealing and clearly organized, conveying data information more effectively. With Spire.XLS for JavaScript, you can load an Excel file containing a pivot chart, get the pivot chart via the Charts.get() method, then set fill types, colors, and border styles via the series' DataFormat property, and set formats such as the gap width of the data bars via the format object returned by the GetCommonSerieFormat() method. The steps are as follows:
- Create a
Workbookobject. - Load an Excel file containing a pivot chart using the
LoadFromFile()method. - Get a specific worksheet in the Excel file using the
Worksheets.get()method. - Get the pivot chart in the worksheet using the
Charts.get()method. - Set the position and title of the pivot chart.
- Get the data series of the pivot chart using the
Series.get()method. - Set fill types, colors, and border styles via the
DataFormatproperty, and set formats such as the gap width of the data bars via theGetCommonSerieFormat()method. - Save the generated file using the
SaveToFile()method.
Below is a complete code example demonstrating how to set the format of pivot chart series in React (the example loads the PivotChart.xlsx file containing a pivot chart generated in the previous section):
function App() {
const formatPivotChartSeries = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the sample file containing a pivot table into the virtual file system (VFS)
let excelFileName = 'PivotChart.xlsx';
await window.spire.FetchFileToVFS(excelFileName, '', `${process.env.PUBLIC_URL}data/`);
// Create a Workbook object
const workbook = new xlsModule.Workbook();
// Load the Excel file
workbook.LoadFromFile({ fileName: excelFileName });
// Get the first worksheet
let sheet = workbook.Worksheets.get(0);
// Get the pivot chart
let chart = sheet.Charts.get(0);
// Set the pivot chart position
chart.TopRow = 1;
chart.LeftColumn = 8;
chart.RightColumn = 18;
chart.BottomRow = 15;
// Set the chart title
chart.ChartTitle = "";
// Add a series to the pivot chart
let series = chart.Series.get(0);
// Set the gap width of the data bars
series.GetCommonSerieFormat().GapWidth = 10;
// series.GetCommonSerieFormat().Overlap = 100;
// Set the fill type, foreground color, and background color of the series
series.DataFormat.Fill.FillType = xlsModule.ShapeFillType.SolidColor;
series.DataFormat.ForeGroundColor = xlsModule.Color.get_Red();
series.DataFormat.BackGroundColor = xlsModule.Color.get_White();
// Set the border color, line style, and line weight of the series
series.DataFormat.LineProperties.Pattern = xlsModule.ChartLinePatternType.Solid;
series.DataFormat.LineProperties.Color = xlsModule.Color.get_Blue();
series.DataFormat.LineProperties.CustomLineWeight = 2.5;
// Add a shadow effect to the series
series.DataFormat.IsShadow = true;
// Save the workbook
const outputFileName = 'PivotChartSeriesFormat.xlsx';
workbook.SaveToFile(outputFileName);
workbook.Dispose();
// 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.spreadsheetml.sheet' });
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 PivotChart Series</h1>
<button onClick={formatPivotChartSeries}>
Generate
</button>
</div>
);
}
export default App;
Pivot chart series format set with Spire.XLS for JavaScript

FAQ
How to refresh a pivot chart to show the latest data?
Cause: A pivot chart is created based on a pivot table. After modifying the data source of the pivot table, the chart does not automatically sync the updates.
Solution: After modifying the data source, use the Cache.IsRefreshOnLoad property to make the pivot table refresh automatically when the file opens, so the pivot chart is updated accordingly:
// Get the pivot table
let pivotTable = sheet.PivotTables.get(0);
// Refresh the pivot table automatically when the file opens
pivotTable.Cache.IsRefreshOnLoad = true;
Why does my pivot chart not show any data?
Cause: The series of a pivot chart come from the summarized results of a pivot table. If the pivot table has not been calculated, or the pivot chart was not correctly associated with the pivot table, the chart may appear blank.
Solution: Call the CalculateData() method after creating the pivot table to calculate the results, and correctly associate the pivot table via the pivotTable parameter when creating the pivot chart:
// Calculate the data of the pivot table
pivotTable.CalculateData();
// Create a pivot chart based on the pivot table
let chart = sheet.Charts.Add({ pivotChartType: xlsModule.ExcelChartType.ColumnClustered, pivotTable: pivotTable });
Get a Free License
Spire.XLS for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Extract and Replace Images in Excel with JavaScript in React
2026-08-07 07:55:22 Written by zaki zakiIn office automation workflows, you often need to batch-extract product images from Excel reports, replace outdated logos, or export a specific image individually. Spire.XLS for JavaScript handles all of these image operations directly in the browser via WebAssembly, using a virtual file system (VFS) to manage input and output files — no backend server is required.
This article covers three core features:
- Extract All Images from a Worksheet
- Extract a Specific Image
- Replace an Existing Image in a Worksheet
For installation and project setup, refer to Integrating Spire.XLS for JavaScript in a React Project. The examples below assume Spire.XLS is installed and the WebAssembly module is initialized.
Extract All Images from a Worksheet
Batch-extracting all images from a worksheet is useful for backing up embedded images in reports, migrating product materials, and similar scenarios. The process consists of three steps: iterate over the Worksheet.Pictures collection, call the Picture.Save method on each image to save it to the VFS, then read each file and trigger a browser download.
function App() {
const extractAllImages = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the Excel file into VFS
const inputFileName = 'ReadImages.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// Load the workbook and get the first worksheet
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
const sheet = workbook.Worksheets.get(0);
// Iterate through all pictures in the worksheet and export each one
for (let i = 0; i < sheet.Pictures.Count; i++) {
const pic = sheet.Pictures.get(i);
const outputFileName = `Image-${i + 1}.png`;
pic.Picture.Save(outputFileName);
// Read the exported image file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: "image/png" });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
}
// Release resources
workbook.Dispose();
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Extract All Images from Worksheet</h1>
<button onClick={extractAllImages}>
Extract All Images
</button>
</div>
);
}
export default App;
Image files extracted and downloaded from the worksheet in batch

Extract a Specific Image
There are two common ways to extract a specific image from a worksheet: retrieve it directly by index, or iterate through pictures by name to find a match. The index approach suits scenarios where the picture position is known (for example, the first picture), while the name approach is better when you know the picture identifier in advance. The process consists of two steps: first locate the target image by index or name, then export it as a local file.
function App() {
const extractImage = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the Excel file into VFS
const inputFileName = 'ReadImages.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// Load the workbook and get the first worksheet
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
const sheet = workbook.Worksheets.get(0);
// Method 1: Extract by index (e.g., extract the second picture)
const pic = sheet.Pictures.get(1);
const outputFileName = 'ExtractByIndex.png';
// // Method 2: Iterate through pictures by name to find a match
// let pic = null;
// const targetName = 'SpireXLS';
// for (let i = 0; i < sheet.Pictures.Count; i++) {
// if (sheet.Pictures.get(i).Name === targetName) {
// pic = sheet.Pictures.get(i);
// break;
// }
// }
// const outputFileName = 'ExtractByName.png';
// Save the picture to VFS and trigger download
pic.Picture.Save(outputFileName);
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: "image/png" });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = outputFileName;
a.click();
URL.revokeObjectURL(url);
workbook.Dispose();
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Extract a Specific Image</h1>
<button onClick={extractImage}>
Extract Image
</button>
</div>
);
}
export default App;
Specific image extracted and downloaded by index or name

Replace an Existing Image in a Worksheet
Replacing an existing image in a worksheet is a common requirement when updating report logos, changing product display images, and in similar scenarios. The approach is to first retrieve the position and size information of the target image, then delete it via XlsShape.Convert, and finally insert a new image at the same position, setting the new image's size and offsets to match the original.
function App() {
const replaceImage = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the Excel file and the new image into VFS
const inputFileName = 'ReadImages.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
const newImageFile = 'Logo.png';
await window.spire.FetchFileToVFS(newImageFile, '', `${process.env.PUBLIC_URL}data/`);
// Load the workbook and get the first worksheet
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
const sheet = workbook.Worksheets.get(0);
// Get the first picture and its position and size information
const oldPic = sheet.Pictures.get(0);
const topRow = oldPic.TopRow;
const leftColumn = oldPic.LeftColumn;
const leftColumnOffset = oldPic.LeftColumnOffset;
const topRowOffset = oldPic.TopRowOffset;
const width = oldPic.Width;
const height = oldPic.Height;
// Delete the original picture
xlsModule.XlsShape.Convert(oldPic).Remove();
// Insert the new picture at the same position
let picture = sheet.Pictures.Add({ topRow: topRow, leftColumn: leftColumn, fileName: newImageFile });
// Set the new picture's size and offsets to match the original
picture.Width = width;
picture.Height = height;
picture.LeftColumnOffset = leftColumnOffset;
picture.TopRowOffset = topRowOffset;
const outputFileName = 'ReplaceImage-out.xlsx';
// Save the modified workbook
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
// Release resources
workbook.Dispose();
// 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.spreadsheetml.sheet" });
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 Image in Worksheet</h1>
<button onClick={replaceImage}>
Replace Image
</button>
</div>
);
}
export default App;
The Excel worksheet after the image is replaced

FAQ
Extracted images cannot be opened or the format is incorrect
Cause: The correct file extension was not specified when saving the image, or the MIME type does not match the image format.
Solution: Make sure the file extension used in the Picture.Save method matches the actual image format. If the image is in PNG format, the file extension should be .png; if it is in JPEG format, use .jpg. The Blob type used for the download should be set accordingly:
// PNG format
const blob = new Blob([fileArray], { type: "image/png" });
// JPEG format
const blob = new Blob([fileArray], { type: "image/jpeg" });
The position or size of the image changes after replacement
Cause: The position and size properties of the original image were not recorded before deletion, so the new image cannot be precisely aligned to the original position or retain its original size.
Solution: Save the position properties such as TopRow, LeftColumn, LeftColumnOffset, TopRowOffset and the size properties Width, Height before deleting the image. After inserting the new image, set these properties on the new picture so it matches the original:
// Insert the new picture (specify the row and column position)
let picture = sheet.Pictures.Add({ topRow: topRow, leftColumn: leftColumn, fileName: newImageFile });
// Set size and offsets to match the original
picture.Width = width;
picture.Height = height;
picture.LeftColumnOffset = leftColumnOffset;
picture.TopRowOffset = topRowOffset;
Get a Free License
Spire.XLS for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
OFD (Open Fixed-layout Document) is a national standard fixed-layout document format widely used in e-invoices, e-certificates, administrative approvals, and other government and financial scenarios. OFD describes document structure based on XML, offering advantages such as independent control and information security. Meanwhile, PDF remains indispensable as an internationally recognized document format for cross-platform distribution. Real-world business often requires flexible switching between the two formats: receiving OFD-format e-invoices and converting them to PDF for printing and distribution, or converting existing PDF contracts to OFD to meet government platform upload requirements.
Spire.PDF for JavaScript performs bidirectional conversion between PDF and OFD entirely in the browser via WebAssembly, managing input and output files through a virtual file system (VFS) with no backend server required.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.PDF for JavaScript in a React Project. The examples below assume Spire.PDF is installed and the WebAssembly module is initialized.
Convert PDF to OFD
The core of PDF-to-OFD conversion is to re-encode the page content, fonts, and graphics elements from a PDF document into an XML description structure compliant with the OFD standard. Spire.PDF for JavaScript accomplishes this in one step through the PdfDocument object's SaveToFile method with the FileFormat.OFD enum value, eliminating the need to handle underlying format differences manually.
function App() {
const convertToOFD = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check if the WASM module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load fonts and PDF file into VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'TemplateIntroduction-en.pdf';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Create PdfDocument object and load the PDF document
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName);
// Define the output file name for OFD format
const outputFileName = 'OutputOFD.ofd';
// Save as OFD format
doc.SaveToFile({ fileName: outputFileName, fileFormat: pdfModule.FileFormat.OFD });
doc.Close();
// Read the converted file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/ofd' });
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>Convert PDF To OFD</h1>
<button onClick={convertToOFD}>
Generate
</button>
</div>
);
}
export default App;
OFD output generated after conversion via SaveToFile with FileFormat.OFD

Convert OFD to PDF
OFD-to-PDF conversion is a common requirement in government electronic document distribution scenarios. Spire.PDF for JavaScript provides the OfdConverter component, which is specifically designed to parse OFD fixed-layout documents and export them as standard PDF files while preserving the original document's layout and visual appearance.
function App() {
const convertOFDToPDF = async () => {
// Get the Spire.PDF WASM module
const pdfModule = window.wasmModule?.spirepdf;
// Check if the WASM module is ready
if (!pdfModule) {
alert('Spire.PDF is not ready yet');
return;
}
// Load fonts and OFD file into VFS
await window.spire.FetchFileToVFS('Arial.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'Invoice_EN.ofd';
await window.spire.FetchFileToVFS(inputFileName, "", `${process.env.PUBLIC_URL}/data/`);
// Create OfdConverter object and pass the OFD file path
let converter = new pdfModule.OfdConverter(inputFileName);
// Define the output file name for PDF format
const outputFileName = 'OutputPDF.pdf';
// Convert to PDF format
converter.ToPdf(outputFileName);
converter.Dispose();
// Read the converted file from VFS and trigger download
const fileArray = window.dotnetRuntime.Module.FS.readFile(outputFileName);
const blob = new Blob([fileArray], { type: 'application/pdf' });
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>Convert OFD To PDF</h1>
<button onClick={convertOFDToPDF}>
Generate
</button>
</div>
);
}
export default App;
Standard PDF output generated after conversion via OfdConverter

FAQ
Can encrypted PDFs be converted to OFD?
Password-protected encrypted PDFs cannot be saved as OFD directly via SaveToFile — the document must be decrypted first.
Solution: Provide the password when loading the PDF via the second parameter of LoadFromFile, then save as OFD:
// Load a password-protected PDF document
let doc = new pdfModule.PdfDocument();
doc.LoadFromFile(inputFileName, "password");
// Save as OFD format
doc.SaveToFile({ fileName: outputFileName, fileFormat: pdfModule.FileFormat.OFD });
doc.Close();
Garbled text in the converted OFD document
OFD relies on font embedding to ensure consistent cross-platform rendering. If the input PDF uses non-embedded fonts and the corresponding font files are not loaded in the VFS, text may appear garbled after conversion.
Solution: Make sure the required TrueType font files (e.g., ARIALUNI.TTF) are loaded into the /Library/Fonts/ directory in VFS before calling the conversion. ARIALUNI.TTF covers common CJK characters and is the recommended font for ensuring conversion quality.
Get a Free License
Spire.PDF for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Data labels are an essential element of Excel charts for displaying detailed information about data points, such as values, series names, and category names. Spire.XLS for JavaScript runs entirely in the browser via WebAssembly, using a virtual file system (VFS) to manage input and output files — no backend server required. It provides a complete API for controlling data label display content, font formatting, number format, position, background, borders, and other appearance properties.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.XLS for JavaScript in a React Project. The examples below assume Spire.XLS is installed and the WebAssembly module is initialized.
Set Data Label Content and Font
Data labels can display various types of information, including values, series names, category names, and legend keys. With Spire.XLS for JavaScript, you can flexibly control the display content of data labels and customize their font styles to make the chart information clearer and more readable. The steps are as follows:
- Create a
Workbookobject and get the default worksheet. - Populate the worksheet with category labels and numeric data for the chart.
- Add a chart using
sheet.Charts.Add()and set the chart type. - Configure the chart's data range, position, and title.
- Enable data label display content (values, series names, category names) via the
DataLabelsproperty. - Set data label font properties (font name, size, color, bold, etc.).
- Save the workbook to an Excel file using
SaveToFile().
Below is a complete code example demonstrating how to set chart data label content and font in React:
function App() {
const setDataLabelContentAndFont = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Create a new workbook and get the default worksheet
const workbook = new xlsModule.Workbook();
let sheet = workbook.Worksheets.get(0);
sheet.Name = "DataLabelDemo";
// Populate chart data
sheet.Range.get("A1").Value = "Month";
sheet.Range.get("A2").Value = "Jan";
sheet.Range.get("A3").Value = "Feb";
sheet.Range.get("A4").Value = "Mar";
sheet.Range.get("A5").Value = "Apr";
sheet.Range.get("A6").Value = "May";
sheet.Range.get("A7").Value = "Jun";
sheet.Range.get("B1").Value = "Sales";
sheet.Range.get("B2").NumberValue = 25;
sheet.Range.get("B3").NumberValue = 18;
sheet.Range.get("B4").NumberValue = 8;
sheet.Range.get("B5").NumberValue = 13;
sheet.Range.get("B6").NumberValue = 22;
sheet.Range.get("B7").NumberValue = 28;
// Add a line chart and set its data range
let chart = sheet.Charts.Add({ chartType: xlsModule.ExcelChartType.LineMarkers });
chart.DataRange = sheet.Range.get("B1:B7");
chart.SeriesDataFromRange = false;
// Set the chart position
chart.TopRow = 5;
chart.BottomRow = 26;
chart.LeftColumn = 2;
chart.RightColumn = 11;
// Configure chart title
chart.ChartTitle = "Data Labels Demo";
chart.ChartTitleArea.IsBold = true;
chart.ChartTitleArea.Size = 12;
// Bind category labels
let cs1 = chart.Series.get(0);
cs1.CategoryLabels = sheet.Range.get("A2:A7");
// Set data label display content: show values, series names, and category names
cs1.DataPoints.DefaultDataPoint.DataLabels.HasValue = true;
cs1.DataPoints.DefaultDataPoint.DataLabels.HasSeriesName = true;
cs1.DataPoints.DefaultDataPoint.DataLabels.HasCategoryName = true;
// Set data label delimiter
cs1.DataPoints.DefaultDataPoint.DataLabels.Delimiter = ". ";
// Customize data label font styles
cs1.DataPoints.DefaultDataPoint.DataLabels.Size = 9;
cs1.DataPoints.DefaultDataPoint.DataLabels.Color = xlsModule.Color.get_Red();
cs1.DataPoints.DefaultDataPoint.DataLabels.FontName = "Calibri";
cs1.DataPoints.DefaultDataPoint.DataLabels.IsBold = true;
// Save the workbook
const outputFileName = 'DataLabelContentAndFont.xlsx';
workbook.SaveToFile(outputFileName);
workbook.Dispose();
// 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.spreadsheetml.sheet' });
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 Data Label Content and Font</h1>
<button onClick={setDataLabelContentAndFont}>
Generate
</button>
</div>
);
}
export default App;
Data label content and font set with Spire.XLS for JavaScript

Adjust Data Label Position and Appearance
Beyond display content and font styles, the position and appearance of data labels are also important aspects of chart visual enhancement. Spire.XLS for JavaScript supports adjusting the display position of data labels through the DataLabelPositionType enumeration, and allows you to set fill colors, border styles, and shadow effects for data labels. The steps are as follows:
- Create a
Workbookobject and load an existing Excel file containing a chart. - Get the worksheet via
workbook.Worksheets.get(). - Get the chart object using
sheet.Charts.get(). - Iterate through the chart's data series and set the data label position using
DataLabels.Position. - Set a background fill color for the data labels via
FrameFormat.Fill. - Set border color and style for the data labels via
FrameFormat.Border. - Add shadow effects to data labels via
FrameFormat.Shadow(type, color, transparency, size, blur, angle, and distance). - Save the workbook to an Excel file using
SaveToFile().
Below is a complete code example demonstrating how to adjust chart data label position and appearance in React:
function App() {
const setDataLabelPositionAndAppearance = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the sample file into the virtual file system (VFS)
let excelFileName = 'SampleChart.xlsx';
await window.spire.FetchFileToVFS(excelFileName, '', `${process.env.PUBLIC_URL}data/`);
// Create a workbook object and load the existing file
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: excelFileName });
// Get the first worksheet
let sheet = workbook.Worksheets.get(0);
// Get the first chart
let chart = sheet.Charts.get(0);
// Iterate through all data series and adjust data label position and appearance
for (let i = 0; i < chart.Series.Count; i++) {
let cs = chart.Series.get(i);
// Set data point marker style and size to make data points more prominent
cs.DataFormat.MarkerSize = 6;
cs.DataFormat.MarkerStyle = xlsModule.ChartMarkerType.Circle;
cs.DataFormat.MarkerForegroundColor = xlsModule.Color.get_Blue();
cs.DataFormat.MarkerBackgroundColor = xlsModule.Color.get_White();
let dataLabels = cs.DataPoints.DefaultDataPoint.DataLabels;
// Enable value labels
dataLabels.HasValue = true;
// Set data label position
dataLabels.Position = xlsModule.DataLabelPositionType.Right;
// Set data label font color and size
dataLabels.Color = xlsModule.Color.get_Blue();
dataLabels.Size = 10;
// Set pink fill background
dataLabels.FrameFormat.Fill.FillType = xlsModule.ShapeFillType.SolidColor;
dataLabels.FrameFormat.ForeGroundColor = xlsModule.Color.get_Pink();
// Set red border
dataLabels.FrameFormat.Border.Pattern = xlsModule.ChartLinePatternType.Solid;
dataLabels.FrameFormat.Border.Color = xlsModule.Color.get_Red();
// Set yellow shadow effect
dataLabels.FrameFormat.Shadow.ShadowOuterType = xlsModule.XLSXChartShadowOuterType.OffsetDiagonalBottomLeft;
dataLabels.FrameFormat.Shadow.Color = xlsModule.Color.get_Yellow();
dataLabels.FrameFormat.Shadow.Transparency = 0;
dataLabels.FrameFormat.Shadow.Size = 10;
dataLabels.FrameFormat.Shadow.Blur = 2;
dataLabels.FrameFormat.Shadow.Angle = 45;
dataLabels.FrameFormat.Shadow.Distance = 8;
}
// Save the workbook
const outputFileName = 'DataLabelPositionAndAppearance.xlsx';
workbook.SaveToFile(outputFileName);
workbook.Dispose();
// 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.spreadsheetml.sheet' });
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 Data Label Position and Appearance</h1>
<button onClick={setDataLabelPositionAndAppearance}>
Generate
</button>
</div>
);
}
export default App;
Data label position and appearance adjusted with Spire.XLS for JavaScript

FAQ
How to modify the label content of a specific data point instead of the entire series?
Cause: DefaultDataPoint.DataLabels applies to all data points in a series and cannot control individual data points separately.
Solution: Use DataPoints.get(index) to access a specific data point and set its label:
// Modify the label text of the third data point
chart.Series.get(0).DataPoints.get(2).DataLabels.Text = "Peak";
chart.Series.get(0).DataPoints.get(2).DataLabels.HasValue = false;
How to set number format for data labels (decimal places, currency symbols)
Cause: The number format of data labels matches the cell format by default, but sometimes needs to be controlled independently.
Solution: Use the DataLabels.NumberFormat property to customize the number format:
// Show two decimal places
dataLabels.NumberFormat = "0.00";
// Display as percentage
dataLabels.NumberFormat = "0.0%";
// Display with currency symbol
dataLabels.NumberFormat = "$#,##0";
Get a Free License
Spire.XLS for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.
Convert Excel to TXT or TXT to Excel with JavaScript in React
2026-08-03 02:29:40 Written by zaki zakiIn daily office work, data often needs to be exchanged between Excel spreadsheets and plain text (TXT) files. Spire.XLS for JavaScript runs entirely in the browser via WebAssembly, using a virtual file system (VFS) to manage input and output files — no backend server is required. It provides flexible APIs for controlling conversion parameters such as delimiters and encoding formats.
With Spire.XLS for JavaScript, you can export Excel worksheet data as structured text files, or import delimited text files to create fully formatted Excel workbooks. This makes data migration between different applications more convenient and efficient.
This article covers two core features:
For installation and project setup, refer to Integrating Spire.XLS for JavaScript in a React Project. The examples below assume Spire.XLS is installed and the WebAssembly module is initialized.
Convert Excel Worksheet Data to TXT
Exporting Excel data as a plain text file makes it convenient for further processing or analysis in other applications. With Spire.XLS for JavaScript, you can save the contents of a specified worksheet as a TXT file, with flexible control over the field separator and character encoding. The steps are as follows:
- Create a
Workbookobject and load an existing Excel file. - Retrieve a specific worksheet via
workbook.Worksheets.get(index). - Call the worksheet's
SaveToFile()method, specifying the output filename, separator, and encoding. - Dispose of the workbook resources, read the result file from VFS, and trigger the download.
Below is a complete code example demonstrating how to convert Excel to TXT in React:
function App() {
const convertToText = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the sample file into VFS
await window.spire.FetchFileToVFS('Sample.xlsx', '', `${process.env.PUBLIC_URL}data/`);
// Create a workbook object and load the Excel file
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: 'Sample.xlsx' });
// Get the first worksheet
let sheet = workbook.Worksheets.get(0);
// Save the worksheet as a TXT file with space separator and UTF-8 encoding
const outputFileName = 'ExcelToTxt.txt';
sheet.SaveToFile({
fileName: outputFileName,
separator: " ",
encoding: xlsModule.Encoding.get_UTF8()
});
workbook.Dispose();
// Read the file from VFS and trigger download
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);
};
return (
<div style={{ textAlign: 'center', height: '300px' }}>
<h1>Convert Excel to TXT</h1>
<button onClick={convertToText}>
Generate
</button>
</div>
);
}
export default App;
Excel converted to TXT with Spire.XLS for JavaScript

Convert TXT File to Excel Workbook
Importing a delimited text file into an Excel spreadsheet allows you to take full advantage of Excel's formatting, calculation, and charting capabilities. Spire.XLS for JavaScript supports TXT-to-Excel conversion by reading the text file content and writing data to the workbook cell by cell. Formatting such as bold headers can also be applied during the process. The steps are as follows:
- Load the font file and TXT sample file into the VFS.
- Read the TXT file content from VFS, split it by lines, and parse the cell data for each line.
- Create a
Workbookobject, iterate through the data array, and write data to worksheet cells row by row and column by column. - Apply bold styling to the header row and call
AllocatedRange.AutoFitColumns()to auto-fit column widths. - Save the workbook as an Excel file and trigger the download.
Below is a complete code example demonstrating how to convert TXT to Excel in React:
function App() {
const convertToExcel = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check if the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the font file to ensure proper text rendering
await window.spire.FetchFileToVFS('ARIAL.TTF', '', `${process.env.PUBLIC_URL}font/`);
// Load the TXT file into VFS
await window.spire.FetchFileToVFS('Sample.txt', '', `${process.env.PUBLIC_URL}data/`);
// Read the text file content from VFS
const txtData = window.dotnetRuntime.Module.FS.readFile('Sample.txt');
const text = typeof txtData === 'string' ? txtData : new TextDecoder('utf-8').decode(txtData);
// Split by lines, compatible with \r\n and \n
const lines = text.trim().split(/\r?\n/);
// Parse each line of data (try tab delimiter first, then fallback to other delimiters)
const data = [];
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed) continue;
let cells = trimmed.split('\t');
if (cells.length === 1) {
cells = trimmed.split(/\s+/);
}
data.push(cells);
}
// Create a Workbook object
const workbook = new xlsModule.Workbook();
// Get the first worksheet
const sheet = workbook.Worksheets.get(0);
// Iterate through rows and columns in the data array and write to cells
for (let row = 0; row < data.length; row++) {
for (let col = 0; col < data[row].length; col++) {
const cell = sheet.get_Item(row + 1, col + 1);
cell.Value = data[row][col];
// Bold the header row
if (row === 0) {
cell.Style.Font.IsBold = true;
}
}
}
// Auto-fit column widths
sheet.AllocatedRange.AutoFitColumns();
// Save the workbook and release resources
const outputFileName = 'TxtToExcel.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
workbook.Dispose();
// 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.spreadsheetml.sheet' });
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>Convert TXT to Excel</h1>
<button onClick={convertToExcel}>
Generate
</button>
</div>
);
}
export default App;
TXT converted to Excel with Spire.XLS for JavaScript

FAQ
How to handle encoding issues during conversion?
Cause: The TXT file in this example uses UTF-8 encoding. If the TXT file uses a different encoding format (such as GBK, GB2312, etc.), decoding it directly with TextDecoder('utf-8') will result in garbled text.
Solution: Specify the corresponding encoding type in the TextDecoder constructor parameter based on the actual encoding of the TXT file:
// UTF-8 encoding
const text = new TextDecoder('utf-8').decode(txtData);
// GBK encoding
const text = new TextDecoder('gbk').decode(txtData);
// GB2312 encoding
const text = new TextDecoder('gb2312').decode(txtData);
// UTF-16 encoding
const text = new TextDecoder('utf-16').decode(txtData);
How to handle TXT files with different delimiters?
Cause: TXT files may use different delimiters such as tabs (\t), spaces, commas (,), semicolons (;), etc. Choosing the wrong delimiter can lead to data parsing errors.
Solution: In JavaScript, you can specify different delimiters by modifying the parameter of the split() method:
// Tab delimiter
let cells = trimmed.split('\t');
// Comma delimiter
let cells = trimmed.split(',');
// Semicolon delimiter
let cells = trimmed.split(';');
// Regular expression: split by one or more whitespace characters (spaces, tabs, etc.)
let cells = trimmed.split(/\s+/);
Get a Free License
Spire.XLS for JavaScript offers a 30-day full-featured free trial license with no functional limitations. Apply here to evaluate before purchasing.