When creating flowcharts, relationship diagrams, or data annotations, inserting lines into an Excel worksheet is a common requirement. Spire.XLS for JavaScript provides rich line APIs for creating various line types (straight lines, curved lines, elbow connectors, etc.) and arrow-tipped connectors. All operations are performed directly in the browser based on WebAssembly, with no backend service required.

This article covers two 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.


Insert Different Types of Lines

The sheet.Lines.AddLine() method inserts line shapes at a specified position. Using the LineShapeType enum, you can create various line types: straight lines (Line), curved lines (CurveLine), elbow connectors (ElbowLine), and inverted lines (LineInv). The appearance of lines can be customized through properties such as DashStyle (dash style), Color (color), and Weight (thickness).

The main steps are as follows:

  1. Create a Workbook object and get the first worksheet.
  2. Call the Worksheet.Lines.AddLine() method, passing position parameters and LineShapeType to specify the line type.
  3. Customize line appearance through the DashStyle, Color, Weight, and EndArrowHeadStyle properties.
  4. Save the workbook with the Workbook.SaveToFile() method.

Here is a complete code example showing how to insert four different types of lines into Excel in React:

function App() {
  const addLineShapes = 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 into the VFS for text measurement and column auto-fit
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);

    // Create a new workbook and get the first worksheet
    const workbook = new xlsModule.Workbook();
    const sheet = workbook.Worksheets.get(0);

    // Add a straight line - solid, CadetBlue, weight 2, with arrow
    let line1 = sheet.Lines.AddLine({ row: 10, column: 2, width: 200, height: 1, lineShapeType: xlsModule.LineShapeType.Line });
    line1.DashStyle = xlsModule.ShapeDashLineStyleType.Solid;
    line1.Color = xlsModule.Color.get_CadetBlue();
    line1.Weight = 2;
    line1.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;

    // Add a curved line - dotted, OrangeRed, weight 2
    let line2 = sheet.Lines.AddLine({ row: 12, column: 2, width: 200, height: 1, lineShapeType: xlsModule.LineShapeType.CurveLine });
    line2.DashStyle = xlsModule.ShapeDashLineStyleType.Dotted;
    line2.Color = xlsModule.Color.get_OrangeRed();
    line2.Weight = 2;

    // Add an elbow connector - DashDotDot, Purple, weight 2
    let line3 = sheet.Lines.AddLine({ row: 14, column: 2, width: 200, height: 1, lineShapeType: xlsModule.LineShapeType.ElbowLine });
    line3.DashStyle = xlsModule.ShapeDashLineStyleType.DashDotDot;
    line3.Color = xlsModule.Color.get_Purple();
    line3.Weight = 2;

    // Add an inverted line - Dashed, Green, weight 2
    let line4 = sheet.Lines.AddLine({ row: 16, column: 2, width: 200, height: 1, lineShapeType: xlsModule.LineShapeType.LineInv });
    line4.DashStyle = xlsModule.ShapeDashLineStyleType.Dashed;
    line4.Color = xlsModule.Color.get_Green();
    line4.Weight = 2;

    // Save the workbook
    const outputFileName = 'AddLineShapes.xlsx';
    workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    workbook.Dispose();

    // Read the saved 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>Add Line Shapes</h1>
      <button onClick={addLineShapes}>Start</button>
    </div>
  );
}

export default App;

Effect of inserting different line types:

Insert different types of lines


Insert Arrow-Tipped Lines

The sheet.TypedLines.AddLine() method inserts arrow-tipped lines. Unlike Lines.AddLine(), TypedLines supports precise positioning using pixel coordinates or row/column coordinates, and supports setting different arrow head styles on both ends (beginning BeginArrowHeadStyle and end EndArrowHeadStyle).

The main steps are as follows:

  1. Create a Workbook object and get the first worksheet.
  2. Call the Worksheet.TypedLines.AddLine() method to create a line.
  3. Set line position through the Top, Left, Width, and Height properties (in pixels).
  4. Set arrow styles on both ends through BeginArrowHeadStyle and EndArrowHeadStyle.
  5. Specify the line type through LineShapeType (straight, elbow, curved, etc.).
  6. Save the workbook with the Workbook.SaveToFile() method.

