formulas.md explains where arrays come from, what spills and how spilled cells behave, LET and LAMBDA's names, and the REGEX functions; files.md how spills go to and come from XLSX and why the file keeps only the formula. Co-Authored-By: Claude <noreply@anthropic.com>
- commit
- 7497bb78c112b4528295fa7bb254e312f8ee4d70
- parent
- b1aa3d3a98cb3f470668bcf9357610c0fa00aff5
- author
- Dami <dami.etoile@gmail.com>
| M | docs/ | 26 | +++++++- |
| M | docs/ | 100 | +++++++++++++++++++++++++++--- |
@@ -19,11 +19,32 @@ File > Import asks where the data goes, as Sheets' Import location does
1919 | Format | Import | Download |2020 |---|---|---|2121 | CSV, TSV | Delimiter (`,` `;` tab `\|`), UTF-8 BOM, UTF-16 and Windows-1252 detected; entries become numbers, dates, currency and percentages as if typed; formulas stay text | Values as shown, as Sheets' Download does |22-| Excel `.xlsx` | Every sheet, opening on the one Excel showed: values, formulas (references between sheets too), workbook named ranges, number formats, bold, italic, underline, strikethrough, alignment, column widths, column and row styles, frozen panes, filters (see [Filters in XLSX](#filters-in-xlsx)), shared formulas, dates in the 1904 system; sheets Excel hid stay hidden (unless it's the one Excel showed). Formulas 012 can't read (unknown functions) keep their values; Excel pivot tables come in as the values they showed. Files past the reader's limits (a zip bomb, 1 GB in one part, 2 GB in all, cells past XFD1048576) are refused with a message saying which | Every sheet, the same, with formulas in Excel's syntax and their results cached, column and row formats as column and row styles, frozen rows and columns as frozen panes, and a filter as Excel's with the rows it hides hidden. A sheet whose name Excel can't take as is (spaces at its ends, or the same as another's but for them and case) gets one it can (without the spaces, with a number when two would clash, e.g. `Plan (2)`), and the formulas and named ranges naming it name that. JEV functions and `#AND#` save as values, and so do formulas naming a sheet that doesn't exist (their `#REF!`; Excel would refuse the reference), and pivot tables: Excel gets the results, not a pivot. The download's result counts the formulas saved as values, with an example |22+| Excel `.xlsx` | Every sheet, opening on the one Excel showed: values, formulas (references between sheets too), workbook named ranges, number formats, bold, italic, underline, strikethrough, alignment, column widths, column and row styles, frozen panes, filters (see [Filters in XLSX](#filters-in-xlsx)), shared formulas, dates in the 1904 system; sheets Excel hid stay hidden (unless it's the one Excel showed). Formulas 012 can't read (unknown functions) keep their values; Excel pivot tables come in as the values they showed. Array formulas (Excel 365's dynamic arrays and older `{=...}` ones) come in as formulas that spill again, without the values Excel kept in the cells they spilled into. Files past the reader's limits (a zip bomb, 1 GB in one part, 2 GB in all, cells past XFD1048576) are refused with a message saying which | Every sheet, the same, with formulas in Excel's syntax and their results cached, column and row formats as column and row styles, frozen rows and columns as frozen panes, and a filter as Excel's with the rows it hides hidden. A sheet whose name Excel can't take as is (spaces at its ends, or the same as another's but for them and case) gets one it can (without the spaces, with a number when two would clash, e.g. `Plan (2)`), and the formulas and named ranges naming it name that. A formula that spills goes out as Excel 365's dynamic array formula, with the values it spilled in the cells, so Excel spills it the same and older Excels show the values; see [Arrays in XLSX](#arrays-in-xlsx). JEV functions and `#AND#` save as values, and so do formulas naming a sheet that doesn't exist (their `#REF!`; Excel would refuse the reference), functions only Sheets has (`SORTN`, `FLATTEN`, `SPLIT`, `REGEXMATCH`, `REGEXEXTRACT`), and pivot tables: Excel gets the results, not a pivot. The download's result counts the formulas saved as values, with an example |2323 | SQLite | Pick a table or view, or type a query; a header row names the columns | The sheet shown or the selection as a table, first row as column names; a table of that name is replaced |2424 | Parquet | Every column, with dates and timestamps; lists joined with commas | |2525 | Lotus 1-2-3 `.wk1`, `.wks` | Numbers, labels with their alignment, formats, column widths, formulas translated (references, operators, `@SUM`, `@AVG`, `@IF`, `@ROUND`, `@PMT` and 60 more) or kept as values | |2626 27+## Arrays in XLSX28+29+A formula whose array spills (see [formulas.md](formulas.md#arrays-and-spills))30+is written as Excel writes a dynamic array formula: an array formula over31+the cells it spills into (`<f t="array" ref="C1:C9">`) on a cell whose32+metadata marks it dynamic (`cm="1"`, defined in `xl/metadata.xml`), with33+the values in the cells below and right of it. Formulas calling array34+functions (`FILTER`, `SORT`, `UNIQUE`, `SEQUENCE`, `LET`, `LAMBDA` and the35+like) or holding an array literal are written that way even when they36+compute one value, so Excel doesn't put its implicit intersection (`@`)37+in front of them. Excel gets its own names for the functions newer than38+Excel 2007 (`_xlfn._xlws.FILTER`, `_xlfn.SEQUENCE`), `_xlpm.` before the39+names LET and LAMBDA bind, and the formula inside an `ARRAYFORMULA` around40+a whole formula, which a dynamic array formula computes over arrays41+anyway. What Excel can't hold goes out as the value it showed, counted in42+the download's note: functions only Sheets has (`SORTN`, `FLATTEN`,43+`SPLIT`, `REGEXMATCH`, and `REGEXEXTRACT`, whose Excel namesake returns44+the whole match where Sheets' returns the capture group), array literals45+holding references (Excel's hold only constants) and `ARRAYFORMULA`46+inside a formula.47+2748 ## Filters in XLSX2849 2950 A sheet's filter goes out as Excel's AutoFilter over the same range, and@@ -169,7 +190,8 @@ A workbook with a pivot table is version 5: version 4 with a `pivot`
169190 field, on one line after the cells of the pivot's sheet, holding its170191 definition. The results are never saved; they are computed again when171192 the file opens, so the file stays small and can't disagree with its172-data. Builds that know only version 4 refuse the file rather than show an193+data. Arrays that formulas spill are the same: the file keeps the formula,194+and the cells it spills into only for their formatting. Builds that know only version 4 refuse the file rather than show an173195 empty sheet; a workbook without pivots is still written as version 4.174196 175197 ```json@@ -78,26 +78,104 @@ tighter than `^` as in Sheets and Excel, so `=-2^2` is 4. 1-2-3's `#AND#`,
7878 7979 ## A range where one value is wanted8080 81-A range used where a formula wants one value (with an operator, as an82-argument that takes a number or text, or as a cell's whole result) reads83-as one of its cells, as in Sheets and Excel (implicit intersection):81+A range used where a formula wants one value (with an operator, or as82+an argument that takes a number or text) reads as one of its cells, as83+in Sheets and Excel (implicit intersection):8484 8585 - a single column gives the cell in the formula's own row, so with the8686 named range Rent = B2:B4, `=Rent*2` in F4 is B4*2 and `=B:B+1` in G5 is8787 B5+1;88-- a single row gives the cell in the formula's own column: `=B6:D6` in C889- is C6;88+- a single row gives the cell in the formula's own column: `=B6:D6+1` in89+ C8 is C6+1;9090 - a single cell is itself;9191 - anything else is `#VALUE!`: a formula outside the range's rows (or9292 columns), and a range of several rows and columns.9393 9494 Ranges on other sheets work the same, by the formula's row or column:95-`='Q3 plan'!C2:C9` in A3 reads `'Q3 plan'!C3`. Functions that take ranges96-(`SUM`, `COUNTIF`, `MATCH`, `VLOOKUP`, `SUMPRODUCT` and the like)97-read the whole range. Inside their range arguments an expression over98-ranges, such as `SUM(B2:B4*2)` or `SUMPRODUCT(A1:A3*B1:B3)`, is `#VALUE!`:99-Sheets computes those as arrays, which 012 doesn't, and a single cell's100-answer there would be wrong rather than missing.95+`='Q3 plan'!C2:C9*10` in A3 reads `'Q3 plan'!C3`. A range that is a96+cell's whole formula, `=B2:B4` or `=Rent`, is an array and spills, as in97+Sheets (see [Arrays and spills](#arrays-and-spills)). Functions that98+take ranges (`SUM`, `COUNTIF`, `MATCH`, `VLOOKUP`, `SUMPRODUCT` and the99+like) read the whole range, and an expression given to them is computed100+over arrays: `SUM(B2:B4*2)` doubles each cell and adds them.101+102+## Arrays and spills103+104+An array is a block of values: a range read whole, an array literal105+such as `{1,2;3,4}` (`,` between values in a row, `;` between rows; its106+values may be ranges, so `{A1:A3,C1:C3}` puts two columns side by107+side), or what an array function computes. A formula whose result is an108+array shows its first value and spills the rest into the cells to its109+right and below, as in Sheets:110+111+- `=SEQUENCE(3, 2)` fills three rows of two; `=SORT(A2:A99)`,112+ `=FILTER(A2:C99, C2:C99>100)` and `=UNIQUE(B:B)` spill as tall as113+ their results, and grow or shrink as the data changes. Blank cells past114+ a range's data aren't spilled, so `=SORT(A:A)` fills as many rows as115+ column A holds.116+- Operators work value by value: `={1,2,3}*10` is 10, 20, 30. A row and a117+ column combine into a block (`={1;2}+{10,20}` is two rows of two), and118+ arrays of different sizes line up with `#N/A` past the smaller one.119+- `ARRAYFORMULA(...)` computes its formula over arrays: ranges read whole120+ and functions of one value are applied to each value, so121+ `=ARRAYFORMULA(IF(C2:C99>100, "big", "small"))` spills one word per row122+ and `=ARRAYFORMULA(VLOOKUP(A2:A9, Prices, 2, FALSE))` looks each key up.123+ The arguments of functions that take ranges are computed the same way,124+ so `=SUM(LEN(A2:A9))` counts every character and125+ `=SUMPRODUCT((B2:B99="north")*C2:C99)` sums a column by a condition.126+- Elsewhere an array reads as its first value, as Sheets does:127+ `=LEN(SEQUENCE(3)*100)` is 3. `IF`, `IFERROR`, `IFNA`, `IFS`, `SWITCH`,128+ `CHOOSE` and `INDEX` pass an array through, so129+ `=IFERROR(FILTER(A2:A99, B2:B99="x"), "none")` spills or says none, and130+ `=INDEX(A2:C9, 0, 2)` spills the second column.131+132+The context line says where a spilled cell's value comes from133+("Spilled from B2"), and on the formula's own cell where it spills134+("Spills into B2:C9"); spilled values are drawn in a color of their own,135+and the formula bar shows a spilled cell's formula dimmed. A spilled cell136+can't be typed into, cleared, pasted over or filled: the context line137+names the formula to edit instead. Selecting the formula with its spill138+and pressing Del clears it, formatting spilled cells keeps the139+formatting, and inserting or deleting rows and columns through a spill140+spills it again. Copying spilled cells pastes their values.141+142+When a cell in the way of an array isn't empty, the formula shows143+`#REF!` and says why, as Sheets does: "Array result was not expanded144+because it would overwrite data in C3". Clearing that cell lets the145+array spill. The same goes for an array that would pass the sheet's146+edge, or write more cells than `max-cells` allows.147+148+Formulas reading spilled cells recalculate when the array changes, on149+any sheet, and undo brings back what an array spilled with the formula.150+Files keep only the formula: its array is computed again when the file151+opens.152+153+## Names in a formula: LET and LAMBDA154+155+`=LET(total, SUM(B2:B99), count, COUNT(B2:B99), total/count)` names156+values for use in the rest of the formula. A name bound to a range reads157+as the range would where the name is used. Names that LET and LAMBDA158+bind are the formula's own: a named range of the same name isn't used159+inside them.160+161+`LAMBDA(x, y, x*y)` is a function of its names, called with values right162+after it, `=LAMBDA(x, x*2)(21)`, or through a name LET gave it,163+`=LET(double, LAMBDA(v, v*2), double(21))`. `MAP`, `REDUCE`, `SCAN`,164+`BYROW`, `BYCOL` and `MAKEARRAY` call one for each value, row or column:165+`=BYROW(B2:D9, LAMBDA(row, SUM(row)))` spills each row's total. A LAMBDA166+that isn't called is `#VALUE!`, and one called with the wrong number of167+values `#N/A`, as in Sheets.168+169+## Regular expressions170+171+`REGEXMATCH`, `REGEXEXTRACT` and `REGEXREPLACE` use Go's regular172+expressions, which are RE2, as Sheets' are: the same patterns mean the173+same thing. They take text only: a number is `#VALUE!`, as in Sheets174+(`A1&""` makes one text). `REGEXEXTRACT` returns the first175+capture group, or the whole match without one, and spills several176+groups across; `REGEXREPLACE` writes a group in the replacement as `$1`.177+`SPLIT` spills the pieces of a text across, reading those that look like178+numbers as numbers.101179 102180 ## Values and errors103181