# Getting started

This page walks the canonical @office-kit/xlsx workflow: load a workbook, mutate it, write it back. Every snippet below is a real `.ts` file in this repo — `svelte-check` compiles them against the live `@office-kit/xlsx` types on every build, so when this page renders, it's already proven that the code typechecks.

## Read, edit, write — full library

`@office-kit/xlsx/io` loads and saves the full workbook model: cells, styles, charts, drawings, the lot. There is no root import; each area has its own subpath, such as `@office-kit/xlsx/worksheet` for cells. Pair them with the platform-specific I/O helpers from `@office-kit/xlsx/node` (or your own `XlsxSource`).

```ts title="site/src/lib/examples/basic-read-write.ts"
// Read an xlsx, mutate one cell, write it back.
//
// This file is imported as ?raw into the docs site so the snippet shown to
// readers is exactly what svelte-check / tsc compiled — if an API rename
// breaks this import, the docs build fails before deploy.

import { loadWorkbook, workbookToBytes } from '@office-kit/xlsx/io';
import { fromBuffer } from '@office-kit/xlsx/node';
import { setCell } from '@office-kit/xlsx/worksheet';
import { readFile, writeFile } from 'node:fs/promises';

const wb = await loadWorkbook(fromBuffer(await readFile('input.xlsx')));
const ref = wb.sheets[0];
if (ref?.kind === 'worksheet') {
  setCell(ref.sheet, 1, 1, 'Hello from @office-kit/xlsx');
}
await writeFile('output.xlsx', await workbookToBytes(wb));
```

`loadWorkbook` returns a `Workbook`. `wb.sheets` is an array of `{ sheet, name, ... }` records — the `sheet` property is the worksheet itself. Cell coordinates are 1-indexed (`row=1, col=1` is `A1`) to match the openpyxl API.

`workbookToBytes` serializes back to a `Uint8Array` in one shot — fine for workbooks that fit in memory. For larger workbooks see <a href="{base}/docs/streaming">Streaming</a>.

## Direct fs helpers (Node)

`@office-kit/xlsx/node` exposes `fromFile` / `toFile` so you can skip the `readFile` / `writeFile` glue:

```ts title="site/src/lib/examples/node-fs.ts"
// One-shot read + save direct from / to disk via the @office-kit/xlsx/node
// helpers, no manual fs glue needed.

import { loadWorkbook, saveWorkbook } from '@office-kit/xlsx/io';
import { fromFile, toFile } from '@office-kit/xlsx/node';

const wb = await loadWorkbook(fromFile('input.xlsx'));
// ...mutate wb...
await saveWorkbook(wb, toFile('output.xlsx'));
```

`fromFile` returns an `XlsxSource` backed by a Node `fs.ReadStream`; `toFile` returns an `XlsxSink` backed by a `fs.WriteStream`. Both are streamed under the hood.

## Browser via fetch

The streaming entry is browser-safe (no `node:fs`). Use `fromResponse` to consume a `fetch` Response straight into the loader without buffering the whole download:

```ts title="site/src/lib/examples/browser-fetch.ts"
// Browser: pipe a fetch Response straight into the loader. fromResponse is
// streaming, so the workbook starts parsing before the download is done.

import { fromResponse, loadWorkbook } from '@office-kit/xlsx/io';

const response = await fetch('/sheet.xlsx');
const wb = await loadWorkbook(fromResponse(response));
const ref = wb.sheets[0];
if (ref?.kind === 'worksheet') {
  console.log(ref.sheet.title);
}
```

This works in any environment with `fetch` + Web Streams: modern browsers, Bun, Deno, Cloudflare Workers, edge runtimes.

## What's next

- <strong><a href="{base}/docs/recipes">Recipes</a></strong> — copy-pasteable code for the most common tasks (styling, charts, validation, streaming, export).
- <strong><a href="{base}/docs/streaming">Streaming</a></strong> — millions of rows in fixed memory.
- <strong><a href="{base}/api">API reference</a></strong> — every export, organized by section.
- **GitHub:** [`office-kit/xlsx`](https://github.com/office-kit/xlsx)