Here is a complete code example showing how to insert six different types of arrow lines into Excel in React:

function App() {
  const addArrowLines = 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 into the VFS for text measurement and column auto-fit
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);

    // Create a new workbook and get the first worksheet
    const workbook = new xlsModule.Workbook();
    const sheet = workbook.Worksheets.get(0);

    // Add a double-arrow line - solid blue
    let line = sheet.TypedLines.AddLine();
    line.Top = 10;
    line.Left = 20;
    line.Width = 100;
    line.Height = 0;
    line.Color = xlsModule.Color.get_Blue();
    line.BeginArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;
    line.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;

    // Add a single-arrow line - solid red
    let line_1 = sheet.TypedLines.AddLine();
    line_1.Top = 50;
    line_1.Left = 30;
    line_1.Width = 100;
    line_1.Height = 100;
    line_1.Color = xlsModule.Color.get_Red();
    line_1.BeginArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineNoArrow;
    line_1.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;

    // Add an elbow arrow connector
    let line3 = sheet.TypedLines.AddLine();
    line3.LineShapeType = xlsModule.LineShapeType.ElbowLine;
    line3.Width = 30;
    line3.Height = 50;
    line3.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;
    line3.Top = 100;
    line3.Left = 50;

    // Add an elbow double-arrow connector
    let line2 = sheet.TypedLines.AddLine();
    line2.LineShapeType = xlsModule.LineShapeType.ElbowLine;
    line2.Width = 50;
    line2.Height = 50;
    line2.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;
    line2.BeginArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrow;
    line2.Left = 120;
    line2.Top = 100;

    // Add a curved arrow connector
    line3 = sheet.TypedLines.AddLine();
    line3.LineShapeType = xlsModule.LineShapeType.CurveLine;
    line3.Width = 30;
    line3.Height = 50;
    line3.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrowOpen;
    line3.Top = 100;
    line3.Left = 200;

    // Add a curved double-arrow connector
    line2 = sheet.TypedLines.AddLine();
    line2.LineShapeType = xlsModule.LineShapeType.CurveLine;
    line2.Width = 30;
    line2.Height = 50;
    line2.EndArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrowOpen;
    line2.BeginArrowHeadStyle = xlsModule.ShapeArrowStyleType.LineArrowOpen;
    line2.Left = 250;
    line2.Top = 100;

    // Save the workbook
    const outputFileName = 'AddArrowLines.xlsx';
    workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    workbook.Dispose();

    // Read the saved 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>Add Arrow Lines</h1>
      <button onClick={addArrowLines}>Start</button>
    </div>
  );
}

export default App;

Effect of inserting arrow-tipped lines:

Insert arrow-tipped lines


Frequently Asked Questions

How do I retrieve and modify existing lines in a worksheet?

Reason: An Excel file with existing lines was imported, but it's unclear how to read or modify them.

Solution: Traverse the sheet.Shapes collection to retrieve line shape objects, then modify their properties via the ILineShape interface. For example, sheet.Shapes.get(0) gets the first shape, and after confirming it's a line type, you can modify properties like color, dash style, etc.

How do I delete lines from an Excel worksheet?

Reason: Need to remove excess lines that were created or imported.

Solution: Use sheet.Shapes.Remove(index) to delete a line object at a specified index from the shapes collection, or iterate through the Shapes collection to delete them one by one based on name or type conditions.


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.

Pie charts and doughnut charts are the most intuitive chart types for showing the proportion of each data item. An exploded pie chart or exploded doughnut chart pulls all the slices apart, which makes every part stand out more clearly. Spire.XLS for JavaScript completes this directly in the browser based on WebAssembly, managing input/output files through a virtual file system (VFS), with no backend service required.

This article introduces two 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.


Create an Exploded Pie Chart

