sheet_to_formulae

This commit is contained in:
SheetJS 2023-05-15 04:38:23 -04:00
parent abd00f34a9
commit c62069a7e4
8 changed files with 168 additions and 94 deletions

@ -829,7 +829,7 @@ Array formulae are rendered in the form `range=formula` while plain cells are
rendered in the form `cell=formula or value`. String literals are prefixed with
an apostrophe `'`, consistent with Excel's formula bar display.
["Formulae Output"](/docs/api/utilities#formulae-output) describes the function in more detail.
["Formulae Output"](/docs/api/utilities/formulae) describes the function in more detail.
## Streaming Write

@ -48,22 +48,6 @@ numeric text. There are 6 valid cell types:
| `s` | Text: value interpreted as JS `string` and written as text ** |
| `z` | Stub: blank stub cell that is ignored by data processing utilities ** |
<details>
<summary><b>Error values and interpretation</b> (click to show)</summary>
| Value | Error Meaning |
| -----: | :-------------- |
| `0x00` | `#NULL!` |
| `0x07` | `#DIV/0!` |
| `0x0F` | `#VALUE!` |
| `0x17` | `#REF!` |
| `0x1D` | `#NAME?` |
| `0x24` | `#NUM!` |
| `0x2A` | `#N/A` |
| `0x2B` | `#GETTING_DATA` |
</details>
Type `n` is the Number type. This includes all forms of data that Excel stores
as numbers, such as dates/times and Boolean fields. Excel exclusively uses data
that can be fit in an IEEE754 floating point number, just like JS Number, so the
@ -82,8 +66,23 @@ Type `s` is the String type. Values are explicitly stored as text. Excel will
interpret these cells as "number stored as text". Generated Excel files
automatically suppress that class of error, but other formats may elicit errors.
Type `b` is the Boolean type. Values are either `true` or `false`.
Type `z` represents blank stub cells. They are generated in cases where cells
have no assigned value but hold comments or other metadata. They are ignored by
the core library data processing utility functions. By default these cells are
not generated; the parser `sheetStubs` option must be set to `true`.
Type `e` is the Error type. The `v` field holds numeric error codes, while `w`
holds the error message. Acceptable values are listed below:
| Value | Error Meaning |
| -----: | :-------------- |
| `0x00` | `#NULL!` |
| `0x07` | `#DIV/0!` |
| `0x0F` | `#VALUE!` |
| `0x17` | `#REF!` |
| `0x1D` | `#NAME?` |
| `0x24` | `#NUM!` |
| `0x2A` | `#N/A` |
| `0x2B` | `#GETTING_DATA` |

@ -7,7 +7,7 @@ sidebar_position: 1
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<details><summary><b>Formulae File Format Support</b> (click to show)</summary>
<details><summary><b>File Format Support</b> (click to show)</summary>
The parser will translate from the storage representation to A1-Style strings,
while the writer will translate from A1-Style strings to the file format.

@ -5,11 +5,27 @@ sidebar_position: 4
# Cell Comments
<details>
<summary><b>Format Support</b> (click to show)</summary>
<summary><b>File Format Support</b> (click to show)</summary>
**Simple Notes/Comments**: XLSX/M, XLSB, BIFF8 XLS (read only), XLML, ODS (read only)
Comments and Notes have evolved over the years. "Notes" (powered by VML) were
the original comments. "Comments" were added later.
**Threaded Comments**: XLSX/M, XLSB (read only)
Excel 365 introduced "Threaded Comments" which do not support rich text but do
allow users to "reply". The original "Comments" were renamed to "Notes".
| Formats | Notes | Comment | Threaded |
|:------------------|:-----:|:-------:|:--------:|
| XLSX / XLSM | ✔ | ✔ | ✔ |
| XLSB | ✔ | ✔ | R |
| XLS | R | R | * |
| XLML | ✔ | ✔ | * |
| SYLK | | * | * |
| ODS / FODS / UOS | ✔ | R | * |
Asterisks (*) mark features that are not supported by the file formats. There is
no way to specify a threaded comment in the SYLK format.
The letter R (R) marks features parsed but not written in the format.
</details>

@ -0,0 +1,124 @@
---
sidebar_position: 9
title: Formulae Output
pagination_next: miscellany/formats
---
```js
var fmla_arr = XLSX.utils.sheet_to_formulae(ws);
```
`XLSX.utils.sheet_to_formulae` generates an array of commands that represent
how a person would enter data into an application.
## Live Preview
After choosing a file, the demo will extract and display all formulae.
```jsx live
function SheetJSFormulaPreview() {
const [__html, setHTML] = React.useState("Select a file");
return ( <>
<pre dangerouslySetInnerHTML={{ __html }}/>
<input type="file" onChange={async(e) => {
const wb = XLSX.read(await e.target.files[0].arrayBuffer());
var res = "";
wb.SheetNames.forEach((n, idx) => {
const ws = wb.Sheets[n];
res += `<b>Sheet #${idx+1} (${n})</b>\n`;
res += XLSX.utils.sheet_to_formulae(ws).join("\n") + "\n\n";
});
setHTML(res);
}}/>
</> );
}
```
## Cell Processing
Cells are analyzed in "row-major order" (starting from the first row).
#### Cells without formulae
Cells without formulae are written as `A1-cell-address=value`:
```
A1=1 // A1 is the numeric value 1
B1=TRUE // B1 is the logical value TRUE
```
String literals are prefixed with a `'` in accordance with Excel:
```
A5='A4+A3 // A5 is the string "A4+A3"
```
#### Cells with formulae
Cells with formulae are written as `A1-cell-address=formula`:
```
A5=A4+A3 // A5 is a cell with formula =A4+A3
```
#### Array formulae
Array formulae are written as `A1-range=formula`. They do not include the
displayed curly braces:
```
A4:B4=A2:B2*A3:B3 // A4:B4 array formula {=A2:B2*A3:B3}
```
Single-cell array formulae are written with single-cell ranges:
```
C4:C4=SUM(A2:A3*B2:B3) // C4 array formula {=SUM(A2:A3*B2:B3)}
```
## Demo
This example constructs a workbook including cells with no formulae, cells with
normal formulae, single-cell array formulae and array formulae spanning ranges.
For verification, the button writes a workbook whose formulae can be inspected.
```jsx live
function SheetJSToFormulae() {
var ws = XLSX.utils.aoa_to_sheet([
["A", "B", "C"],
[1, 2, { t: "n", f: "SUM(A2:B2)" }],
[3, 4, { t: "n", f: "A3+B3" }]
]);
XLSX.utils.sheet_set_array_formula(ws, "A4:B4", "A2:B2*A3:B3");
XLSX.utils.sheet_set_array_formula(ws, "C4", "SUM(A2:A3*B2:B3)");
const generate = () => {
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
XLSX.writeFile(wb, "SheetJSFormulae.xlsx");
};
var __html = `\
<i>Values</i>
[
["A", "B", "C"],
[ 1 , 2],
[ 3 , 4]
]
<i>Formulae</i>
C2 =SUM(A2:B2)
C3 =A3+B3
<i>Array Formulae</i>
A4:B4 {=A2:B2*A3:B3}
C4 {=SUM(A2:A3*B2:B3)}`;
return ( <pre>
<b>Original worksheet</b><br/>
<button onClick={generate}><b>Export worksheet to XLSX</b></button>
<div dangerouslySetInnerHTML={{__html}}/><br/>
<b>XLSX.utils.sheet_to_formulae(ws).join("\n")</b><br/>
<br/>{XLSX.utils.sheet_to_formulae(ws).join("\n")}
</pre> );
}
```

