Spredin

File formats

This is the same document you'll find inside Spredin under Help.

Spredin reads and writes several formats. Each one carries a different amount of your work. This page is the plain-language map: pick .sprd to keep everything, Excel to hand off to Excel/Sheets, CSV/TSV or JSON for raw values.


The one-line summary#

You want to… Use Menu
Keep a perfect copy of your work .sprd File → Save (or turn on AutoSave)
Give it to an Excel / Google Sheets user .xlsx (all sheets) File → Export Workbook as Excel…
Feed raw values to another tool or an agent .json (all sheets) File → Export Workbook as JSON…
One flat table of values .csv / .tsv (active sheet) File → Export Sheet as CSV… / Export Sheet as TSV…
A page to print, send or file .pdf (sheet, selection or workbook, as page setup lays it out) File → Print… (⌘P) or File → Export as PDF…

Golden rule: work in .sprd. It is the only format that preserves everything — and it is open, human-readable JSON you (or an agent) can read, diff, and generate.


Opening an Excel file — what survives, and what does not#

The table above is about saving. This one is about the other direction: you double-click a colleague's workbook and open it here. It is a different question with a different answer, and the honest version is that Spredin brings across your data and its formatting and leaves behind Excel's automation and drawing layers.

Ways to open a file. File → Open… (⌘O); a double-click in the Finder or Open With → Spredin (it is listed for .sprd, .xlsx, .xlsm, .xls, .csv and .tsv); a drop on Spredin's Dock icon; or a drop on a Spredin window. An untitled, unchanged window takes the file itself; any other window opens it in a window of its own, so nothing you have open is replaced.

✅ kept · 🟡 partial · ❌ dropped

What's in the Excel file .xlsx .xls
Cell values, all sheets ✅ ✅
Formulas ✅ ❌ (values imported instead — see below)
Number formats (dates, currency, %) ✅ ❌
Date and time formats as Excel wrote them (d mmm yyyy, h:mm AM/PM, elapsed [h]:mm) ✅ kept and written back unchanged; a date typed in Excel stays "your region's short date" ❌
Fonts, sizes, bold/italic/underline ✅ ❌
Text and fill colours, incl. theme colours ✅ ❌
Borders (presence) 🟡 no per-edge style ❌
Alignment, vertical alignment, wrap ✅ ❌
Merged cells ✅ ❌
Column widths / row heights ✅ ❌
Hidden rows / columns ✅ ❌
Frozen panes ✅ ❌
Cell comments (classic) ✅ ❌
Data validation (dropdowns, rules) ✅ a rule that uses a formula is kept and saved back, but entries are not checked against it; the status line counts such rules ❌
Spilling formulas (Excel 365 dynamic arrays) 🟡 the formula shows its first value; the cells it spilled into keep Excel's last results and do not recalculate; the status line counts them —
Defined names: ranges, whole columns and rows, several areas, constants and formulas, and names that belong to one sheet ✅ ❌
Page setup — paper, orientation, margins, scaling / fit-to-pages, gridlines and headings, centring, header and footer, page breaks, print area, print titles ✅ ❌
Pivot tables ✅ rebuilt as live Spredin pivots; the original is also kept and saved back to .xlsx ❌
Conditional formatting rules 🟡 the kinds Spredin draws — greater/less than, equal to, between, text contains, duplicates, top/bottom N, two-colour scales, data bars — come in as live rules; the others are named when you save as Excel ❌
Charts ✅ drawn by Spredin from the same cells (bar, column, line, area, pie, doughnut, scatter, radar, stock, box & whisker, funnel, treemap, and sunburst drawn as a treemap; Spredin Pro also waterfall, histogram, high-low-close, trendlines). What Spredin draws differently is listed on the chart; a kind it cannot draw — a map, a 3-D surface — shows as a placeholder. Each is kept as Excel wrote it and saved back unchanged unless you change it here ❌
Images, shapes, text boxes 🟡 not shown here; kept, and saved back into .xlsx ❌
Structured tables (Table1[Amount]) ✅ formulas use them; kept, and saved back into .xlsx ❌
The theme, document properties, links to other workbooks, data connections 🟡 kept, and saved back into .xlsx ❌
Slicers, timelines, sparklines, threaded comments, form controls, embedded objects ❌ named when you save as Excel ❌
Macros / VBA (an .xlsm) 🟡 never run, but kept, and saved back into an Excel Macro-Enabled Workbook (.xlsm). Spredin's own automation is the Python panel — real Python with pandas/numpy ❌
Hyperlinks 🟡 not clickable here; kept, and saved back into .xlsx ❌
Sheet & workbook protection ❌ ❌
AutoFilter 🟡 comes in as the values its visible rows show; a condition (> 100, top 10…) becomes those values ❌
Remembered sort state ❌ ❌
Strikethrough, text rotation, indent ❌ ❌
Patterned fills (hatching, e.g. gray125) ❌ solid fills come across; a patterned one arrives unfilled ❌