The slices of an exploded pie chart are separated from each other, which is suitable for highlighting the proportion of each data item. To create an exploded pie chart, follow these steps:

  1. Create a Workbook object and use the LoadFromFile() method to load the Excel file that contains the data.
  2. Use the Workbook.Worksheets.get() method to get the worksheet that contains the data.
  3. Call the Charts.Add() method to add a chart and set the ChartType to ExcelChartType.PieExploded.
  4. Use the Series.CategoryLabels and Series.Values properties to specify the categories and values of the chart.
  5. Set properties such as the chart title, position and data labels.
  6. Use the Workbook.SaveToFile() method to save the workbook.

Here is a complete code example showing how to create an exploded pie chart from the product sales data in a worksheet in React:

function App() {
  const createExplodedPieChart = 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 Excel file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'SalesData.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Load the workbook and get the worksheet that contains the data
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: inputFileName });
    const sheet = workbook.Worksheets.get(0);

    // Add a chart and set its chart type to an exploded pie chart
    const chart = sheet.Charts.Add();
    chart.ChartType = xlsModule.ExcelChartType.PieExploded;

    // Set the data range and the title of the chart
    chart.DataRange = sheet.Range.get("B2:B7");
    chart.SeriesDataFromRange = false;
    chart.ChartTitle = "Product Sales Share";
    chart.ChartTitleArea.IsBold = true;
    chart.ChartTitleArea.Size = 12;

    // Set the category labels and the values of the chart, and show the value labels
    const cs = chart.Series.get(0);
    cs.CategoryLabels = sheet.Range.get("A2:A7");
    cs.Values = sheet.Range.get("B2:B7");
    cs.DataPoints.DefaultDataPoint.DataLabels.HasValue = true;

    // Set the position of the chart
    chart.LeftColumn = 4;
    chart.TopRow = 1;
    chart.RightColumn = 15;
    chart.BottomRow = 25;

    // Hide the background of the plot area and set the position of the legend
    chart.PlotArea.Fill.Visible = false;
    chart.Legend.Position = xlsModule.LegendPositionType.Right;

    // Save the document
    const outputFileName = 'ExplodedPieChart_output.xlsx';
    workbook.SaveToFile({ fileName: outputFileName });

    // Release resources
    workbook.Dispose();

    // Read the converted file from the VFS and trigger a 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 Exploded Pie Chart</h1>
      <button onClick={createExplodedPieChart}>
        Start
      </button>
    </div>
  );
}

export default App;

After running the code, you can see the effect of the exploded pie chart:

Create an Exploded Pie Chart


Create an Exploded Doughnut Chart

A doughnut chart is similar to a pie chart, but it has a hole in the center and can also show the proportion of each part in the whole. An exploded doughnut chart further pulls the slices apart. To create an exploded doughnut chart, follow these steps:

  1. Create a Workbook object and use the LoadFromFile() method to load the Excel file that contains the data.
  2. Use the Workbook.Worksheets.get() method to get the worksheet that contains the data.
  3. Call the Charts.Add() method to add a chart and set the ChartType to ExcelChartType.DoughnutExploded.
  4. Use the Series.CategoryLabels and Series.Values properties to specify the categories and values of the chart.
  5. Set properties such as the chart title, position and data labels.
  6. Use the Workbook.SaveToFile() method to save the workbook.

Here is a complete code example showing how to create an exploded doughnut chart from the product sales data in a worksheet in React:

