SheetNext JSON Format
Manual supplemental document. This file is not generated by
scripts/doc-scanner.js.
Purpose
SN.IO.getData() exports the current workbook into a JSON object.
SN.IO.setData(data) restores a workbook from the same structure.
This document describes the transport format used by those two APIs.
Versioning
- Current version:
2.0 setDatarequires:data.version === "2.0"data.sheetsto be a non-empty array
If either check fails, setData returns false.
Top-Level Shape
{
"version": "2.0",
"workbookName": "Book1",
"activeSheet": "Sheet1",
"calcMode": "auto",
"readOnly": false,
"properties": {},
"definedNames": {},
"styleTable": {
"fonts": [],
"fills": [],
"borders": [],
"aligns": [],
"styles": []
},
"sizeTable": {
"rowHeights": [],
"colWidths": []
},
"sheets": []
}
Top-Level Fields
| Field | Type | Required | Notes |
|---|---|---|---|
version |
string | Yes | Must currently be "2.0" |
workbookName |
string | No | Workbook display name |
activeSheet |
string | null | No | Active sheet name to restore |
calcMode |
"auto" | "manual" |
No | Defaults to auto on import |
readOnly |
boolean | No | Workbook read-only state |
properties |
object | No | Workbook custom properties |
definedNames |
object | No | Workbook-level defined names |
styleTable |
object | Yes | Deduplicated shared style pools |
sizeTable |
object | Yes | Deduplicated row/column size pools |
sheets |
array | Yes | Workbook sheet list |
pivotCaches |
array | No | Pivot cache payloads |
slicerCaches |
array | No | Slicer cache payloads |
_snTrace |
any | No | Internal/export trace marker |
Shared Tables
styleTable and sizeTable are shared lookup tables.
Instead of storing the same style or size object repeatedly on every cell/row/column, SheetNext stores the object once in a table and references it by index.
styleTable
| Field | Type | Used By |
|---|---|---|
fonts |
array | cell fo |
fills |
array | cell fi |
borders |
array | cell b |
aligns |
array | cell a |
styles |
array | row s, column s, cell s |
sizeTable
| Field | Type | Used By |
|---|---|---|
rowHeights |
array<number> | row h |
colWidths |
array<number> | column w |
Sheet Shape
Each item in sheets looks like this:
{
"name": "Sheet1",
"hidden": false,
"showGridLines": true,
"showRowColHeaders": true,
"showPageBreaks": false,
"outlinePr": {},
"frozenCols": 0,
"frozenRows": 0,
"freezeStartRow": 0,
"freezeStartCol": 0,
"defaultColWidth": 72,
"defaultRowHeight": 21,
"zoom": 1,
"activeCell": { "r": 0, "c": 0 },
"viewStart": { "r": 0, "c": 0 },
"printSettings": null,
"rowCount": 200,
"colCount": 32,
"cols": [],
"rows": [],
"merges": [],
"drawings": []
}
Common Sheet Fields
| Field | Type | Notes |
|---|---|---|
name |
string | Sheet name |
hidden |
boolean | Hidden sheet state |
showGridLines |
boolean | Gridline visibility |
showRowColHeaders |
boolean | Row/column header visibility |
showPageBreaks |
boolean | Page break visibility |
outlinePr |
object | Outline options |
frozenCols |
number | Frozen column count |
frozenRows |
number | Frozen row count |
freezeStartRow |
number | Freeze split start row |
freezeStartCol |
number | Freeze split start column |
defaultColWidth |
number | Default width in px |
defaultRowHeight |
number | Default height in px |
zoom |
number | Import is clamped to 0.1 to 4 |
activeCell |
{r,c} |
Active cell |
viewStart |
{r,c} |
View origin |
printSettings |
object | null | Print config |
rowCount |
number | Sheet size hint |
colCount |
number | Sheet size hint |
sheetProtection |
object | Optional sheet protection config |
Optional Sheet Sections
These sections are included only when data exists:
colsrowsmergesdrawingssparklinescommentstablesautoFilterscfRulespivotTablesslicers
Column Records
{
"cIndex": 0,
"w": 3,
"hidden": false,
"ol": 1,
"cl": false,
"s": 2
}
| Field | Type | Notes |
|---|---|---|
cIndex |
number | Zero-based column index |
w |
number | Index into sizeTable.colWidths |
hidden |
boolean | Hidden column |
ol |
number | Outline level |
cl |
boolean | Collapsed state |
s |
number | Index into styleTable.styles |
Row Records
{
"rIndex": 0,
"h": 4,
"hidden": false,
"ol": 1,
"cl": false,
"s": 5,
"cells": []
}
| Field | Type | Notes |
|---|---|---|
rIndex |
number | Zero-based row index |
h |
number | Index into sizeTable.rowHeights |
hidden |
boolean | Hidden row |
ol |
number | Outline level |
cl |
boolean | Collapsed state |
s |
number | Index into styleTable.styles |
cells |
array | Cell payload list |
Cell Records
Cell payloads are stored inside row.cells.
{
"c": 0,
"v": "Hello",
"vt": "string",
"s": 1
}
Cell Position Fields
| Field | Type | Notes |
|---|---|---|
c |
number | Start column index |
e |
number | Optional end column index for repeated identical cells |
If e is present, the same decoded cell template is applied from c through e inclusive.
Cell Value Fields
| Field | Type | Notes |
|---|---|---|
v |
any | Raw cell value |
vt |
string | null | Value type marker |
f |
string | Formula string; importer ensures a leading = |
cv |
any | Cached formula result |
cvt |
string | null | Cached result type marker |
Supported type markers:
datetimedateTimenaninf-inf
Cell Style Fields
| Field | Type | Notes |
|---|---|---|
s |
number | Index into styleTable.styles |
fo |
number | Index into styleTable.fonts |
fi |
number | Index into styleTable.fills |
b |
number | Index into styleTable.borders |
a |
number | Index into styleTable.aligns |
fmt |
string | Number format |
p |
object | Protection overrides |
Cell Feature Fields
| Field | Type | Notes |
|---|---|---|
link |
object | Hyperlink payload |
dv |
object | Data validation payload |
rt |
array | Rich text runs |
Hyperlink shape:
{
"t": "https://example.com",
"l": null,
"tt": "Open link"
}
Merge Records
Each merge item is a normalized range object:
{
"s": { "r": 0, "c": 0 },
"e": { "r": 1, "c": 2 }
}
Drawing Records
Basic drawing shape:
{
"type": "image",
"startCell": { "r": 1, "c": 1 },
"offsetX": 0,
"offsetY": 0,
"width": 240,
"height": 120,
"anchorType": "twoCell",
"rotation": 0
}
Additional drawing fields depend on type:
chart:chartOptionimage:imageBase64shape/connector:shapeType,shapeStyle,shapeText,isTextBox
Other Optional Sections
Sheet-level optional payloads:
sparklinescommentstablesautoFilterscfRulespivotTablesslicers
Workbook-level optional payloads:
pivotCachesslicerCaches
These sections are round-tripped by getData / setData, but many of them are larger feature-specific payloads and are best produced by exporting an existing workbook first.
Dynamic Value Wrapper
Some advanced cache payloads use a typed wrapper so special values survive JSON serialization:
{
"__sn_json_type": "date",
"__sn_json_value": "2026-03-17T00:00:00.000Z"
}
Possible wrapper types:
datenaninf-inf
Minimal Example
{
"version": "2.0",
"workbookName": "Demo",
"activeSheet": "Sheet1",
"calcMode": "auto",
"readOnly": false,
"properties": {},
"definedNames": {},
"styleTable": {
"fonts": [],
"fills": [],
"borders": [],
"aligns": [],
"styles": []
},
"sizeTable": {
"rowHeights": [],
"colWidths": []
},
"sheets": [
{
"name": "Sheet1",
"hidden": false,
"showGridLines": true,
"showRowColHeaders": true,
"showPageBreaks": false,
"outlinePr": {},
"frozenCols": 0,
"frozenRows": 0,
"freezeStartRow": 0,
"freezeStartCol": 0,
"defaultColWidth": 72,
"defaultRowHeight": 21,
"zoom": 1,
"activeCell": { "r": 0, "c": 0 },
"viewStart": { "r": 0, "c": 0 },
"printSettings": null,
"rowCount": 10,
"colCount": 10,
"cols": [],
"rows": [
{
"rIndex": 0,
"h": 0,
"cells": [
{ "c": 0, "v": "Name" },
{ "c": 1, "v": "Score" }
]
},
{
"rIndex": 1,
"h": 0,
"cells": [
{ "c": 0, "v": "Alice" },
{ "c": 1, "v": 95 }
]
}
],
"merges": [],
"drawings": []
}
]
}
Recommended Workflow
If you need to generate JSON externally:
- create a workbook in SheetNext
- export it with
SN.IO.getData() - treat that JSON as the baseline contract
- modify only the sections you need
- import it back with
SN.IO.setData(data)
This is the safest way to stay aligned with future feature additions.