A workbook exported by a reporting system usually carries nothing but the system name as its author, with the title, subject and keywords left blank; teams meanwhile need to attach fields the export does not produce — an export batch, an owner, an approval state — for archiving and searching. None of this takes up a cell: it all lives in the workbook's document properties, which Excel shows under "File > Info > Properties". Spire.XLS for JavaScript writes them in the browser on top of WebAssembly, using a virtual file system (VFS) for input and output files, so no back-end service is needed.
This article covers three feature points:
- Set the summary properties of a workbook
- Add custom properties
- Update the value of a custom property
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 initialised.
Set the summary properties of a workbook
The summary properties are the layer of description Excel shows in File Explorer and under "File > Info", and the first thing a search of the archive picks up. A workbook produced by a program usually has only the system name as its author and leaves the other entries blank; filling them in gives the file a readable context as it moves between people. The text entries take a plain assignment, while the two date entries have to be given a date object. The steps are:
- Load the workbook and take the summary property collection from
workbook.DocumentProperties. - Assign the text entries —
Title,Subject,Author,Keywords,CommentsandCategory— directly. - Assign
CompanyandManagerthe same way; Excel carries these two in its extended properties. - Set
CreatedTimeandLastSaveTimetoDateobjects. - Save the workbook.
Here is a complete code example showing how to set the summary properties of a workbook in React:
function App() {
const setSummaryProperties = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check that the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the font into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// Load the Excel file into the VFS
const inputFileName = 'WorkbookProperties.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// Load the workbook
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile(inputFileName);
// Set the text entries of the summary properties
const summary = workbook.DocumentProperties;
summary.Title = 'Q3 2026 Sales Report';
summary.Subject = 'Quarterly results by sales department';
summary.Author = 'E-iceblue';
summary.Keywords = 'sales, report, Excel';
summary.Comments = 'Summary filled in after the export';
summary.Category = 'Sales Report';
// Set the entries carried by the extended properties
summary.Company = 'E-iceblue';
summary.Manager = 'Sales Manager';
// Set the document dates; a Date object is required here
summary.CreatedTime = new Date(2026, 8, 1);
summary.LastSaveTime = new Date(2026, 8, 20);
// Save the workbook
const outputFileName = 'SetSummaryProperties.xlsx';
workbook.SaveToFile(outputFileName);
// Release resources
workbook.Dispose();
// Read the result file back out of the VFS and download it
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 workbook summary properties</h1>
<button onClick={setSummaryProperties}>Start</button>
</div>
);
}
export default App;
The effect of setting the summary properties of a workbook:

Add custom properties
Custom properties carry the business fields the summary properties have no room for, such as an export batch, a contact phone number, a revision number or an approval date. Unlike the summary properties they have no fixed set of entries: the caller decides the name and the type, and Excel accepts text, integer, decimal, boolean and date-and-time values. The steps are:
- Load the workbook and take the custom property collection from
workbook.CustomDocumentProperties. - Call
Addto append a property; the name and the value can be written as a named object such as{ strName, boolValue }, or passed directly as two arguments. - Pick the member that matches the type of the value:
intValuefor an integer,dblValuefor a decimal. - Pass a
Dateobject asdtValuefor a date-and-time value. - Save the workbook.
Here is a complete code example showing how to add custom properties to a workbook in React:
function App() {
const addCustomProperties = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check that the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the font into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// Load the Excel file into the VFS
const inputFileName = 'WorkbookProperties.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// Load the workbook
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile(inputFileName);
// Add a boolean property; _MarkAsFinal marks the document as final
workbook.CustomDocumentProperties.Add({ strName: '_MarkAsFinal', boolValue: true });
// Add a text property; a name and a value can also be passed directly
workbook.CustomDocumentProperties.Add('The Editor', 'E-iceblue');
// Add an integer property
workbook.CustomDocumentProperties.Add({ strName: 'Phone number', intValue: 81705109 });
// Add a decimal property
workbook.CustomDocumentProperties.Add({ strName: 'Revision number', dblValue: 7.12 });
// Add a date and time property
workbook.CustomDocumentProperties.Add({ strName: 'Revision date', dtValue: new Date(2026, 8, 1) });
// Save the workbook
const outputFileName = 'AddCustomProperties.xlsx';
workbook.SaveToFile(outputFileName);
// Release resources
workbook.Dispose();
// Read the result file back out of the VFS and download it
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 custom properties</h1>
<button onClick={addCustomProperties}>Start</button>
</div>
);
}
export default App;
The effect of adding custom properties:

Update the value of a custom property
The value of a business field changes with the way it is counted: an export record count, say, has to be rewritten to a new figure once the data is topped up. Custom properties offer no member that assigns a value directly, but Add is keyed on the name — calling it again for a name that already exists does not append a duplicate entry, it replaces the value of the existing one. The steps are:
- Load the workbook and take the custom property collection from
workbook.CustomDocumentProperties. - Call
Addagain, passing the same name as the existing entry together with the new value. - Save the workbook.
Here is a complete code example showing how to update a custom property of a workbook in React:
function App() {
const updateCustomProperties = async () => {
// Get the Spire.XLS WASM module
const xlsModule = window.wasmModule?.spirexls;
// Check that the module is ready
if (!xlsModule) {
alert('Spire.Xls is not ready yet');
return;
}
// Load the font into the VFS
await window.spire.FetchFileToVFS('ARIAL.TTF', '/Library/Fonts/', `${process.env.PUBLIC_URL}/font/`);
// Load the Excel file into the VFS
const inputFileName = 'WorkbookProperties.xlsx';
await window.spire.FetchFileToVFS(inputFileName, '', `${process.env.PUBLIC_URL}data/`);
// Load the workbook
const workbook = new xlsModule.Workbook();
workbook.LoadFromFile(inputFileName);
// Rewrite the exported record count; adding an existing name overwrites it
workbook.CustomDocumentProperties.Add({ strName: 'ExportedRecords', intValue: 256 });
// Save the workbook
const outputFileName = 'UpdateCustomProperties.xlsx';
workbook.SaveToFile(outputFileName);
// Release resources
workbook.Dispose();
// Read the result file back out of the VFS and download it
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>Update the value of a custom property</h1>
<button onClick={updateCustomProperties}>Start</button>
</div>
);
}
export default App;
The effect of updating the value of a custom property:

FAQ
Why does assigning to CreatedTime throw "Assert failed: Value is not a Date"
Cause: CreatedTime and LastSaveTime take a JavaScript Date object and nothing else. A date string such as '2026-09-01', a timestamp number, or a hand-made object that only carries a toISOString() method all fail the type check and throw Assert failed: Value is not a Date.
Solution: build the Date with new Date(...) first, then assign it:
// 1 September 2026; months count from 0, so 8 means September
workbook.DocumentProperties.CreatedTime = new Date(2026, 8, 1);
Why does assigning to the Value of a custom property throw ArgumentNull_Generic
Cause: the Value property only reads. Assigning to it throws ArgumentNull_Generic Arg_ParamName_Name, value, and the original value does not change. Updating an existing property has to go through Add.
Solution: overwrite the original value with a same-name Add:
workbook.CustomDocumentProperties.Add({ strName: 'ExportedRecords', intValue: 256 });
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.