function App() {
  const createExplodedDoughnutChart = 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 Excel file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'SalesData.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Load the workbook and get the worksheet that contains the data
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: inputFileName });
    const sheet = workbook.Worksheets.get(0);

    // Add a chart and set its chart type to an exploded doughnut chart
    const chart = sheet.Charts.Add();
    chart.ChartType = xlsModule.ExcelChartType.DoughnutExploded;

    // Set the data range and the title of the chart
    chart.DataRange = sheet.Range.get("B2:B7");
    chart.SeriesDataFromRange = false;
    chart.ChartTitle = "Sales Share by Product";
    chart.ChartTitleArea.IsBold = true;
    chart.ChartTitleArea.Size = 12;

    // Set the category labels and the values of the chart, and show the value labels
    const cs = chart.Series.get(0);
    cs.CategoryLabels = sheet.Range.get("A2:A7");
    cs.Values = sheet.Range.get("B2:B7");
    cs.DataPoints.DefaultDataPoint.DataLabels.HasValue = true;

    // Set the position of the chart
    chart.LeftColumn = 4;
    chart.TopRow = 1;
    chart.RightColumn = 15;
    chart.BottomRow = 25;

    // Hide the background of the plot area and set the position of the legend
    chart.PlotArea.Fill.Visible = false;
    chart.Legend.Position = xlsModule.LegendPositionType.Right;

    // Save the document
    const outputFileName = 'ExplodedDoughnutChart_output.xlsx';
    workbook.SaveToFile({ fileName: outputFileName });

    // Release resources
    workbook.Dispose();

    // Read the converted file from the VFS and trigger a 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 Exploded Doughnut Chart</h1>
      <button onClick={createExplodedDoughnutChart}>
        Start
      </button>
    </div>
  );
}

export default App;

After running the code, you can see the effect of the exploded doughnut chart:

Create an Exploded Doughnut Chart


FAQ

The created chart is blank with no slices

Cause: The chart has no valid data series. For example, the DataRange or Values points to an empty range or a range without numbers, so the chart has no data to draw.

Solution: Assign a data range that contains the data to the chart, for example:

chart.DataRange = sheet.Range.get("A1:B7");

const cs = chart.Series.get(0);
cs.CategoryLabels = sheet.Range.get("A2:A7");
cs.Values = sheet.Range.get("B2:B7");

Want to show percentages instead of values in the data labels

Cause: Pie and doughnut charts are usually used to show proportions, but the data labels show values by default, or the percentage labels are not enabled.

Solution: Disable the value labels and enable the percentage labels, for example:

const cs = chart.Series.get(0);
cs.DataPoints.DefaultDataPoint.DataLabels.HasValue = false;
cs.DataPoints.DefaultDataPoint.DataLabels.HasPercentage = true;

Obtain 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.

By default, Excel displays the same header and footer at the top and bottom of every page. However, when printing formal reports, manuals, or theses, it is often necessary for different pages to show different headers and footers — for example, odd and even pages can use different headers, or the first page can have no header/footer while only the body pages show the page number. Spire.XLS for JavaScript completes this directly in the browser based on WebAssembly, managing input/output files through a virtual file system (VFS), with no backend service required.

This article introduces two 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.


Set Different Headers and Footers for Odd and Even Pages

In books, papers or reports printed on both sides of the page, odd and even pages usually use different headers and footers, for example the header of odd pages shows the chapter name and the header of even pages shows the book title. To set different headers and footers for odd and even pages with Spire.XLS for JavaScript, follow these steps:

  1. Create a Workbook object and use the LoadFromFile() method to load the Excel file.
  2. Use the Workbook.Worksheets.get() method to get the specified worksheet.
  3. Set the PageSetup.DifferentOddEven property to 1 to enable different headers and footers for odd and even pages.
  4. Use the PageSetup.OddHeaderString and PageSetup.OddFooterString properties to set the header and footer of odd pages.
  5. Use the PageSetup.EvenHeaderString and PageSetup.EvenFooterString properties to set the header and footer of even pages.
  6. Use the Workbook.SaveToFile() method to save the workbook.

Here is a complete code example showing how to set different headers and footers for the odd and even pages of a worksheet in React (the sample input file contains data that spans multiple pages, making it easy to observe the effect on different pages):

