export format

Calcillo documents can be exported as self-contained JSON files for backup, sharing, and interoperability.

File Format

  • File extension: .calcillo
  • Content type: application/vnd.cloudillo.calcillo+json
  • Format version: 3.0.0
  • Encoding: UTF-8 JSON
v3 generic export format

Since format version 3.0.0, Calcillo uses the generic exportYDoc() serializer from @cloudillo/crdt. All Yjs types carry inline @T type markers and data keys match the raw CRDT shared type names. See v3 Generic Export Format for the full specification.

Envelope Structure

{
  "contentType": "application/vnd.cloudillo.calcillo+json",
  "appVersion": "0.1.0",
  "formatVersion": "3.0.0",
  "exportedAt": "2026-02-20T10:00:00.000Z",
  "data": {
    "meta": { "@T": "M", ... },
    "sheetOrder": [ "@T:A", ... ],
    "sheets": { "@T": "M", ... }
  }
}

Envelope Fields

Field Type Description
contentType string Always "application/vnd.cloudillo.calcillo+json"
appVersion string Calcillo version that created this export
formatVersion string Export format version (currently "3.0.0")
exportedAt string ISO 8601 timestamp of export

Data Fields

Key @T Yjs Type Description
meta M Y.Map Document metadata (name, initialized flag)
sheetOrder A Y.Array<SheetId> Sheet IDs in tab order
sheets M Y.Map<YSheetStructure> All sheets keyed by SheetId

Sheet Structure

Each sheet in the sheets map is a Y.Map (@T: "M") containing nested shared types:

Key @T Yjs Type Description
name T Y.Text Sheet name (with text and delta fields)
rowOrder A Y.Array<RowId> Row IDs in display order
colOrder A Y.Array<ColId> Column IDs in display order
rows M Y.Map<Y.Map<Cell>> Nested: rowId → colId → Cell
merges M Y.Map<MergeInfo> Merge definitions keyed by composite key
borders M Y.Map<BorderInfo> Border definitions keyed by composite key
hyperlinks M Y.Map<HyperlinkInfo> Hyperlink definitions keyed by composite key
validations M Y.Map<ValidationRule> Validation rules keyed by validation ID
conditionalFormats A Y.Array<ConditionalFormat> Ordered conditional formatting rules
hiddenRows M Y.Map<boolean> Hidden row flags
hiddenCols M Y.Map<boolean> Hidden column flags
rowHeights M Y.Map<number> Custom row heights in pixels
colWidths M Y.Map<number> Custom column widths in pixels
frozen M Y.Map<string | number> Freeze pane settings
Sheet names are Y.Text in v3

The name field is serialized as a Y.Text with @T: "T", containing both text and delta fields. This preserves any concurrent edit state. In pre-v3 exports, sheet names were plain text strings from Y.Text.toString().

Default cell values are stripped

Calcillo applies a transformSheets post-processing step that removes default cell property values to reduce export size. Empty rows (containing only the @T marker) are also omitted.

Numeric Precision

All numeric values are rounded to 3 decimal places in the export to produce cleaner output. Cell values retain their original precision.

Complete Example

A spreadsheet with 2 sheets. The first sheet has values, a formula, styling, a merge, and a border. The second sheet is a simple data table.