The short version. Your numbers, formulas, the way the sheet looks and its charts come across from .xlsx. Spredin draws the charts itself, so they can look a little different; each chart says what it leaves out, and while you do not change it, saving as .xlsx writes it back exactly as Excel had it — with the pictures, shapes, pivot tables and links Spredin keeps but does not show. Conditional-formatting rules come across where Spredin draws the same kind. VBA never runs here; the replacement is the Python panel, which is a real programming language with pandas in it — see Coming from Excel?.

How big a workbook can Spredin open?#

The limit is cell count, not file size, and it applies per sheet: 20 million cells in any one sheet. The count is the sheet's whole used rectangle — its rows times its columns, from the first used cell to the last — not only the cells that hold something. A sheet past that is not opened, and the rest of the workbook is: a message names the sheets left out when the workbook opens, and Spredin will not save over that file, because the sheet would be lost from it — save under a new name instead.

In practice a large workbook opens one sheet at a time: the first sheet is usable almost at once while the others load in the background, so a large workbook is workable long before it has finished loading — a sheet still arriving says so, and says how big it is.

If a single sheet is refused: open that one on its own. In Excel, save it as .csv or as its own .xlsx, and open that. Everything else in the workbook is unaffected.

Nothing is lost from the original file. Opening never writes to it. If the import drops something you need, the .xlsx on disk is untouched.

.xls carries data only. See the next section for why — it is not an oversight, it is a different file format wearing a similar name.


Opening a .csv or .tsv — what gets converted#

Encoding and separator are detected. A CSV saved by Excel on Windows (in the Windows code page) opens as readily as a UTF-8 one, with or without a byte-order mark; so does a UTF-16 file that starts with one. A file that separates fields with semicolons — what Excel writes in regions whose decimal separator is a comma — is split on the semicolons, and 15.03.2024 is a date. Whether its numbers use a decimal comma is read from the numbers themselves, since Swiss Excel and many systems write semicolons with decimal points: where a column (or the rest of the file) holds 1,5 or 1.234,56, 1.250 is 1250; where it holds 3.14 or 0.125, 1.250 stays 1.25. A file whose only separated numbers could be either (1.250, 1,234 and nothing else) is not guessed at: those cells keep the text the file had. Spaces between thousands (1 234,56) are read too. Excel's own sep=; first line is honoured. A .tsv is always tab-separated.

Chinese, Japanese and Korean files. Excel in those regions saves a CSV in the region's own code page: GBK (Simplified Chinese), Big5 (Traditional Chinese), Shift-JIS or EUC-JP (Japanese), EUC-KR (Korean). Spredin works out which one from the file's bytes, and uses the languages set in System Settings → Language & Region when the bytes alone cannot tell (a very short file, or a Japanese file written only in half-width kana). The status line names the code page it chose ("Read as Shift-JIS text"), so a wrong choice is not left for you to guess from unreadable text. A file saved as "CSV UTF-8" never needs any of this and is the safest choice to send.

A text file has no types, so the reader has to decide what each field means. Spredin applies exactly the same rule as typing into a cell, so a value behaves the same however it arrived:

In the file Becomes
1,200 · $1,200 · €3.5 · (1,200) · 50% a number with a matching format
0,125 · 00,125 · 1,23,456 text, unchanged — a comma after a zero, or groups that are not three digits, mark no thousands (as in Excel; 01,234 is 1234)
2024-01-15 · 1/15/2024 (or 15/01/2024 on a day-first Mac — the system region decides, as in Excel) · 3/4/25 · 5-Mar-2025 · 5 Mar 2025 · March 5, 2025 · 12:30 · 9:30 PM · 25:00 a date/time serial with a format that shows it as written (a slashed date: the region's short date)
Mar 2025 · 5-Mar · Mar 5 text, unchanged — a month with no day or no year is as often a heading
1200 · -3.5 · 1.2E5 a number
1 1/2 · 2 3/16 · 0 1/4 a number (1.5) with a fraction format, shown as written
TRUE · false a logical value (=A1*5, IF(A1,…)), shown in capitals
#N/A · #DIV/0! · #VALUE! · #REF! · #NAME? · #NUM! · #NULL! that error value: a formula that reads it gets the error, IFERROR and ISNA see it
007 · 00123 text — leading zeros are kept
'007 · 't Hart text, apostrophe included — a file's apostrophe is a character, as in Excel (typed in a cell, '007 is the text 007)
a digit string longer than 15 digits text — every digit is kept
SEPT2 · MARCH1 · 1-3 · 3/4 · +1 (555) 010-1234 text, unchanged
=B2*2 · =SUM(A1:A9) a formula
=== Totals === · =5 units (starts with =, but is no formula) text, shown as the file had it

The 007, long-number and SEPT2 rows are where we deliberately differ from Excel, which turns SEPT2 into a date, drops the zeros from 007, and rounds a long account number away into scientific notation. Spredin does not: a value you can see is a value you can compute with.

A field that starts with = but cannot be read as a formula is kept as text, as Excel keeps it when it opens the file. In the cell it is stored as the formula that returns that text (="=5 units"), which is what you would type to put such text in a cell yourself; it shows, sorts and exports as =5 units.

One consequence worth knowing: because 007 is text, SUM over a column of them is 0 (Excel ignores text inside a range) — while =A1+1 is still 8, since operators coerce number-looking text. That is Excel's own split between operators and aggregation, applied to a value Excel would have converted on the way in.

The Python API is exempt — sheet.set(r, c, "007") writes 007 and sheet.set(r, c, "50%") writes the text 50%, because a script has real types available and literalness is the more useful contract there. The one exception is a date or time: a Python date, datetime, time or timedelta (pandas and numpy ones too), or ISO text such as 2024-01-15 or 2024-01-15T09:30, becomes a real date, time or duration. Add as_text=True to keep any value as text.


.xls vs .xlsx — why the older one loses formatting#

They share a name and nothing else. .xlsx is not ".xls version 2"; it is a complete replacement that happens to serve the same purpose.

.xls (Excel 97–2003) .xlsx (Excel 2007+)
What it actually is a binary OLE2 compound file — a little filesystem of byte records a ZIP of XML documents (rename one to .zip and look inside)
Standard Microsoft's [MS-XLS] binary spec ECMA-376 / ISO 29500, an open standard
Max sheet size 65,536 rows × 256 columns 1,048,576 rows × 16,384 columns
Typical size larger smaller (it is compressed)
Corruption recovery poor — one bad region can take the file good — parts are independent

Because the containers have nothing in common, the high-fidelity reader that pulls styles, merges, freezes and comments out of the .xlsx XML cannot be pointed at a .xls — there is no XML in there to read. Spredin decodes .xls records for their values, and stops there (formulas come in as their values, below; the status line says so when the file opens).

Reading and writing .xls#

What to do instead: open the .xls, work, then File → Export Workbook as Excel… to get .xlsx. Excel 2007 and later open it natively; Excel 2003 opens it with Microsoft's free Compatibility Pack. If your recipient truly cannot take .xlsx, export .csv — every version of Excel ever shipped reads that.