function App() {
  const setOddEvenHeaderFooter = 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 Excel file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'DifferentHeaderFooter.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Load the workbook
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: inputFileName });

    // Get the first worksheet
    const sheet = workbook.Worksheets.get(0);

    // Enable different headers and footers for odd and even pages
    sheet.PageSetup.DifferentOddEven = 1;

    // Set the header and footer for odd pages (orange, bold)
    sheet.PageSetup.OddHeaderString = "&\"Arial\"&12&B&KFFC000Odd Page Header";
    sheet.PageSetup.OddFooterString = "&\"Arial\"&12&B&KFFC000Odd Page Footer";

    // Set the header and footer for even pages (red, bold)
    sheet.PageSetup.EvenHeaderString = "&\"Arial\"&12&B&KFF0000Even Page Header";
    sheet.PageSetup.EvenFooterString = "&\"Arial\"&12&B&KFF0000Even Page Footer";

    // Switch to Page Layout view to preview the header and footer
    sheet.ViewMode = xlsModule.ViewMode.Layout;

    // Save the document
    const outputFileName = 'DifferentHeaderFooterOddEven_output.xlsx';
    workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    workbook.Dispose();

    // Read the converted file from the VFS and trigger a 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 Different Header and Footer for Odd and Even Pages</h1>
      <button onClick={setOddEvenHeaderFooter}>
        Start
      </button>
    </div>
  );
}

export default App;

After this setting, different headers and footers are applied to odd and even pages.

Set Different Headers and Footers for Odd and Even Pages


Set a Different Header and Footer on the First Page

Many formal documents require the first page (cover page) to display no header/footer or a dedicated header/footer, while the body pages display a header and footer carrying document information. In this case, you can enable "different first page" and set the header and footer of the first page separately. The steps are as follows:

  1. Create a Workbook object and use the LoadFromFile() method to load the Excel file.
  2. Use the Workbook.Worksheets.get() method to get the specified worksheet.
  3. Set the PageSetup.DifferentFirst property to 1 to enable a header and footer on the first page that differ from those on the other pages.
  4. Use the PageSetup.FirstHeaderString and PageSetup.FirstFooterString properties to set the header and footer of the first page.
  5. Use properties such as PageSetup.LeftHeader and PageSetup.CenterFooter to set the header and footer of the other pages.
  6. Use the Workbook.SaveToFile() method to save the workbook.

Here is a complete code example showing how to set a different header and footer on the first page of a worksheet in React:

function App() {
  const setFirstPageHeaderFooter = 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 Excel file into the VFS
    await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
    const inputFileName = 'DifferentHeaderFooter.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Load the workbook
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: inputFileName });

    // Get the first worksheet
    const sheet = workbook.Worksheets.get(0);

    // Enable a different header and footer on the first page
    sheet.PageSetup.DifferentFirst = 1;

    // Set the header and footer for the first page (blue, bold)
    sheet.PageSetup.FirstHeaderString = "&\"Arial\"&16&B&K4253E2First Page Header";
    sheet.PageSetup.FirstFooterString = "&\"Arial\"&16&B&K4253E2First Page Footer";

    // Set the header and footer for the other pages (gray, bold)
    sheet.PageSetup.LeftHeader = "&\"Arial\"&12&B&K808080Other Pages Header";
    sheet.PageSetup.CenterFooter = "&\"Arial\"&12&B&K808080Other Pages Footer";

    // Switch to Page Layout view to preview the header and footer
    sheet.ViewMode = xlsModule.ViewMode.Layout;

    // Save the document
    const outputFileName = 'DifferentHeaderFooterFirstPage_output.xlsx';
    workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    workbook.Dispose();

    // Read the converted file from the VFS and trigger a 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 Different Header and Footer on the First Page</h1>
      <button onClick={setFirstPageHeaderFooter}>
        Start
      </button>
    </div>
  );
}

export default App;

After this setting, the first page uses a different header and footer from the other pages.

Set a Different Header and Footer on the First Page


FAQ

The header and footer on the first page is not applied

Cause: The "different first page" option was not enabled. If only FirstHeaderString/FirstFooterString are set without setting PageSetup.DifferentFirst to 1, Excel ignores the first-page header and footer.

Solution: Enable sheet.PageSetup.DifferentFirst = 1; before setting the header and footer of the first page.

Header/footer text shows as garbled characters or boxes

Cause: Browser-side Excel processing depends on font files. If the font used by the text (such as ARIAL.TTF) has not been loaded into the virtual file system (VFS), the text may not render correctly.

Solution: Load the font into the VFS with FetchFileToVFS() before calling Workbook.LoadFromFile(), for example:

await window.spire.FetchFileToVFS(
  'ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`
);

Obtain 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.

