Loading & saving
Open a workbook from any source, write it back to any sink.
Browser
src/io/browser.tsfromArrayBuffer function
src/io/browser.ts:135Wrap an ArrayBuffer or Uint8Array. The bytes are referenced (Uint8Array input) or wrapped without copy (ArrayBuffer input).
function fromArrayBuffer(buf: ArrayBuffer | Uint8Array<ArrayBufferLike>): XlsxSourceParameters
| Name | Type | Description |
|---|---|---|
buf | ArrayBuffer | Uint8Array<ArrayBufferLike> |
Returns
XlsxSource
fromBlob function
src/io/browser.ts:17Wrap a Blob (or File, since File extends Blob) as an XlsxSource. The source materialises bytes lazily on the first XlsxSource.toBytes call.
function fromBlob(blob: Blob): XlsxSourceParameters
| Name | Type | Description |
|---|---|---|
blob | Blob |
Returns
XlsxSource
fromResponse function
src/io/browser.ts:43Wrap a fetch Response as an XlsxSource. toBytes collects
the entire response body via Response.arrayBuffer(); toStream
returns response.body directly so the ZIP reader can pull chunks
lazily from the network. The Response can have been fetched with
any method and content-type; this helper does no validation.
function fromResponse(response: Response): XlsxSourceParameters
| Name | Type | Description |
|---|---|---|
response | Response |
Returns
XlsxSource
fromStream function
src/io/browser.ts:81Wrap a Web ReadableStream of bytes as an XlsxSource. toStream
returns the stream directly; toBytes drains it once and caches the
bytes. Streams can only be consumed once — calling toBytes after
toStream (or vice versa) on the same source throws.
function fromStream(stream: ReadableStream<Uint8Array<ArrayBufferLike>>): XlsxSourceParameters
| Name | Type | Description |
|---|---|---|
stream | ReadableStream<Uint8Array<ArrayBufferLike>> |
Returns
XlsxSource
toArrayBuffer function
src/io/browser.ts:216In-memory ArrayBuffer sink.
function toArrayBuffer(): XlsxSink & { result: unknown; toBytes: unknown }Returns
XlsxSink & { result: unknown; toBytes: unknown }
toBlob function
src/io/browser.ts:175In-memory Blob sink. Convenience result() returns the accumulated
payload as a Blob with the supplied MIME type.
function toBlob(mime?: string): XlsxSink & { result: unknown; toBytes: unknown }Parameters
| Name | Type | Description |
|---|---|---|
mime? = 'application/octet-stream' | string |
Returns
XlsxSink & { result: unknown; toBytes: unknown }
Node fs
src/io/node-fs.tsfromFile function
src/io/node-fs.ts:26Wrap a filesystem path as an XlsxSource. toBytes reads the whole file into
memory; toStream opens a fs.createReadStream and bridges it to a Web
ReadableStream via Readable.toWeb so the ZIP reader can iterate
without loading the entire xlsx up front.
function fromFile(path: string): XlsxSourceParameters
| Name | Type | Description |
|---|---|---|
path | string |
Returns
XlsxSource
fromFileSync function
src/io/node-fs.ts:51Synchronous variant of fromFile. Convenience for tooling / scripts
where the cost of await fs.readFile outweighs the ergonomic gain. The
returned source's toBytes resolves immediately with the bytes already in
memory.
function fromFileSync(path: string): XlsxSourceParameters
| Name | Type | Description |
|---|---|---|
path | string |
Returns
XlsxSource
fromReadable function
src/io/node-fs.ts:206Wrap a Node.js Readable as an XlsxSource. toBytes consumes the
entire stream synchronously (collecting chunks); toStream bridges to a Web
ReadableStream via Readable.toWeb so the ZIP reader can pull chunks lazily.
function fromReadable(readable: Readable): XlsxSourceParameters
| Name | Type | Description |
|---|---|---|
readable | Readable |
Returns
XlsxSource
toFile function
src/io/node-fs.ts:96Filesystem sink. Each write(chunk) call streams the bytes to disk via
fs.createWriteStream, honouring backpressure: the actual writable.write
for each chunk is queued behind any pending drain, so the writable's
internal buffer never grows past its highWaterMark (default 16 KB) no
matter how fast the producer hands chunks over.
Note on the producer-side memory budget: the sink contract is
intentionally synchronous (write(chunk): void), so a producer that races
ahead without yielding will let chunk references pile up in the queue.
That keeps writable's buffer bounded but does not bound the queue
itself. Producers that need a hard ceiling should yield between writes
(await new Promise(setImmediate) is enough) or use a sink with an async
write contract.
result() returns the destination path; finish() resolves with an empty
Uint8Array once the stream has flushed. Callers that need the on-disk
bytes should readFile() the returned path themselves — re-reading inside
finish() would defeat the "streamed to disk, never resident" guarantee.
function toFile(path: string): XlsxSink & { result: unknown; toBytes: unknown }Parameters
| Name | Type | Description |
|---|---|---|
path | string |
Returns
XlsxSink & { result: unknown; toBytes: unknown }
toWritable function
src/io/node-fs.ts:248Wrap a Node.js Writable as an XlsxSink. The actual
writable.write for each chunk is queued behind any pending drain, so
the writable's internal buffer never exceeds its highWaterMark regardless
of how fast the producer is. See toFile for the same caveat about
producer-side memory: the synchronous write(chunk) API does not let
backpressure flow back to the caller, so a tight non-yielding producer can
still let chunk references accumulate in the queue.
result() returns the writable itself for downstream chaining.
function toWritable(writable: Writable): XlsxSink & { result: unknown; toBytes: unknown }Parameters
| Name | Type | Description |
|---|---|---|
writable | Writable |
Returns
XlsxSink & { result: unknown; toBytes: unknown }
Node
src/io/node.tsfromBuffer function
src/io/node.ts:18Wrap a Buffer or Uint8Array as an XlsxSource. The underlying bytes are referenced — no copy — so callers must not mutate them while the source is in use.
function fromBuffer(buf: Uint8Array<ArrayBufferLike> | Buffer<ArrayBufferLike>): XlsxSourceParameters
| Name | Type | Description |
|---|---|---|
buf | Uint8Array<ArrayBufferLike> | Buffer<ArrayBufferLike> |
Returns
XlsxSource
toBuffer function
src/io/node.ts:44In-memory Buffer sink. The buffered path concatenates appended chunks into a
single allocation when BufferedSinkWriter.finish resolves; the
convenience result() returns it as a Node Buffer.
function toBuffer(): XlsxSink & { result: unknown; toBytes: unknown }Returns
XlsxSink & { result: unknown; toBytes: unknown }
Save
src/io/save.tssaveWorkbook function
src/io/save.ts:304Save a workbook through the given sink. Returns once finalize() resolves.
function saveWorkbook(wb: Workbook, sink: XlsxSink, opts?: SaveOptions): Promise<void>Parameters
| Name | Type | Description |
|---|---|---|
wb | Workbook | |
sink | XlsxSink | |
opts? = {} | SaveOptions |
Returns
Promise<void>
workbookToBytes function
src/io/save.ts:144Convenience: serialise a Workbook to an in-memory Uint8Array xlsx.
Browser-safe: this path uses an in-memory Uint8Array sink and never
touches Node's Buffer global, so it works unchanged in browser bundles.
function workbookToBytes(wb: Workbook, opts?: SaveOptions): Promise<Uint8Array<ArrayBufferLike>>Parameters
| Name | Type | Description |
|---|---|---|
wb | Workbook | |
opts? = {} | SaveOptions |
Returns
Promise<Uint8Array<ArrayBufferLike>>
Load
src/io/load.tsloadWorkbook function
src/io/load.ts:388Load a workbook from any XlsxSource into a fully populated
Workbook: every worksheet's cells, formulas, merges, tables,
comments, drawings and charts, plus the shared strings, the stylesheet, the
theme, defined names and the docProps. Parts this library does not model
(the VBA project, pivot caches, slicers, external links, printer settings,
custom XML, ...) are retained on wb.passthrough for saving. Strict OOXML
XML is normalized to Transitional; opaque binary parts remain unchanged.
The package is read in full and the returned Workbook holds every cell.
loadWorkbookStream from @office-kit/xlsx/streaming walks a sheet row by
row instead to reduce worksheet memory use. Both loaders keep the compressed
archive in memory; streaming does not make source buffering bounded.
Malformed input throws an OpenXmlError subclass rather than returning a
partial workbook, and a .xls or an encrypted package throws
OpenXmlUnsupportedFormatError. Both caps in LoadOptions apply
here: decompressionLimits bounds what the archive may inflate to and is on
by default, contentLimits bounds the cells and rows the load will model
and is unlimited by default.
What a failure means, for a caller checking a file it did not produce:
- OpenXmlIoError: the bytes are not a readable zip. A CSV, a PDF or a
truncated upload lands here, and the message names what the leading bytes
look like whenever a magic number identifies them.
- OpenXmlDecompressionBombError: the archive inflates past the
LoadOptions.decompressionLimits caps. A subclass of the above, so
test for it first when the distinction matters.
- OpenXmlNotImplementedError: an OOXML feature this library does not read
yet, such as an ISO 29500 strict part it cannot convert.
- OpenXmlUnsupportedFormatError: the input is a different Office format
altogether. A subclass of the above, carrying a format of
'encrypted-xlsx' | 'legacy-xls' | 'compound-file', so "ask for the
password" is answerable apart from "ask for a re-save".
- OpenXmlSchemaError: invalid options, or OOXML that is unreadable or
contradicts the spec.
- OpenXmlContentLimitError: the read exceeds the
LoadOptions.contentLimits caps. This does not validate the rest
of the workbook. It extends OpenXmlError
directly, so a catch ladder written around the others misses it.
Retrying unchanged bytes and options does not resolve parsing or validation
errors. Correct invalid options or supply a supported file; changing a limit
may allow a read to proceed but does not guarantee success. Source I/O errors
can be transient; see OpenXmlIoError. Branch on the class, not the message
text, which names parts and offsets and changes between releases.
function loadWorkbook(source: XlsxSource, opts?: LoadOptions): Promise<Workbook>Parameters
| Name | Type | Description |
|---|---|---|
source | XlsxSource | |
opts? = {} | LoadOptions |
Returns
Promise<Workbook>
Node save
src/io/node-save.tsworkbookToBuffer function
src/io/node-save.ts:8function workbookToBuffer(wb: Workbook, opts?: SaveOptions): Promise<Buffer<ArrayBufferLike>>Parameters
| Name | Type | Description |
|---|---|---|
wb | Workbook | |
opts? | SaveOptions |
Returns
Promise<Buffer<ArrayBufferLike>>