@ -0,0 +1,5 @@
{
"label": "Utility Functions",
"collapsed": false,
"position": 9
}

@ -1,6 +1,7 @@
---
sidebar_position: 9
title: Utility Functions
pagination_prev: api/write-options
---
import Tabs from '@theme/Tabs';
@ -689,76 +690,4 @@ function SheetJSToJSON() {
## Formulae Output
```js
var fmla_arr = XLSX.utils.sheet_to_formulae(ws);
```
`XLSX.utils.sheet_to_formulae` generates an array of commands that represent
how a person would enter data into an application.
Cells without formulae are written as `A1-cell-address=value`:
```
A1=1 // A1 is the numeric value 1
B1=TRUE // B1 is the logical value TRUE
```
String literals are prefixed with a `'` in accordance with Excel:
```
A5='A4+A3 // A5 is the string "A4+A3"
```
Cells with formulae are written as `A1-cell-address=formula`:
```
A5=A4+A3 // A5 is a cell with formula =A4+A3
```
Array formulae are written as `A1-range=formula`. They do not include the
displayed curly braces:
```
A4:B4=A2:B2*A3:B3 // A4:B4 array formula {=A2:B2*A3:B3}
```
Single-cell array formulae are written with single-cell ranges:
```
C4:C4=SUM(A2:A3*B2:B3) // C4 array formula {=SUM(A2:A3*B2:B3)}
```
```jsx live
function SheetJSToJSON() {
var ws = XLSX.utils.aoa_to_sheet([
["A", "B", "C"],
[1, 2, { t: "n", f: "SUM(A2:B2)" }],
[3, 4, { t: "n", f: "A3+B3" }]
]);
XLSX.utils.sheet_set_array_formula(ws, "A4:B4", "A2:B2*A3:B3");
XLSX.utils.sheet_set_array_formula(ws, "C4", "SUM(A2:A3*B2:B3)");
var __html = `\
<i>Values</i>
[
["A", "B", "C"],
[1, 2],
[3, 4]
]
<i>Formulae</i>
C2 =SUM(A2:B2)
C3 =A3+B3
<i>Array Formulae</i>
A4:B4 {=A2:B2*A3:B3}
C4 {=SUM(A2:A3*B2:B3)}
`;
return ( <pre>
<b>Original worksheet</b>
<div dangerouslySetInnerHTML={{__html}}/>
<b>XLSX.utils.sheet_to_formulae(ws).join("\n")</b><br/>
<br/>{XLSX.utils.sheet_to_formulae(ws).join("\n")}
</pre> );
}
```
[**This has been moved to a separate page**](/docs/api/utilities/formulae)

@ -1,6 +1,7 @@
---
sidebar_position: 1
hide_table_of_contents: true
pagination_prev: api/utilities/index
---
# File Formats