Excel Import & Export (with Merged Cells)
Read an .xlsx workbook into GridSheet and write it back out with
@gridsheet/xlsx. Values, formulas (including
cross-sheet references), cell styles, column widths / row heights and merged cells come through
both ways. The demo loads a three-sheet sample whose titles are merged — or open (or drop) any .xlsx
file of your own, edit it, and download the result.
Open any .xlsx file (or drop one here) — the sample loads by default and its titles are merged cells. Edit values or select a range and right-click → Merge cells, then download and open the result in Excel or another spreadsheet app.
Implementation Guide
Section titled “Implementation Guide”npm install @gridsheet/xlsx@gridsheet/xlsx is headless (no DOM, no framework) — it converts bytes ⇄ GridSheet data, so it
works the same in the browser and in Node.
Import: fromXlsx
Section titled “Import: fromXlsx”fromXlsx takes the file’s bytes and returns one { matrices, cells } per sheet — exactly the shape
buildInitialCells accepts:
import { fromXlsx } from '@gridsheet/xlsx';
const workbook = fromXlsx(new Uint8Array(await file.arrayBuffer()));// { Sales: { matrices, cells }, 'Meta Data': { ... }, Summary: { ... } }matricesholds the values; formulas arrive as their"=..."text.cellsholds per-cell styles, column widths / row heights, and merged ranges — a merge is stored on its top-left cell asmerge: { rows, cols }(an ExcelA1:D1becomesA1: { merge: { rows: 1, cols: 4 } }).
Render every sheet into one shared book so cross-sheet formulas such as =SUM(Sales!D3:D5) resolve:
const book = useSpellbook({});
{Object.entries(workbook).map(([name, data]) => ( <GridSheet key={name} book={book} sheetName={name} sheetRef={refs.current[name]} initialCells={buildInitialCells(data)} />))}initialCells is read only on mount, so remount the sheets (e.g. change a key) when a new file is opened.
Export: toXlsx
Section titled “Export: toXlsx”toXlsx takes a map of sheet name → live sheet and returns the workbook as bytes. Passing the live
sheets (from each sheetRef) includes the user’s edits and any cells they merged or unmerged:
import { toXlsx } from '@gridsheet/xlsx';
const sheets = Object.fromEntries( Object.entries(refs.current).map(([name, ref]) => [name, ref.current!.sheet]),);const blob = new Blob([toXlsx(sheets)], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',});// …then download it (object URL + <a download>) or upload it.toXlsx also accepts plain value matrices ([['Name', 'Qty'], ['Apple', 3]]) or cell matrices, for
generating a file without rendering a grid.
Merged cells
Section titled “Merged cells”Users merge and unmerge from the right-click menu (Merge cells / Unmerge cells); in code,
put merge: { rows, cols } on the anchor cell of initialCells. The covered cells stay empty —
only the anchor holds a value, as in Excel.
What isn’t converted
Section titled “What isn’t converted”Number formats (e.g. currency or date display formats), borders, frozen panes and charts are not read or written. Formula results aren’t cached in the file; spreadsheet apps recalculate on open.