Practical note: opening a .xls and exporting .xlsx is a one-way upgrade of the container. The formatting the .xls had was already dropped on import, so the new file has your data and Spredin's formatting, not the original's.


Save As: choosing a format#

File → Save As… (⇧⌘S) shows a File Format menu under the name: Spredin Workbook (.sprd), Excel Workbook (.xlsx), CSV, TSV and JSON. Type any name — dots and all (Report 30.06.2026) — and the extension is added for you. Typing one of those five extensions yourself (Budget.xlsx) picks that format too. If adding the extension would replace a file that is already there, Spredin asks first.

The menu opens on the format of the file you are working in. A workbook you opened from an Excel file opens on Excel Workbook, in that file's folder and under its name, so ⌘S and Return keep it an Excel file; a new workbook opens on Spredin Workbook.

What each format preserves when Spredin saves or exports#

✅ kept · 🟡 partial · ❌ dropped

Your content .sprd .xlsx .json .csv/.tsv
Cell values ✅ ✅ ✅ ✅
Formulas (=SUM(…)) ✅ ✅ ❌ values only ❌ values only
Number formats, fonts, colours, fills, borders, alignment, wrap ✅ ✅ ❌ ❌
Merged cells ✅ ✅ ❌ ❌
Column widths / row heights ✅ ✅ ❌ ❌
Frozen panes ✅ ✅ ❌ ❌
Cell comments / notes ✅ ✅ ❌ ❌
Data validation (dropdowns / rules) ✅ ✅ ❌ ❌
Defined names (ranges, constants, formulas, names that belong to one sheet) ✅ ✅ ❌ ❌
Conditional formatting ✅ ✅ as live Excel rules ❌ ❌
Page setup (paper, margins, scaling, print area, print titles, header/footer, breaks) ✅ ✅ ❌ ❌
AutoFilter (which rows a filter is hiding) ✅ ✅ ❌ ❌
Structured tables (Table1[Amount]) ✅ 🟡 the tables that came from Excel ❌ ❌
Charts ✅ ✅ Excel charts where Excel has the type; kept as Excel wrote them while unchanged; a picture where Excel has no type — each named before saving ❌ ❌
Pictures, shapes, pivot tables, hyperlinks, the theme and document properties from an Excel file ✅ ✅ written back (a pivot table as Excel's own while unchanged here) ❌ ❌
Pivot tables made or changed in Spredin ✅ live 🟡 as a table of their values, which no longer refreshes in Excel — named before saving ❌ ❌
Macros (VBA) from an Excel file ✅ ✅ in an Excel Macro-Enabled Workbook (.xlsm) only ❌ ❌
Python scripts ✅ ❌ ❌ ❌
The workbook's AutoSave switch, and the id its earlier versions are kept under ✅ ❌ ❌ ❌
Multiple sheets ✅ ✅ ✅ ❌ active sheet only

Anything Spredin-specific — the bundled Python, slides (Spredin Pro), and chart options Excel has no place for — lives only in .sprd. Before an Excel save Spredin names what the file will not hold: scripts, and the slide decks, assistant's notes and kept conversation of a workbook made in Spredin Pro. Conditional formatting is written to .xlsx as Excel's own rule types (cell / text / duplicate / top-N / colour scale / data bar), so it keeps responding to the data over there rather than freezing into fixed fills. Read back IN from .xlsx, the rule kinds Spredin draws come in as live rules too. TRUE/FALSE and error values (#N/A, #DIV/0!…) go into an .xlsx as Excel's own logical values and errors — a cell's, and a formula's saved result — so ISLOGICAL and ISERROR see them, and so does a reader with no formula engine; text that only looks like one ('TRUE) is written, and read back, as text.


The formats, one by one#

Spredin's native format, and the default when you Save. Nothing is lost (unless you turn off Settings → Keep Excel Content in Spredin Files, below). Inside it is plain, human-readable JSON — one compact CSV line per row for the cells, with separate sections for styles, merges, sizes, freeze, conditional formatting, charts, named ranges, the active AutoFilter, structured tables, page setup and the Python files.

In LITE a Spredin Workbook has a size limit. A workbook with a great deal of formatting or cell content can be larger than this edition saves as .sprd. Spredin says so in time — when it opens and when edits bring it close, and whether formatting or contents make it large; the status bar keeps saying it. A save that would be too large writes nothing over your file and offers Save as Excel…; AutoSave pauses and says why.

Spredin and Spredin Pro read each other's .sprd files. A file can carry a part one edition does not have — Pro's assistant memory and slide decks, or a section a newer version adds. The edition that does not know the part keeps it exactly as it was and writes it back when you save, and says so when the file opens, so passing a workbook to a colleague on the other edition never deletes anything. What it cannot do is UPDATE that part: rename a sheet in the free edition and a Pro slide that pointed at it shows its source as missing until you point it again.

Workbooks saved by Spredin Pro open whole, including those Pro saves in its compact form, and Spredin saves them back in its own form, which Pro opens as well. A Pro workbook with more formatting than this LITE version handles is refused with the reason — how much formatting it holds and the most LITE opens; open it in Spredin Pro, or save it from there as Excel. A workbook from a newer version of Spredin that this one cannot read is refused, and says to update.

The file is gzip-compressed — much smaller than the same data as .csv, and usually smaller than .xlsx — but the compression is inside the file rather than in the name: there is one extension to know, and Finder can't mistake a workbook for an archive. .xlsx is secretly a zip and .numbers a package; neither says so either. Spredin reads a .sprd whether or not it is compressed — it checks the file's first two bytes, not its name — so you can gunzip one to read the JSON by hand and it will still open.

Because it's open JSON, an agent or script can read and write it directly. One shape worth knowing: formatting that came from an imported .xlsx is stored the way Excel stores it — a styleTable of the distinct formats plus styleRuns row spans into it — because a real workbook uses a handful of formats across millions of cells, and writing one entry per cell made saving a large import slow enough to look frozen. When styleRuns is present, the styles section holds only the cells you edited yourself, and an empty {} there means "this cell was explicitly cleared". A file with no styleRuns has the whole map in styles, which is how every earlier file reads. A file written by Spredin Pro may carry compactSheets (filled-down ranges and formats written once, as lines); Spredin reads it into cells and writes the full form back.

A file written by hand or by a script is checked as it is read. Spredin either refuses it ("Not a valid .sprd workbook", with the document you had still open) or opens all of it that can be used. One wrong value does not cost the file: a rule, a size, a note or a format that cannot be read is left out alone, and the line that says the file was opened also says that part of it was left out and on which sheets. A few things are put right rather than left out: a number where text belongs (a validation bound written 1, a sheet called 2024) is read as that text, a rule with no id gets one, and two sheets of the same name are renamed apart. A field or a kind of rule this version does not know is kept and written back, not left out. A byte-order mark in front of the JSON is accepted.

.xlsx — Excel / Google Sheets interop#

File → Export Workbook as Excel… writes every sheet (empty ones too) with values, formulas, and per-cell styling (bold/italic/underline, text + fill colours, alignment, wrap, borders, number format, font). Use it to hand data to someone in Excel or Sheets. Charts go across as Excel charts (a picture where Excel has no such chart, named before saving); the Python scripts do not. Conditional formatting goes as Excel's own live rules (see the table above).

Spredin reads .xlsx at high fidelity — all sheets with styling, number formats, merges, sizes, frozen panes, comments, data validation and named ranges. Writing back is .xlsx, or .xlsm for a workbook with macros (the legacy .xls binary format is import-only).

Excel's size limits. An .xlsx holds at most 1,048,576 rows and 16,384 columns (to XFD). What a Spredin sheet holds past them does not fit in an Excel file: Save as Excel and Export say so first, name the sheets, and offer to keep the workbook as a .sprd instead. Nothing is written.

Dates. Excel's own date and time formats come in as they are — 15 Jan 2024, 9:00 AM, 30:00:00 (elapsed hours) — and go back to Excel unchanged. Excel's short date, which every computer shows in its own way, stays a short date: it shows in your region's order here (15/01/2024, or 1/15/2024), and in the reader's own order when the file is opened in Excel again. A date you type with slashes gets that short date; one typed as 2024-01-15 keeps that form. Editing a date cell shows your region's short date (2024-01-15 for a cell in Spredin's own Date format), so what you type back reads as the same date.

Tab colours an Excel file gives its sheets show on Spredin's tabs and go back to Excel. Spredin has no command to set one yet.

Sheet names. Excel caps a sheet name at 31 characters, forbids : \ / ? * [ ], and will not have two sheets with the same name (it compares them case-insensitively, so Sales and sales clash). Spredin applies those rules wherever a name is chosen — renaming a tab refuses a name Excel would not accept, a script's add_sheet raises an error for one, and importing data[2025].csv names the sheet data 2025 — so an ordinary workbook exports unchanged. Renaming a tab updates every formula and defined name that referred to it, in the same undo step, as Excel does. A workbook saved by an older version can still hold an illegal name; export makes it legal and rewrites the formulas and names that point at it, so the file still adds up.

Identifiers stay text. A cell holding 007, a ZIP code or a 16-digit account number is text in Spredin, and it is written to Excel as text, so no leading zero or trailing digit is lost.

Defined names are written absolute (Data!$B$2). Excel reads a name without $ as relative to the cell using it; Spredin treats names as fixed ranges either way, and the export makes Excel agree.

Very long text. Excel holds at most 32,767 characters in a cell. If a cell holds more, Spredin names the cells and asks before writing the .xlsx; the exported copy has that text cut to fit, and your workbook keeps it in full.

.json — plain values out (export only)#

File → Export Workbook as JSON… writes every sheet's computed values as { "sheets": [ { "name": "Sheet1", "rows": [[…], …] } ] }. Formulas are evaluated to their results; no styling, formulas or other Spredin-specific metadata is included — it's the clean data, nothing else. It's the easiest format for another program or an AI agent to consume.

Export only. Spredin does not open arbitrary .json files (there's no single "right" way to lay an arbitrary JSON schema onto a grid). To bring JSON data in, convert it to .csv/.xlsx first, or parse it in the Python panel (import json) and sheet.write(...) the rows you want.

.csv / .tsv — one flat table of values#

The active sheet's computed values only. No formulas, no styling, no other sheets — just a grid of text. Best for piping raw data into another tool. .tsv uses tabs instead of commas.

Dates and times are written as they display (2024-01-15), so they read as dates in any tool and come back as dates when the file is opened here again. Other numbers are written plain — $1,200.50 becomes 1200.5 — which every tool reads as a number. The JSON export follows the same rule.

The text is UTF-8. A file that holds any character beyond plain ASCII — an accent, €, Chinese, Japanese, Korean, an emoji — starts with a UTF-8 byte-order mark, which is how Excel (on Windows and on the Mac) knows to read it as UTF-8; without the mark it reads the file in an older code page and garbles those characters. A file of plain ASCII has no mark and is the same, byte for byte, as before. Spredin reads its own files back either way. A few programmer tools see the mark as a stray character at the start of the first heading (Python's csv module reads it right with encoding='utf-8-sig'). The JSON export never has a mark.


Round-trip expectations (important)#


For agents#

Opening an untrusted spreadsheet is safe: Spredin never runs anything stored inside a file, and its readers are hardened against malformed input.

External-workbook references#

Excel writes a reference into another file as '[1]Sheet Name'!$A$1, where [1] points at a link to that other workbook. Opening the workbook here does not open the linked file; Spredin works the reference out in this order:

  1. The values Excel saved for the link. An .xlsx keeps a copy of every value it last read from the linked file, and Excel itself shows those until you refresh the link. Spredin uses them the same way, and keeps them when you save as .sprd.
  2. A sheet of the same name in this workbook, when the saved values do not cover that sheet. Links often point at an earlier copy of the same model, so the sheet is usually here too.
  3. Otherwise the cell shows #REF!. Inventing a target would produce a confident wrong number, which is worse than an error.

The formula itself is not changed: it still names the other file, as Excel wrote it.