When multiple users collaborate on an Excel document with tracking changes (Track Changes) enabled, every insertion, modification and deletion made to cells is recorded. When reviewing these changes, you often need to accept all tracked changes (to formally merge the changes of others into the document) or reject all tracked changes (to revert all changes and restore the state before the edits). Handling these changes one by one in Excel is tedious and error-prone, while processing them in bulk through code in a web application is far more efficient. Spire.XLS for JavaScript completes this directly in the browser based on WebAssembly, and manages input/output files through a virtual file system (VFS), with no backend service required.

Spire.XLS for JavaScript provides revision-handling capabilities through the workbook object: after loading a workbook that contains revision records, call the AcceptAllTrackedChanges() method to accept all tracked changes in the document, or call the RejectAllTrackedChanges() method to reject all tracked changes in the document.

This article covers two 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.


Accept All Tracked Changes in Excel

When a workbook containing revision records has been edited by multiple users and passes review, all the changes need to be formally merged into the document, that is, the tracked changes are "accepted". After the changes are accepted, they become the official content of the document and the revision records are cleared. The main steps are as follows:

  1. Create a Workbook object.
  2. Load the workbook containing revision records with the Workbook.LoadFromFile() method.
  3. Call the Workbook.AcceptAllTrackedChanges() method to accept all tracked changes in the document.
  4. Save the workbook with the Workbook.SaveToFile() method.

Here is a complete code example showing how to accept all tracked changes in an Excel workbook in React:

function App() {
  const acceptTrackedChanges = 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 = 'TrackChanges.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Create a Workbook object and load the workbook containing tracked changes
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: inputFileName });

    // Accept all tracked changes in the document
    workbook.AcceptAllTrackedChanges();

    // Save the document
    const outputFileName = 'AcceptTrackedChanges_output.xlsx';
    workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    workbook.Dispose();

    // Read the converted file from the VFS and trigger a 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>Accept All Tracked Changes</h1>
      <button onClick={acceptTrackedChanges}>
        Start
      </button>
    </div>
  );
}

export default App;

Effect of accepting all tracked changes

Accept All Tracked Changes in Excel


Reject All Tracked Changes in Excel

When the tracked changes are disputed or no longer needed, the reviewer can reject all of them at once so that the document returns to the state before the edits. The main steps are as follows:

  1. Create a Workbook object.
  2. Load the workbook containing revision records with the Workbook.LoadFromFile() method.
  3. Call the Workbook.RejectAllTrackedChanges() method to reject all tracked changes in the document.
  4. Save the workbook with the Workbook.SaveToFile() method.

Here is a complete code example showing how to reject all tracked changes in an Excel workbook in React:

function App() {
  const rejectTrackedChanges = 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 = 'TrackChanges.xlsx';
    await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);

    // Create a Workbook object and load the workbook containing tracked changes
    const workbook = new xlsModule.Workbook();
    workbook.LoadFromFile({ fileName: inputFileName });

    // Reject all tracked changes in the document
    workbook.RejectAllTrackedChanges();

    // Save the document
    const outputFileName = 'RejectTrackedChanges_output.xlsx';
    workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });

    // Release resources
    workbook.Dispose();

    // Read the converted file from the VFS and trigger a 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>Reject All Tracked Changes</h1>
      <button onClick={rejectTrackedChanges}>
        Start
      </button>
    </div>
  );
}

export default App;

Effect of rejecting all tracked changes

Reject All Tracked Changes in Excel


FAQ

The content is not restored to its pre-edit state after rejecting tracked changes

Cause: RejectAllTrackedChanges() rejects only the cell changes that were recorded by the Track Changes feature. If some changes were made before tracking was enabled, or were written by other means and never recorded, they are not revisions that can be rejected, so they keep their current values and the document will not fully return to the original baseline.

Can I accept or reject only part of the tracked changes instead of all of them

Cause: AcceptAllTrackedChanges() and RejectAllTrackedChanges() process all the revisions of a whole workbook at once. They do not provide APIs for filtering individual revisions by user, time or cell range.


Obtain 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.

Page 7 of 7