Set Excel Print Titles and Print Order in React with JavaScript
When a report is generated in the browser, an order detail sheet often runs to several printed pages. With the default print settings, the header and the key columns disappear from the second page onwards, which makes the columns hard to identify and leaves the page numbers out of step with the rest of the report. Spire.XLS for JavaScript handles the page setup directly in the browser through WebAssembly, managing input and output files in a virtual file system (VFS) with no backend service required.
Using an order detail sheet of 18 columns by 60 rows as the sample, this article covers two core feature points:
For installation and project setup, see Integrating Spire.XLS for JavaScript in a React Project. The examples below assume Spire.XLS is installed and the WebAssembly module has been initialized.
Set the print title rows and columns
Print titles are what Excel calls the "Rows to repeat at top" and "Columns to repeat at left" options in the Page Setup dialog. Once set, the chosen rows or columns are repeated in the same position on every printed page, so the header is still visible once the table runs onto the second page. Spire.XLS for JavaScript sets them through the PrintTitleRows and PrintTitleColumns properties of PageSetup, which take a row or column reference string. Here is a complete code example showing how to set the print title rows and columns in React:
function App() {
const setPrintTitles = 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 and the input file into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'OrderDetails.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);
// Get the page setup of the worksheet
const pageSetup = sheet.PageSetup;
// Use rows 1 and 2 as the print title rows, so they repeat at the top of every page
pageSetup.PrintTitleRows = '$1:$2';
// Use columns A and B as the print title columns, so they repeat at the left of every page
pageSetup.PrintTitleColumns = '$A:$B';
// Save the workbook
const outputFileName = 'SetPrintTitles.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
// Dispose of the workbook object to free resources
workbook.Dispose();
// Read the result 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>Set Print Title Rows and Columns</h1>
<button onClick={setPrintTitles}>Set Print Title Rows and Columns</button>
</div>
);
}
export default App;
Print result of the original file

After running, the effect of setting the print title rows and columns:

Set the print order
When a worksheet is wider than one page and longer than one page at the same time, Excel has to decide which direction the pages advance in. The default, "down, then over", fills a page vertically before moving to the next block of columns on the right; "over, then down" fills a page horizontally first and then moves down. Spire.XLS for JavaScript switches between the two with the Order property of PageSetup. Here is a complete code example showing how to set the print order of a worksheet in React:
function App() {
const setPrintOrder = 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 and the input file into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'OrderDetails.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);
// Get the page setup of the worksheet
const pageSetup = sheet.PageSetup;
// Set the page order to over-then-down: print a column top to bottom, then move right
pageSetup.Order = xlsModule.OrderType.OverThenDown;
// Save the workbook
const outputFileName = 'SetPrintOrder.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
// Dispose of the workbook object to free resources
workbook.Dispose();
// Read the result 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>Set Print Order</h1>
<button onClick={setPrintOrder}>Set Print Order</button>
</div>
);
}
export default App;
After running, the effect of setting the print order to over-then-down:

FAQ
Can I set only the print title rows and not the title columns
Cause: PrintTitleRows and PrintTitleColumns are two independent properties — one controls the rows repeated at the top of each page, the other the columns repeated at the left. Setting only one leaves the other unset: the call is not rejected for the missing half, and no default is filled in.
Solution: Set whichever one you need. To repeat the header rows only, use pageSetup.PrintTitleRows = '$1:$2'.
Does setting the print titles change the data in the worksheet
Cause: Print titles are part of the page setup. They only decide which rows and columns are repeated in the printout; they do not touch cell contents, and they add or remove no rows and columns.
Solution: The data is unaffected. The file measures 62 rows by 18 columns both before and after the setting, with cell-by-cell identical text — the only difference is the print title definition added to the page setup. The worksheet looks exactly the same on screen.
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.
Set Excel Print Output Options in React with JavaScript
When an order detail sheet or a statement is exported for printing, the page setup decides whether the printed copy is actually readable: whether the table comes out with gridlines and row and column headings, how fine the output is, and whether comments travel with it. These switches are scattered across several tabs of the Excel Page Setup dialog, which makes them tedious to tick one by one.Spire.XLS for JavaScript handles the page setup in the browser through WebAssembly, using a virtual file system (VFS) for the input and the output, with no backend service involved.
This article takes an 18-column by 60-row order detail sheet and covers three feature points:
- Set the print quality and draft quality
- Print gridlines and row and column headings
- Set black and white printing, comments and error values
For installation and project configuration, see Integrating Spire.XLS for JavaScript in a React Project. The examples below assume Spire.XLS is installed and the WebAssembly module has finished initializing.
Set the print quality and draft quality
Print quality sets the number of ink dots per inch in the printed output and takes a plain integer in dpi; draft quality lets the printer run faster with less toner, which suits a proof that only circulates internally. Spire.XLS for JavaScript exposes both through the PrintQuality and Draft members of PageSetup:
PrintQuality = 72prints at 72 dpi, a low setting that lets the page come out faster with less consumableDraft = trueturns on draft quality, trading fine detail for speed
The complete example code is as follows:
function App() {
const setPrintQuality = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Make sure the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the font and the input file into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'OrderDetails.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// Load the workbook and take its first worksheet
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
const sheet = workbook.Worksheets.get(0);
// Get the page setup of the worksheet
const pageSetup = sheet.PageSetup;
// Set the print quality to 72 dpi
pageSetup.PrintQuality = 72;
// Turn on draft quality: speed matters more than fine detail
pageSetup.Draft = true;
// Save the workbook
const outputFileName = 'SetPrintQuality.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
// Release the workbook to free its resources
workbook.Dispose();
// Read the result file back from the VFS to 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>Set print quality and draft quality</h1>
<button onClick={setPrintQuality}>Set print quality and draft quality</button>
</div>
);
}
export default App;
The original file as printed:

The effect of the print quality and draft quality settings:

Print gridlines and row and column headings
The gridlines on screen do not travel with the data when the sheet is printed, so a sheet without borders of its own reaches paper as a field of floating values that is hard to check cell by cell. Row and column headings have the same problem: printing them is what lets a printed copy be discussed in the same C5, D7 terms used in Excel. The two boolean members IsPrintGridlines and IsPrintHeadings control them. The complete example code is as follows:
function App() {
const setGridlinesAndHeadings = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Make sure the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the font and the input file into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'OrderDetails.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// Load the workbook and take its first worksheet
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
const sheet = workbook.Worksheets.get(0);
// Get the page setup of the worksheet
const pageSetup = sheet.PageSetup;
// Print the gridlines along with the data
pageSetup.IsPrintGridlines = true;
// Print the row and column headings along with the data
pageSetup.IsPrintHeadings = true;
// Save the workbook
const outputFileName = 'SetGridlinesAndHeadings.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
// Release the workbook to free its resources
workbook.Dispose();
// Read the result file back from the VFS to 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>Print gridlines and headings</h1>
<button onClick={setGridlinesAndHeadings}>Print gridlines and headings</button>
</div>
);
}
export default App;
The effect of printing the gridlines and the row and column headings:

Set black and white printing, comments and error values
The remaining three output switches also live on PageSetup, and they decide what colour the printed copy comes out in, whether comments travel with the sheet, and how errors are shown. The three members and their values:
BlackAndWhiteset totrueprints in black and white, turning colour content into greyscale, which is especially useful with a mono laser printerPrintCommentsset toInPlaceprints each comment box where it sits on the sheet; the comment has to be shown first — one that is not displayed is not printedPrintErrorsset toNAshows every error value such as#DIV/0!as#N/Aon paper, keeping internal formula errors out of sight
The complete example code is as follows:
function App() {
const setOtherPrintOptions = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Make sure the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the font and the input file into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
const inputFileName = 'OrderDetails.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// Load the workbook and take its first worksheet
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile({ fileName: inputFileName });
const sheet = workbook.Worksheets.get(0);
// Get the page setup of the worksheet
const pageSetup = sheet.PageSetup;
// The sample carries one comment, on cell A18
// Show it first: a comment that is not displayed is not printed
sheet.Range.get('A18').Comment.Visible = true;
// Print the worksheet in black and white
pageSetup.BlackAndWhite = true;
// Print comments where they appear on the worksheet
pageSetup.PrintComments = xlsModule.PrintCommentType.InPlace;
// Print every cell error as #N/A
pageSetup.PrintErrors = xlsModule.PrintErrorsType.NA;
// Save the workbook
const outputFileName = 'SetOtherPrintOptions.xlsx';
workbook.SaveToFile({ fileName: outputFileName, version: xlsModule.ExcelVersion.Version2010 });
// Release the workbook to free its resources
workbook.Dispose();
// Read the result file back from the VFS to 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>Set black and white, comments and errors</h1>
<button onClick={setOtherPrintOptions}>Set black and white, comments and errors</button>
</div>
);
}
export default App;
The effect of the black and white, comment and error value settings:

FAQ
The sheet still runs to several pages, and lowering the print quality did not help
Cause: print quality and draft quality only decide how fine the output is and how much ink it uses; they do not change the layout of the content, so no setting of theirs moves a page break. Fitting a whole sheet onto one page is a matter of page scaling, which has nothing to do with print quality. Setting both at once is not a conflict — each one simply does its own job.
Solution: use FitToPagesWide and FitToPagesTall to squeeze the worksheet into a given number of pages, where 1 means one page wide and one page tall:
// Scale the worksheet onto one page wide and one page tall
pageSetup.FitToPagesWide = 1;
pageSetup.FitToPagesTall = 1;
Set together with the print quality, both survive:
<pageSetup fitToHeight="1" fitToWidth="1" horizontalDpi="72" verticalDpi="72" orientation="portrait" paperSize="9" />
The worksheet looks exactly the same after setting PrintQuality and Draft
Cause: both act on the printer output only and leave the worksheet's own content and display untouched, so the document looks no different once they are set. That is expected, and does not mean the setting failed to apply.
Solution: the print quality and the draft quality are written into the result file. To confirm they took effect, unzip the result file and look at xl/worksheets/sheet1.xml: the print quality lands on the horizontalDpi and verticalDpi of <pageSetup>, and the draft quality shows up as draft="1" on the same element. This example sets both, giving:
<pageSetup draft="1" horizontalDpi="72" verticalDpi="72" orientation="portrait" paperSize="9" />
Note that what Draft actually does depends on the printer driver — some drivers ignore the switch, and the attribute is written into the file either way.
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.