{
  "contentType": "application/vnd.cloudillo.calcillo+json",
  "appVersion": "0.1.0",
  "formatVersion": "3.0.0",
  "exportedAt": "2026-02-20T10:00:00.000Z",
  "data": {
    "meta": {
      "@T": "M",
      "initialized": true,
      "name": "Q1 Sales Report"
    },
    "sheetOrder": ["@T:A", "aB3x_Qm7kL9p", "Xk2nR8vH_wYq"],
    "sheets": {
      "@T": "M",
      "aB3x_Qm7kL9p": {
        "@T": "M",
        "name": {
          "@T": "T",
          "text": "Summary",
          "delta": [{ "insert": "Summary" }]
        },
        "rowOrder": ["@T:A", "r_Hw5qT2m", "r_m4JfL1p", "r_Nz9cKvW", "r_Qp4rW9x"],
        "colOrder": ["@T:A", "cAb3x", "cXk2n", "cM4Jf", "cNz9c"],
        "rows": {
          "@T": "M",
          "r_Hw5qT2m": {
            "@T": "M",
            "cAb3x": {
              "@T": "M",
              "v": "Product",
              "bl": 1,
              "bg": "#e3f2fd",
              "ht": 2
            },
            "cXk2n": {
              "@T": "M",
              "v": "Q1",
              "bl": 1,
              "bg": "#e3f2fd",
              "ht": 2
            },
            "cM4Jf": {
              "@T": "M",
              "v": "Q2",
              "bl": 1,
              "bg": "#e3f2fd",
              "ht": 2
            },
            "cNz9c": {
              "@T": "M",
              "v": "Total",
              "bl": 1,
              "bg": "#e3f2fd",
              "ht": 2
            }
          },
          "r_m4JfL1p": {
            "@T": "M",
            "cAb3x": { "@T": "M", "v": "Widget A" },
            "cXk2n": {
              "@T": "M",
              "v": 15000,
              "ct": { "@T": "M", "t": "n", "fa": "$#,##0.00" }
            },
            "cM4Jf": {
              "@T": "M",
              "v": 18500,
              "ct": { "@T": "M", "t": "n", "fa": "$#,##0.00" }
            },
            "cNz9c": {
              "@T": "M",
              "v": 33500,
              "f": "=B2+C2",
              "ct": { "@T": "M", "t": "n", "fa": "$#,##0.00" },
              "bl": 1
            }
          },
          "r_Nz9cKvW": {
            "@T": "M",
            "cAb3x": { "@T": "M", "v": "Widget B" },
            "cXk2n": {
              "@T": "M",
              "v": 22000,
              "ct": { "@T": "M", "t": "n", "fa": "$#,##0.00" }
            },
            "cM4Jf": {
              "@T": "M",
              "v": 19800,
              "ct": { "@T": "M", "t": "n", "fa": "$#,##0.00" }
            },
            "cNz9c": {
              "@T": "M",
              "v": 41800,
              "f": "=B3+C3",
              "ct": { "@T": "M", "t": "n", "fa": "$#,##0.00" },
              "bl": 1
            }
          },
          "r_Qp4rW9x": {
            "@T": "M",
            "cAb3x": {
              "@T": "M",
              "v": "Grand Total",
              "bl": 1,
              "it": 1
            },
            "cNz9c": {
              "@T": "M",
              "v": 75300,
              "f": "=D2+D3",
              "ct": { "@T": "M", "t": "n", "fa": "$#,##0.00" },
              "bl": 1,
              "bg": "#fff9c4"
            }
          }
        },
        "merges": {
          "@T": "M",
          "r_Qp4rW9x_cAb3x": {
            "@T": "M",
            "startRow": "r_Qp4rW9x",
            "endRow": "r_Qp4rW9x",
            "startCol": "cAb3x",
            "endCol": "cM4Jf"
          }
        },
        "borders": {
          "@T": "M",
          "r_Hw5qT2m_cAb3x": {
            "@T": "M",
            "bottom": { "@T": "M", "style": 2, "color": "#1565c0" }
          },
          "r_Hw5qT2m_cXk2n": {
            "@T": "M",
            "bottom": { "@T": "M", "style": 2, "color": "#1565c0" }
          },
          "r_Hw5qT2m_cM4Jf": {
            "@T": "M",
            "bottom": { "@T": "M", "style": 2, "color": "#1565c0" }
          },
          "r_Hw5qT2m_cNz9c": {
            "@T": "M",
            "bottom": { "@T": "M", "style": 2, "color": "#1565c0" }
          }
        },
        "hyperlinks": { "@T": "M" },
        "validations": { "@T": "M" },
        "conditionalFormats": ["@T:A"],
        "hiddenRows": { "@T": "M" },
        "hiddenCols": { "@T": "M" },
        "rowHeights": { "@T": "M" },
        "colWidths": {
          "@T": "M",
          "cAb3x": 150,
          "cXk2n": 120,
          "cM4Jf": 120,
          "cNz9c": 120
        },
        "frozen": {
          "@T": "M",
          "type": "row",
          "rowIndex": 1
        }
      },
      "Xk2nR8vH_wYq": {
        "@T": "M",
        "name": {
          "@T": "T",
          "text": "Raw Data",
          "delta": [{ "insert": "Raw Data" }]
        },
        "rowOrder": ["@T:A", "r_Jx8mP3q", "r_Vn4wK7r", "r_Bt6yH2s"],
        "colOrder": ["@T:A", "cPq7r", "cWm3s"],
        "rows": {
          "@T": "M",
          "r_Jx8mP3q": {
            "@T": "M",
            "cPq7r": { "@T": "M", "v": "Date", "bl": 1 },
            "cWm3s": { "@T": "M", "v": "Amount", "bl": 1 }
          },
          "r_Vn4wK7r": {
            "@T": "M",
            "cPq7r": {
              "@T": "M",
              "v": "2026-01-15",
              "ct": { "@T": "M", "t": "t", "fa": "yyyy-mm-dd" }
            },
            "cWm3s": {
              "@T": "M",
              "v": 5200,
              "ct": { "@T": "M", "t": "n", "fa": "#,##0" }
            }
          },
          "r_Bt6yH2s": {
            "@T": "M",
            "cPq7r": {
              "@T": "M",
              "v": "2026-02-01",
              "ct": { "@T": "M", "t": "t", "fa": "yyyy-mm-dd" }
            },
            "cWm3s": {
              "@T": "M",
              "v": 7800,
              "ct": { "@T": "M", "t": "n", "fa": "#,##0" }
            }
          }
        },
        "merges": { "@T": "M" },
        "borders": { "@T": "M" },
        "hyperlinks": { "@T": "M" },
        "validations": { "@T": "M" },
        "conditionalFormats": ["@T:A"],
        "hiddenRows": { "@T": "M" },
        "hiddenCols": { "@T": "M" },
        "rowHeights": { "@T": "M" },
        "colWidths": { "@T": "M" },
        "frozen": { "@T": "M" }
      }
    }
  }
}

In this example:

  • Summary sheet (aB3x_Qm7kL9p):
    • Header row with bold text, blue background, and centered alignment
    • Product data with currency formatting ($#,##0.00)
    • Formula cells computing totals (=B2+C2, =B3+C3, =D2+D3)
    • “Grand Total” row with a merge spanning columns A-C and italic styling
    • Medium blue bottom border on all header cells
    • Custom column widths (150px for product name, 120px for data columns)
    • Frozen first row (header stays visible while scrolling)
  • Raw Data sheet (Xk2nR8vH_wYq):
    • Simple 2-column table with date and amount data
    • Date cells with yyyy-mm-dd format, number cells with thousands separator
    • No merges, borders, or custom sizing (all defaults)
  • All Y.Map entries carry "@T": "M", arrays carry "@T:A", and sheet names are Y.Text with "@T": "T"