Compare commits

...

4 Commits

Author SHA1 Message Date
d77a40c6bf NuxtJS workarounds 2025-05-18 16:09:19 -04:00
9af5473755 added demo for sheetjs in vscode extension 2025-05-15 01:41:40 -04:00
1f87dda979 Demo refresh 2025-05-12 00:41:16 -04:00
1b242c12ef Demo refresh 2025-05-06 20:21:41 -04:00
75 changed files with 1981 additions and 648 deletions

3
.gitignore vendored

@ -4,4 +4,5 @@ package-lock.json
pnpm-lock.yaml
/docs
node_modules
.idea
.idea
.vscode

@ -352,7 +352,7 @@
<Cell><Data ss:Type="String">Python</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String"></Data></Cell>

@ -118,20 +118,20 @@ importScripts("https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.mi
### Type Checker
:::danger VSCode Telemetry and Data Exfiltration
:::danger VS Code Telemetry and Data Exfiltration
The official Microsoft builds of Visual Studio Code ("VSCode") embed telemetry
and send information to external servers.
The official builds of Visual Studio Code ("VS Code" or "VSCode") embed
telemetry and send information to Microsoft servers.
**[VSCodium](https://vscodium.com/) is a telemetry-free fork of VSCode.**
**[VSCodium](https://vscodium.com/) is a telemetry-free fork of VS Code.**
When writing code that may process personally identifiable information (PII),
the SheetJS team strongly encourages building VSCode from source or using IDEs
the SheetJS team strongly encourages building VS Code from source or using IDEs
that do not exfiltrate data.
:::
The type checker integrated in VSCodium and VSCode does not currently provide
The type checker integrated in VSCodium and VS Code does not currently provide
type hints when using the standalone build. Using the JSDoc `@type` directive
coupled with type imports, VSCodium will recognize the types:
@ -176,7 +176,7 @@ The `.d.ts` file extension must be omitted.
JSDoc types using the `@import` directive are not supported in `<script>` tags.
**This is a known bug with VSCode!**
**This is a known bug with VS Code!**
:::

@ -644,7 +644,7 @@ After saving the file, run a local web server in the folder with the HTML file.
For example, if NodeJS is installed:
```bash
npx http-server .
npx -y http-server .
```
The server process will display a URL (typically `http://127.0.0.1:8080`). Open

@ -489,20 +489,20 @@ function SheetJSAoAFilled() {
### Select Data Rows
At this point, each data row will have the year in column `A` and dollar value
in column `C`. The year (first value in the row) will be between 2007 and 2024.
in column `C`. The year (first value in the row) will be between 2007 and 2029.
The value (third value) will be positive. The following function tests a row
against the requirements:
```js
const is_valid_row = r =>
r[0] >= 2007 && r[0] <= 2024 // year (column A) is between 2007 and 2024
r[0] >= 2007 && r[0] <= 2029 // year (column A) is between 2007 and 2029
&& r[2] > 0; // dollar value (column C) is positive
```
`Array#filter`, using the previous test, can select the matching rows:
```js
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
```
<details>
@ -522,7 +522,7 @@ function SheetJSAoAFiltered() {
var last_year = 0;
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
/* select data rows */
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
/* display data */
setRows(rows);
})(); }, []);
@ -598,7 +598,7 @@ function SheetJSObjects() {
var last_year = 0;
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
/* select data rows */
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
/* generate row objects */
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));
/* display data */
@ -706,7 +706,7 @@ function StudentAidTotal() {
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
/* select data rows */
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
/* generate row objects */
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));
@ -761,7 +761,7 @@ Save the following script to `SheetJSStandaloneDemo.html`:
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
\n\
/* select data rows */
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
\n\
/* generate row objects */
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));
@ -781,7 +781,7 @@ After saving the file, run a local web server in the folder with the HTML file.
For example, if NodeJS is installed:
```bash
npx http-server .
npx -y http-server .
```
The server process will display a URL (typically `http://127.0.0.1:8080`). Open
@ -827,7 +827,7 @@ const XLSX = require("xlsx");
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
/* select data rows */
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
/* generate row objects */
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));
@ -900,7 +900,7 @@ Save the following script to `SheetJSNW.html`:
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
\n\
/* select data rows */
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
\n\
/* generate row objects */
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));
@ -1001,7 +1001,7 @@ const App = () => {
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
/* select data rows */
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2024 && r[2] > 0);
const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2029 && r[2] > 0);
/* generate row objects */
const objects = rows.map(r => ({FY: r[0], FQ: r[1], total: r[8]}));

@ -35,6 +35,7 @@ This demo was tested in the following configurations:
| Platform | Architecture | Date |
|:------------------------------------------------------------------|:-------------|:-----------|
| NVIDIA RTX 5090 (32 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-05-17 |
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-04-17 |
| NVIDIA RTX 4090 (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `linux-x64` | 2025-01-28 |
| AMD RX 7900 XTX (24 GB VRAM) + Ryzen Z1 Extreme (16 GB RAM) | `win11-x64` | 2025-01-12 |

@ -42,7 +42,7 @@ This demo was tested in the following deployments:
|:-------------|:----------------|:-------|:-------|:-----------|
| `darwin-x64` | Duktape `2.7.0` | 2.2.3 | 3.13.1 | 2025-03-31 |
| `darwin-arm` | Duktape `2.7.0` | 2.2.3 | 3.13.2 | 2025-03-30 |
| `win11-x64` | Duktape `2.7.0` | 2.2.3 | 3.11.8 | 2024-12-21 |
| `win11-x64` | Duktape `2.7.0` | 2.2.3 | 3.11.9 | 2025-04-28 |
| `win11-arm` | Duktape `2.7.0` | 2.2.3 | 3.13.2 | 2025-02-23 |
| `linux-x64` | Duktape `2.7.0` | 1.5.3 | 3.11.7 | 2025-01-01 |
| `linux-arm` | Duktape `2.7.0` | 1.5.3 | 3.11.2 | 2025-02-16 |
@ -203,7 +203,7 @@ DataFrame. The DataFrame will be exported to the binary XLSB spreadsheet format.
:::note pass
The Windows build requires Visual Studio with "Desktop development with C++".
Commands must be run in a "Native Tools Command Prompt" session.
**Commands must be run in a "Native Tools Command Prompt" session.**
:::
@ -215,6 +215,14 @@ python3 -m pip install pandas
:::info pass
On Windows, Python may be available as `python.exe`:
```bash
python.exe -m pip install pandas
```
---
On macOS and Linux, the install command may require root access:
```bash
@ -305,15 +313,13 @@ cd ..
</TabItem>
<TabItem value="win11-x64" label="Windows">
- Download and extract the source tarball. Commands must be run in WSL `bash`:
- Download and extract the source tarball:
```bash
curl -LO https://duktape.org/duktape-2.7.0.tar.xz
tar -xJf duktape-2.7.0.tar.xz
```
(Run `bash`, then run the aforementioned commands, then run `exit` to exit WSL)
- Enter the source folder:
```bash
@ -472,6 +478,17 @@ def eval_file(ctx, path):
python3 SheetJSPandas.py pres.numbers
```
:::info pass
On Windows, Python may be available as `python.exe`:
```bash
python.exe SheetJSPandas.py pres.numbers
```
:::
If successful, the script will display DataFrame metadata:
```
@ -529,7 +546,7 @@ This demo was tested in the following deployments:
|:-------------|:----------------|:--------|:-------|:-----------|
| `darwin-x64` | Duktape `2.7.0` | 1.26.0 | 3.13.1 | 2025-03-31 |
| `darwin-arm` | Duktape `2.7.0` | 1.26.0 | 3.13.2 | 2025-03-30 |
| `win11-x64` | Duktape `2.7.0` | 1.17.1 | 3.11.8 | 2024-12-21 |
| `win11-x64` | Duktape `2.7.0` | 1.28.1 | 3.11.9 | 2025-04-28 |
| `win11-arm` | Duktape `2.7.0` | 1.23.0 | 3.13.2 | 2025-02-23 |
| `linux-x64` | Duktape `2.7.0` | 1.18.0 | 3.11.7 | 2025-01-01 |
| `linux-arm` | Duktape `2.7.0` | 1.22.0 | 3.11.2 | 2025-02-16 |
@ -599,10 +616,18 @@ python3 -m pip install polars
:::info pass
On Windows, Python may be available as `python.exe`:
```bash
python.exe -m pip install polars
```
---
On macOS and Linux, the install command may require root access:
```bash
sudo python3 -m pip install pandas
sudo python3 -m pip install polars
```
:::
@ -662,6 +687,16 @@ cp ../libduktape.* ../SheetJSPandas.py ../sheetjs.py ../*.js ../*.numbers .
python3 SheetJSPandas.py pres.numbers
```
:::info pass
On Windows, Python may be available as `python.exe`:
```bash
python.exe SheetJSPandas.py pres.numbers
```
:::
:::note pass
If the virtual environment was configured in the previous step, run:
@ -692,7 +727,7 @@ shape: (5, 2)
It will also export the DataFrame to `SheetJSPolars.xlsb`. The file can be
inspected with a spreadsheet editor that supports XLSB files.
[^1]: See ["Other Languages"](/docs/demos/engines/) for more examples.
[^1]: See ["JavaScript Engines"](/docs/demos/engines/) for more examples.
[^2]: See [`ctypes`](https://docs.python.org/3/library/ctypes.html) in the Python documentation.
[^3]: See [`read` in "Reading Files"](/docs/api/parse-options)
[^4]: See ["Workbook Object"](/docs/csf/book)

@ -518,7 +518,7 @@ The generated site will be placed in the `dist` folder.
9) Start a local web server:
```bash
npx http-server dist
npx -y http-server dist
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser
@ -665,7 +665,7 @@ The generated site will be placed in the `dist` folder.
9) Start a local web server:
```bash
npx http-server dist
npx -y http-server dist
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser

@ -135,7 +135,7 @@ The SheetJS [`read`](/docs/api/parse-options) and [`sheet_to_json`](/docs/api/ut
functions simplify state updates. They are best used in the function bodies of
`useEffect`[^2] and `useCallback`[^3] hooks.
A `useEffect` hook can download and update state when a person loads the site:
A `useEffect` hook can download and update state when the site is loaded:
```mermaid
flowchart LR
@ -150,12 +150,13 @@ flowchart LR
wb --> |wb.Sheets\nselect sheet| ws
ws --> |sheet_to_json\n\n| aoo
aoo --> |setPres\nfrom `setState`| state
linkStyle 1,2,3 color:blue,stroke:blue;
```
<Tabs groupId="lang">
<TabItem name="JS" value="JavaScript">
```js
```js title="In a useEffect hook, update state with data from a remote workbook"
import { useEffect } from 'react';
import { read, utils } from 'xlsx';
@ -182,7 +183,7 @@ useEffect(() => { (async() => {
</TabItem>
<TabItem name="TS" value="TypeScript" default>
```ts
```ts title="In a useEffect hook, update state with data from a remote workbook"
import { useEffect } from 'react';
import { read, utils } from 'xlsx';
@ -252,9 +253,10 @@ flowchart LR
state --> |json_to_sheet\n\n| ws
ws --> |book_new\nbook_append_sheet| wb
wb --> |writeFile\n\n| file
linkStyle 0,1,2 color:blue,stroke:blue;
```
```ts
```ts title="Export data from state to a new XLSX workbook"
import { useCallback } from 'react';
import { utils, writeFile } from 'xlsx';
@ -332,7 +334,7 @@ This demo was tested in the following environments:
| ReactJS | ViteJS | Date |
|:---------|:--------|:-----------|
| `18.3.1` | `6.0.1` | 2024-12-12 |
| `19.1.0` | `6.3.5` | 2025-05-11 |
:::
@ -369,7 +371,7 @@ The generated site will be placed in the `dist` folder.
6) Start a local web server:
```bash
npx http-server dist
npx -y http-server dist
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser
@ -384,23 +386,14 @@ This demo was tested in the following environments:
| ReactJS | CRA | Date |
|:---------|:--------|:-----------|
| `18.2.0` | `5.0.1` | 2024-12-12 |
| `19.1.0` | `5.1.0` | 2025-05-11 |
:::
:::caution pass
CRA has known compatibility issues with React 19[^5]. CRA no longer receives
updates and the ReactJS docs no longer recommend using CRA. For new projects, it
is strongly recommended to use ViteJS with the `react` or `react-ts` templates.
:::
1) Create a new site:
```bash
npx -y create-react-app@5.0.1 --scripts-version=5.0.1 sheetjs-react
npx -y create-react-app@5.1.0 sheetjs-react
```
2) Install the SheetJS dependency and start the dev server:
@ -408,7 +401,7 @@ npx -y create-react-app@5.0.1 --scripts-version=5.0.1 sheetjs-react
<CodeBlock language="bash">{`\
cd sheetjs-react
npm i
npm i react@18.2.0 react-dom@18.2.0 web-vitals --save --save-exact
npm i react@19.1.0 react-dom@19.1.0 web-vitals --save --save-exact
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
npm start`}
</CodeBlock>
@ -431,7 +424,7 @@ The generated site will be placed in the `build` folder.
6) Start a local web server:
```bash
npx http-server build
npx -y http-server build
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser
@ -446,7 +439,7 @@ This demo was tested in the following environments:
| ReactJS | NextJS | Date |
|:---------|:---------|:-----------|
| `19.0.0` | `15.1.0` | 2024-12-13 |
| `19.1.0` | `15.3.2` | 2025-05-11 |
:::
@ -567,7 +560,7 @@ This demo was tested in the following environments:
| Preact | ViteJS | Date |
|:----------|:----------|:-----------|
| `10.22.1` | `5.3.3` | 2024-12-17 |
| `10.26.6` | `5.4.19` | 2025-05-11 |
:::
@ -578,7 +571,12 @@ npm init preact sheetjs-preact
```
This will initiate the project creation process. **Follow the on-screen prompts and
press Enter to accept the default options.**
press Enter to accept the default options:**
- `Project language:` JavaScript
- `Use router?` No
- `Prerender app (SSG)?` No
- `Use ESLint?` No
2) Install the SheetJS dependency and start the dev server:
@ -620,7 +618,7 @@ The generated site will be placed in the `dist` folder.
7) Start a local web server:
```bash
npx http-server dist
npx -y http-server dist
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser
@ -641,10 +639,149 @@ The main disadvantage of the Array of Objects approach is the specific nature
of the columns. For more general use, passing around an Array of Arrays works.
However, this does not handle merge cells[^6] well!
HTML Tables support elements with `rowspan` and `colspan` attributes.
#### State
The state will be the serialized HTML string:
<Tabs groupId="lang">
<TabItem name="JS" value="JavaScript">
```ts
import { useState } from 'react';
/* the component state is a string */
const [__html, setHtml] = useState("");
```
</TabItem>
<TabItem name="TS" value="TypeScript" default>
```ts
import { useState } from 'react';
/* the component state is a string */
const [__html, setHtml] = useState<string>("");
```
</TabItem>
</Tabs>
:::info Use of the variable name `__html`
Examples use the name `__html` due to the design of `dangerouslySetInnerHTML`.
`dangerouslySetInnerHTML` expects objects of the form `{ __html: "html code" }`.
For example, the following snippet assumes `html` is the variable name:
```jsx
<div ref={tbl} dangerouslySetInnerHTML={{ __html: html }} />
```
By using the name `__html`, the ES6 shorthand syntax simplifies the code:
```jsx
<div ref={tbl} dangerouslySetInnerHTML={{ __html }} />
```
:::
#### Updating State
The [`sheet_to_html`](/docs/api/utilities/html#html-table-output) function
generates HTML that is aware of merges and other worksheet features. ReactJS
`dangerouslySetInnerHTML`[^7] prop allows code to set the `innerHTML` attribute,
effectively inserting the code into the page.
generates HTML that is aware of merges and other worksheet features.
A `useEffect` hook can download and update state when the site is loaded:
```mermaid
flowchart LR
url[(Remote\nFile)]
ab[(Data\nArrayBuffer)]
wb(SheetJS\nWorkbook)
ws(SheetJS\nWorksheet)
html(HTML\nTABLE)
state((component\nstate))
url --> |fetch\n\n| ab
ab --> |read\n\n| wb
wb --> |wb.Sheets\nselect sheet| ws
ws --> |sheet_to_html\n\n| html
html --> |setHtml\nfrom `setState`| state
linkStyle 1,2,3 color:blue,stroke:blue;
```
```js title="In a useEffect hook, update state with HTML generated from a remote workbook"
import { useEffect } from 'react';
import { read, utils } from 'xlsx';
/* Fetch and update the state once */
useEffect(() => { (async() => {
/* Download from https://docs.sheetjs.com/pres.numbers */
const f = await fetch("https://docs.sheetjs.com/pres.numbers");
const ab = await f.arrayBuffer();
// highlight-start
/* parse */
const wb = read(ab);
/* generate HTML TABLE from first worksheet */
const ws = wb.Sheets[wb.SheetNames[0]]; // get the first worksheet
const data = utils.sheet_to_html(ws); // generate objects
/* update state */
setHtml(data); // update state
// highlight-end
})(); }, []);
```
#### Rendering Data
ReactJS `dangerouslySetInnerHTML`[^7] prop allows code to set the `innerHTML`
attribute, effectively inserting the code into the page.
It is strongly recommended to set the `innerHTML` of a parent `DIV` container.
By attaching a `ref`, callbacks will be able to access the live `TABLE` element.
```jsx title="Example JSX for displaying HTML TABLE code"
<div ref={tbl} dangerouslySetInnerHTML={{ __html }} />
```
#### Exporting Data
The [`writeFile`](/docs/api/write-options) and [`table_to_book`](/docs/api/utilities/html#html-table-input)
functions simplify exporting data. They are best used in the function bodies of
`useCallback`[^4] hooks attached to button or other elements.
A callback can generate a local file when a user clicks a button:
```mermaid
flowchart LR
state((component\nstate))
wb(SheetJS\nWorkbook)
file[(XLSX\nexport)]
state --> |table_to_book\n\n| wb
wb --> |writeFile\n\n| file
linkStyle 0,1 color:blue,stroke:blue;
```
```ts title="Export data from HTML TABLE element to a new XLSX workbook"
import { useCallback } from 'react';
import { utils, writeFile } from 'xlsx';
/* get data from live HTML TABLE and export to XLSX */
const exportFile = useCallback(() => {
/* get live reference to HTML TABLE element */
const elt = tbl.current.getElementsByTagName("TABLE")[0];
/* generate workbook from element */
// highlight-next-line
const wb = utils.table_to_book(elt);
/* export to XLSX */
writeFile(wb, "SheetJSReactAoO.xlsx");
}, [pres]);
```
#### Complete Component
In this example, the component attaches a `ref` to the `DIV` container. During
export, the first `TABLE` child element can be parsed with [`table_to_book`](/docs/api/utilities/html#html-table-input) to
@ -701,7 +838,7 @@ This demo was tested in the following environments:
| ReactJS | ViteJS | Date |
|:---------|:--------|:-----------|
| `18.3.1` | `6.0.1` | 2024-12-13 |
| `19.1.0` | `6.3.5` | 2025-05-11 |
:::
@ -738,7 +875,7 @@ The generated site will be placed in the `dist` folder.
6) Start a local web server:
```bash
npx http-server dist
npx -y http-server dist
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser
@ -753,22 +890,14 @@ This demo was tested in the following environments:
| ReactJS | CRA | Date |
|:---------|:--------|:-----------|
| `18.2.0` | `5.0.1` | 2024-12-31 |
:::
:::caution pass
CRA has known compatibility issues with React 19[^5]. CRA no longer receives
updates and the ReactJS docs no longer recommend using CRA. For new projects, it
is strongly recommended to use ViteJS with the `react` or `react-ts` templates.
| `19.1.0` | `5.1.0` | 2025-05-11 |
:::
1) Create a new site:
```bash
npx -y create-react-app@5.0.1 --scripts-version=5.0.1 sheetjs-react
npx -y create-react-app@5.1.0 sheetjs-react
```
2) Install the SheetJS dependency and start the dev server:
@ -776,7 +905,7 @@ npx -y create-react-app@5.0.1 --scripts-version=5.0.1 sheetjs-react
<CodeBlock language="bash">{`\
cd sheetjs-react
npm i
npm i react@18.2.0 react-dom@18.2.0 web-vitals --save --save-exact
npm i react@19.1.0 react-dom@19.1.0 web-vitals --save --save-exact
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
npm start`}
</CodeBlock>
@ -799,7 +928,7 @@ The generated site will be placed in the `build` folder.
6) Start a local web server:
```bash
npx http-server build
npx -y http-server build
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser
@ -812,9 +941,9 @@ and test the page.
This demo was tested in the following environments:
| Preact | ViteJS | Date |
|:----------|:--------|:-----------|
| `10.22.1` | `5.3.3` | 2024-12-17 |
| Preact | ViteJS | Date |
|:----------|:---------|:-----------|
| `10.26.6` | `5.4.19` | 2025-05-11 |
:::
@ -823,11 +952,15 @@ npm init preact sheetjs-preact
```
This will initiate the project creation process. **Follow the on-screen prompts and
press Enter to accept the default options.**
press Enter to accept the default options:**
- `Project language:` JavaScript
- `Use router?` No
- `Prerender app (SSG)?` No
- `Use ESLint?` No
2) Install the SheetJS dependency and start the dev server:
<CodeBlock language="bash">{`\
cd sheetjs-preact
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
@ -866,7 +999,7 @@ The generated site will be placed in the `dist` folder.
7) Start a local web server:
```bash
npx http-server dist
npx -y http-server dist
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser
@ -913,8 +1046,8 @@ const columns = Array.from({ length: range.e.c + 1 }, (_, i) => ({
## Legacy Deployments
[The Standalone Scripts](/docs/getting-started/installation/standalone) play nice
with legacy deployments that do not use a bundler.
[SheetJS Standalone Scripts](/docs/getting-started/installation/standalone) use
simple `SCRIPT` tags and work with legacy deployments that do not use a bundler.
[The legacy demo](pathname:///react/index.html) shows a simple ReactJS component
transpiled in the browser using Babel standalone library.

@ -397,7 +397,7 @@ The generated site will be placed in the `dist` folder.
6) Start a local web server:
```bash
npx http-server dist
npx -y http-server dist
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser
@ -449,7 +449,7 @@ The generated site will be placed in the `dist` folder.
6) Start a local web server:
```bash
npx http-server .output/public/
npx -y http-server .output/public/
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser
@ -558,7 +558,7 @@ The generated site will be placed in the `dist` folder.
6) Start a local web server:
```bash
npx http-server dist
npx -y http-server dist
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser
@ -610,7 +610,7 @@ The generated site will be placed in the `dist` folder.
6) Start a local web server:
```bash
npx http-server .output/public/
npx -y http-server .output/public/
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser

@ -91,7 +91,7 @@ in the ["API Reference"](/docs/api/) section of the documentation.
<!-- The SheetJS Standalone script must be loaded before the UI5 bootstrap -->
<script src="https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js"></script>
<!-- UI5 bootstrap script -->
<script
id="sap-ui-bootstrap"
@ -441,7 +441,7 @@ generated. The `dist` folder in this demo can be deployed on a static host.
9) Start a local web server:
```bash
npx http-server dist
npx -y http-server dist
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser
@ -611,7 +611,7 @@ generated. The `dist` folder in this demo can be deployed on a static host.
9) Start a local web server:
```bash
npx http-server dist
npx -y http-server dist
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser

@ -173,7 +173,7 @@ npx vite build
7) Verify the new site by running a local web server in the `dist` folder:
```bash
npx http-server dist
npx -y http-server dist
```
8) Access the displayed URL (typically `http://localhost:8080`) in a web browser

@ -145,7 +145,7 @@ npx -y esbuild@0.19.8 esbrowser.js --bundle --outfile=esb.browser.js
5) Start a local HTTP server:
```bash
npx http-server .
npx -y http-server .
```
Access the displayed URL (typically `http://localhost:8080`) with a web browser.

@ -322,7 +322,7 @@ npx webpack --mode=production
6) Start a local HTTP server:
```bash
npx http-server .
npx -y http-server .
```
7) Load the displayed URL (typically `http://localhost:8080/`) in a web browser.

@ -177,7 +177,7 @@ npm install --save browserify@3.46.1
5) Start a local HTTP server:
```bash
npx http-server .
npx -y http-server .
```
6) Load the displayed URL (typically `http://localhost:8080/`) in a web browser.

@ -209,7 +209,7 @@ uses normal functions and traditional Promise chains.
3) Start a local HTTP server:
```bash
npx http-server .
npx -y http-server .
```
4) Load the displayed URL (typically `http://localhost:8080/`) in a web browser.

@ -169,7 +169,7 @@ This step will create `bundle.js`
5) Start a local HTTP server:
```bash
npx http-server .
npx -y http-server .
```
Access the displayed URL (typically `http://localhost:8080/`) in a web browser.

@ -34,8 +34,8 @@ This demo was tested in the following environments:
| Version | Date |
|:---------|:-----------|
| `2.13.3` | 2024-12-31 |
| `1.12.3` | 2024-12-31 |
| `2.14.4` | 2025-05-07 |
| `1.12.3` | 2025-05-07 |
:::
@ -239,7 +239,7 @@ The production site will be stored in the `dist` folder
7) Start a local web server and serve the `dist` folder:
```bash
npx http-server dist
npx -y http-server dist
```
Access the displayed URL (typically `http://localhost:8080/`) in a web browser.

@ -195,7 +195,7 @@ This command will create the script `lib/web.js`
6) Start a local HTTP server, then go to `http://localhost:8080/`
```bash
npx http-server .
npx -y http-server .
```
Click on "Click here to export" to generate a file.

@ -164,7 +164,7 @@ npx snowpack@3.8.8 build
5) Start a local HTTP server:
```bash
npx http-server build/
npx -y http-server build/
```
6) Open a web browser to the displayed URL (typically `http://localhost:8080/`).
@ -290,7 +290,7 @@ npx wmr@3.8.0 build
5) Start a local HTTP server:
```bash
npx http-server dist/
npx -y http-server dist/
```
6) Open a web browser to the displayed URL (typically `http://localhost:8080/`).

@ -36,12 +36,13 @@ the file can be downloaded or previewed in the browser.
This demo was tested in the following deployments:
| Platform | Version | Date |
|:-------------|:---------|:-----------|
| Chromium 131 | `1.9.0` | 2024-12-22 |
| Konqueror 22 | `1.9.0` | 2025-04-23 |
| NodeJS 20 | `1.10.0` | 2024-12-22 |
| BunJS 1.1 | `1.10.0` | 2024-12-22 |
| Platform | Version | Date |
|:--------------|:---------|:-----------|
| Chromium 136 | `1.9.0` | 2025-05-07 |
| Safari 17.5 | `1.9.0` | 2025-05-07 |
| Konqueror 22 | `1.9.0` | 2025-05-07 |
| NodeJS 24.0.0 | `1.11.0` | 2025-05-07 |
| BunJS 1.2.10 | `1.11.0` | 2025-05-07 |
:::

@ -377,7 +377,7 @@ This demo was tested in the following deployments:
|:-------------|:--------|:-------|:-----------|
| `darwin-x64` | 0.1.48 | 2.2.6 | 2025-03-31 |
| `darwin-arm` | 0.1.48 | 2.2.12 | 2025-04-24 |
| `win11-x64` | 0.1.48 | 2.0.4 | 2024-10-30 |
| `win11-x64` | 0.1.48 | 2.2.12 | 2025-04-28 |
| `win11-arm` | 0.1.48 | 2.2.1 | 2025-02-23 |
| `linux-x64` | 0.1.48 | 2.0.5 | 2025-01-10 |
| `linux-arm` | 0.1.48 | 2.1.10 | 2025-02-16 |
@ -392,17 +392,17 @@ This demo was tested in the following deployments:
2) Run the script with `--allow-net` and `--allow-write` entitlements:
```bash
deno run --allow-net --allow-write SheetJSDenoDOM.ts
deno run --allow-net --allow-write --allow-import SheetJSDenoDOM.ts
```
The script will create a file `SheetJSDenoDOM.xlsx` that can be opened.
:::caution pass
:::note pass
Deno 2 additionally requires the `--allow-import` entitlement:
In older versions of Deno, the `--allow-import` flag must be omitted:
```bash
deno run --allow-net --allow-write --allow-import SheetJSDenoDOM.ts
deno run --allow-net --allow-write SheetJSDenoDOM.ts
```
:::

@ -231,7 +231,7 @@ This will create a static site in the `_site` folder
8) Test the generated site by starting a web server:
```bash
npx http-server _site
npx -y http-server _site
```
The program will display a URL (typically `http://localhost:8080`). Accessing

@ -294,7 +294,7 @@ The final script will be saved to `out.js`
7) Start a local web server to host the project folder:
```bash
npx http-server .
npx -y http-server .
```
The command will print a list of URLs.

@ -430,7 +430,7 @@ Save and refresh the page. A data table should be displayed
```bash
npm run build
npx http-server dist/
npx -y http-server dist/
```
The terminal will display a URL, typically `http://127.0.0.1:8080` . Access
@ -506,7 +506,7 @@ Save and refresh the page. A data table should be displayed
```bash
npm run build
npx http-server dist/
npx -y http-server dist/
```
The terminal will display a URL, typically `http://127.0.0.1:8080` . Access
@ -594,7 +594,7 @@ const data = utils.sheet_to_json<IPresident>(ws);
```bash
npm run build
npx http-server dist/
npx -y http-server dist/
```
The terminal will display a URL ( `http://127.0.0.1:8080` ). Access that page

@ -334,7 +334,7 @@ The final site will be placed in the `dist` folder.
12) Start a local web server to host the `dist` folder:
```bash
npx http-server dist
npx -y http-server dist
```
The command will print a list of URLs.

@ -32,6 +32,7 @@ flowchart LR
file --> |.eleventy.js\ncustom parser| buffer
buffer --> |.eleventy.js\ncustom parser| aoo
aoo --> |index.njk\ntemplate| html
linkStyle 1 color:blue,stroke:blue;
```
:::tip No Telemetry
@ -114,10 +115,11 @@ accessed using the variable `pres` in a template:
This demo was tested in the following environments:
| Eleventy | Date |
|:---------|:-----------|
| `2.0.1` | 2024-12-23 |
| `3.0.0` | 2024-12-23 |
| Eleventy | Date |
|:---------------|:-----------|
| `2.0.1` | 2025-05-07 |
| `3.0.0` | 2025-05-07 |
| `3.1.0-beta.1` | 2025-05-07 |
:::
@ -212,7 +214,7 @@ Eleventy will place the generated site in the `_site` subfolder.
9) Start a web server to host the static site:
```bash
npx http-server _site
npx -y http-server _site
```
Open a web browser and access the displayed URL ( `http://localhost:8080` ).

@ -49,7 +49,8 @@ This demo was tested in the following environments:
| Nuxt Content | Nuxt | Date |
|:-------------|:-----------|:-----------|
| `1.15.1` | `2.18.1` | 2025-04-23 |
| `2.13.4` | `3.14.159` | 2024-11-14 |
| `2.13.4` | `3.17.2` | 2025-05-12 |
| `3.5.1` | `3.17.3` | 2025-05-18 |
:::
@ -525,8 +526,8 @@ script files. The module script is expected to export a module configured with
- Add the transformer to Nuxt Content in the `content:context` hook
```js title="sheetmodule.ts (Module)"
import { resolve } from 'path'
import { defineNuxtModule } from '@nuxt/kit'
import { resolve } from 'path';
import { defineNuxtModule } from '@nuxt/kit';
export default defineNuxtModule({
/* module setup method */
@ -549,7 +550,7 @@ The module must be loaded in `nuxt.config.ts` and added to the `modules` array:
```ts title="nuxt.config.ts"
// highlight-next-line
import SheetJSModule from './sheetmodule'
import SheetJSModule from './sheetmodule';
export default defineNuxtConfig({
// @ts-ignore
@ -606,7 +607,7 @@ from the script setup will be shaped like the return value from the transformer.
:::caution pass
For some older versions, parts of the Nuxt dependency tree did not support
NodeJS version 20. If the `yarn install` step fails with a message like
NodeJS version 20. If the `pnpm install` step fails with a message like
```
error @nuxt/kit@3.4.1: The engine "node" is incompatible with this module.
@ -619,17 +620,18 @@ The recommended solution is to switch to Node 18.
1) Create a stock app and install dependencies:
```bash
npx -y nuxi init -t content --packageManager yarn --no-gitInit sheetjs-nc2
npx -y nuxi init -t content --packageManager pnpm --no-gitInit sheetjs-nc2 -M ,
cd sheetjs-nc2
npx -y yarn install
npx -y yarn add --dev @types/node
npx -y pnpm install
npx -y pnpm install @nuxt/content@2 --save
npx -y pnpm install @types/node @nuxt/kit --save
```
2) Install the SheetJS library and start the server:
<CodeBlock language="bash">{`\
npx -y yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
npx -y yarn dev`}
npx -y pnpm install --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
npx -y pnpm dev`}
</CodeBlock>
@ -639,7 +641,7 @@ When the build finishes, the terminal will display a URL like:
> Local: http://localhost:3000/
```
The server is listening on that URL. Open the link in a web browser.
The server is listening on that URL. Open the link in a web browser.
3) Download https://docs.sheetjs.com/pres.xlsx and move to the `content` folder.
@ -649,12 +651,12 @@ curl -L -o content/pres.xlsx https://docs.sheetjs.com/pres.xlsx
4) Create the transformer. Two files must be saved at the root of the project:
- [`sheetformer.ts`](https://docs.sheetjs.com/nuxt/3/sheetformer.ts) (raw transformer module)
- [`sheetformer.ts`](https://docs.sheetjs.com/nuxt/2/sheetformer.ts) (raw transformer module)
- [`sheetmodule.ts`](https://docs.sheetjs.com/nuxt/3/sheetmodule.ts) (Nuxt configuration module)
```bash
curl -O https://docs.sheetjs.com/nuxt/3/sheetformer.ts
curl -O https://docs.sheetjs.com/nuxt/3/sheetmodule.ts
curl -O https://docs.sheetjs.com/nuxt/2/sheetformer.ts
curl -O https://docs.sheetjs.com/nuxt/2/sheetmodule.ts
```
After creating the source files, the module must be added to `nuxt.config.ts`:
@ -668,14 +670,13 @@ export default defineNuxtConfig({
// @ts-ignore
telemetry: false,
// highlight-end
devtools: { enabled: true },
// highlight-start
modules: [
// highlight-next-line
SheetJSModule,
'@nuxt/content'
],
content: {}
// highlight-end
devtools: { enabled: true },
// ...
});
```
@ -684,33 +685,13 @@ Stop the dev server (<kbd>CTRL</kbd>+<kbd>C</kbd>) and run the following:
```bash
npx -y nuxi clean
npx -y nuxi cleanup
npx -y nuxi typecheck
npx -y yarn run dev
npx -y pnpm run dev
```
Loading `http://localhost:3000/pres` should show some JSON data:
```json
{
// ...
"data": {
"_path": "/pres",
// ...
"_id": "content:pres.xlsx",
"body": [
{
"name": "Sheet1", // <-- sheet name
"data": [ // <-- array of data objects
{
"Name": "Bill Clinton",
"Index": 42
},
```
5) Download [`pres.vue`](pathname:///nuxt/3/pres.vue) and save to `pages`:
5) Download [`pres.vue`](pathname:///nuxt/2/pres.vue) and save to `app/pages`:
```bash
curl -o pages/pres.vue https://docs.sheetjs.com/nuxt/3/pres.vue
curl -o app/pages/pres.vue https://docs.sheetjs.com/nuxt/2/pres.vue
```
Stop the dev server (<kbd>CTRL</kbd>+<kbd>C</kbd>) and run the following:
@ -718,24 +699,247 @@ Stop the dev server (<kbd>CTRL</kbd>+<kbd>C</kbd>) and run the following:
```bash
npx -y nuxi clean
npx -y nuxi cleanup
npx -y yarn run dev
npx -y pnpm run dev
```
The browser should now display an HTML table.
6) From the browser window in step 2, access `/pres` from the site. For example,
if the URL in step 2 was `http://localhost:3000/`, the new page should be
`http://localhost:3000/pres`.
6) To verify that hot loading works, open `pres.xlsx` from the `content` folder
This page should now display an HTML table.
7) To verify that hot loading works, open `pres.xlsx` from the `content` folder
with a spreadsheet editor.
Set cell `A7` to "SheetJS Dev" and set `B7` to `47`. Save the spreadsheet.
The page should automatically refresh with the new content.
8) Stop the server (press <kbd>CTRL</kbd>+<kbd>C</kbd> in the terminal window).
9) Copy `app/pages/pres.vue` to `app/pages/index.vue`:
```bash
cp app/pages/pres.vue app/pages/index.vue
```
:::info pass
In older test runs, the Nuxt starter created a default `/` page. The most recent
test did not create the index page, resulting in build errors. This step ensures
some sort of index page exists.
:::
10) Build the static site:
```bash
npx -y pnpm run generate
```
This will create a static site in `.output/public`, which can be served with:
```bash
npx -y http-server .output/public
```
Access the displayed URL (typically `http://localhost:8080`) in a web browser.
To confirm that the spreadsheet data is added to the site, view the page source.
Searching for `Bill Clinton` reveals the following encoded HTML row:
```html
<tr><td>Bill Clinton</td><td>42</td></tr>
```
## Nuxt Content v3
:::danger pass
When this demo was last tested, the official Nuxt Content v3 custom transformers
and custom collections examples did not work.
:::
[ViteJS modules](/docs/demos/static/vitejs) can be used in Nuxt v3.
### Installation
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
safely imported from `nuxt.config.ts` or transformer or module scripts. As long
as the SheetJS modules are not imported in the various `.vue` pages, the library
will not be added to the final page bundle!
### Configuration
The `vite` property in the NuxtJS config is passed to ViteJS. Plugins and other
configuration options can be copied to the object. `vite.config.js` for the
[Pure Data Plugin](/docs/demos/static/vitejs#pure-data-plugin) is shown below:
```js title="vite.config.js (raw ViteJS)"
import { readFileSync } from 'fs';
import { read, utils } from 'xlsx';
import { defineConfig } from 'vite';
export default defineConfig({
assetsInclude: ['**/*.xlsx'], // xlsx file should be treated as assets
plugins: [
{ // this plugin handles ?sheetjs tags
name: "vite-sheet",
transform(_code, id) {
if(!id.match(/\?sheetjs$/)) return;
var wb = read(readFileSync(id.replace(/\?sheetjs$/, "")));
var data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
return `export default JSON.parse('${JSON.stringify(data).replace(/\\/g, "\\\\")}')`;
}
}
]
});
```
The `assetsInclude` and `plugins` properties should be added within the `vite`
property in the object passed to `defineNuxtConfig`.
:::danger pass
NuxtJS does not properly honor the `?sheetjs` tag! As a result, the transform
explicitly tests for the `.xlsx` extension.
:::
```ts title="nuxt.config.ts"
import { readFileSync } from 'fs';
import { read, utils } from 'xlsx';
export default defineNuxtConfig({
// highlight-next-line
vite: { // these options are passed to ViteJS
assetsInclude: ['**/*.xlsx'], // xlsx file should be treated as assets
plugins: [
{ // this plugin handles .xlsx
name: "vite-sheet",
transform(_code, id) {
if(!id.match(/\.xlsx$/)) return;
var wb = read(readFileSync(id.replace(/\?sheetjs$/, "")));
var data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
return `export default JSON.parse('${JSON.stringify(data).replace(/\\/g, "\\\\")}')`;
}
},
],
},
// ...
```
### Template Use
Pages can reference spreadsheets using a relative file reference. The ViteJS
plugin will transform files with the `.xlsx` extension.
```js title="Script section of .vue VueJS page"
import data from '../../pres.xlsx'; // data is an array of objects
```
In the template, `data` is an array of objects that works with `v-for`[^4]:
```xml title="Template section of .vue VueJS page"
<table>
<thead><tr><th>Name</th><th>Index</th></tr></thead><tbody>
<!-- loop over the rows of each worksheet -->
<tr v-for="row in data" v-bind:key="row.Index">
<!-- here `row` is a row object generated from sheet_to_json -->
<td>{{ row.Name }}</td>
<td>{{ row.Index }}</td>
</tr>
</table>
```
### Nuxt Content 3 Demo
1) Create a stock app and install dependencies:
```bash
npx -y nuxi init -t content --packageManager pnpm --no-gitInit sheetjs-nc3 -M ,
cd sheetjs-nc3
npx -y pnpm install
```
2) Install the SheetJS library and start the server:
<CodeBlock language="bash">{`\
npx -y pnpm install --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
npx -y pnpm dev`}
</CodeBlock>
When the build finishes, the terminal will display a URL like:
```
> Local: http://localhost:3000/
```
The server is listening on that URL. Open the link in a web browser.
3) Download https://docs.sheetjs.com/pres.xlsx and move to the root folder:
```bash
curl -o pres.xlsx https://docs.sheetjs.com/pres.xlsx
```
4) Replace `nuxt.config.ts` with the following codeblock:
```ts title="nuxt.config.ts"
import { readFileSync } from 'fs';
import { read, utils } from 'xlsx';
export default defineNuxtConfig({
vite: { // these options are passed to ViteJS
assetsInclude: ['**/*.xlsx'], // xlsx file should be treated as assets
plugins: [
{ // this plugin handles .xlsx
name: "vite-sheet",
transform(_code, id) {
if(!id.match(/\.xlsx$/)) return;
var wb = read(readFileSync(id.replace(/\?sheetjs$/, "")));
var data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
return `export default JSON.parse('${JSON.stringify(data).replace(/\\/g, "\\\\")}')`;
}
},
],
},
modules: [
'@nuxt/content',
],
devtools: { enabled: true },
});
```
5) Create a new file `app.vue` with the following contents:
```jsx title="app.vue (create new file)"
<script setup>
import data from '../../pres.xlsx'
</script>
<template>
<table><thead><tr><th>Name</th><th>Index</th></tr></thead><tbody>
<tr v-for="row in data" v-bind:key="row.Index">
<td>{{ row.Name }}</td>
<td>{{ row.Index }}</td>
</tr>
</tbody></table>
</template>
```
6) Refresh the browser window. This page should now display an HTML table.
7) Stop the server (press <kbd>CTRL</kbd>+<kbd>C</kbd> in the terminal window).
8) Build the static site:
```bash
npx -y yarn run generate
npx -y pnpm run generate
```
This will create a static site in `.output/public`, which can be served with:

@ -345,7 +345,7 @@ AstroJS will place the generated site in the `dist` subfolder.
9) Start a web server to host the static site:
```bash
npx http-server dist
npx -y http-server dist
```
Open a web browser and access the displayed URL ( `http://localhost:8080` ).

@ -56,15 +56,15 @@ This demo was tested in the following environments:
| OS | Device | NS | Date |
|:-----------|:--------------------|:---------|:-----------|
| Android 30 | NVIDIA Shield | `8.7.2` | 2024-06-09 |
| iOS 15.1 | iPad Pro | `8.7.2` | 2024-06-09 |
| Android 30 | NVIDIA Shield | `8.9.2` | 2025-05-06 |
| iOS 15.1 | iPad Pro | `8.9.2` | 2025-05-06 |
**Simulators**
| OS | Device | NS | Dev Platform | Date |
|:-----------|:--------------------|:---------|:-------------|:-----------|
| Android 34 | Pixel 3a | `8.7.2` | `darwin-arm` | 2024-06-09 |
| iOS 17.5 | iPhone SE (3rd gen) | `8.7.2` | `darwin-arm` | 2024-06-09 |
| Android 35 | Pixel 9 Pro XL | `8.9.2` | `darwin-x64` | 2025-05-06 |
| iOS 18.4 | iPhone 16 Pro Max | `8.9.2` | `darwin-x64` | 2025-05-06 |
| Android 35 | Pixel 9 | `8.8.3` | `win11-x64` | 2024-12-21 |
| Android 35 | Pixel 9 | `8.8.3` | `linux-x64` | 2025-01-02 |
@ -78,15 +78,15 @@ NativeScript 8.6.1 split the telemetry into two parts: "usage" and "error". Both
must be disabled separately:
```bash
npx -p nativescript ns usage-reporting disable
npx -p nativescript ns error-reporting disable
npx -y -p nativescript ns usage-reporting disable
npx -y -p nativescript ns error-reporting disable
```
To verify telemetry was disabled:
```bash
npx -p nativescript ns usage-reporting status
npx -p nativescript ns error-reporting status
npx -y -p nativescript ns usage-reporting status
npx -y -p nativescript ns error-reporting status
```
:::
@ -120,6 +120,22 @@ for accessing data and are subject to change in future platform versions.
<details>
<summary><b>Technical Details</b> (click to show)</summary>
**iOS**
The following key/value pairs must be added to `Info.plist`:
```xml title="App_Resources/iOS/Info.plist (add highlighted lines)"
<dict>
<!-- highlight-start -->
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<!-- highlight-end -->
```
---
**Android**
Android security has evolved over the years. In newer Android versions, the
@ -265,8 +281,8 @@ const wb = read(ab);
0) Disable telemetry:
```bash
npx -p nativescript ns usage-reporting disable
npx -p nativescript ns error-reporting disable
npx -y -p nativescript ns usage-reporting disable
npx -y -p nativescript ns error-reporting disable
```
1) Follow the official Environment Setup instructions[^8].
@ -274,14 +290,14 @@ npx -p nativescript ns error-reporting disable
:::caution pass
In previous test runs, NativeScript did not support the latest Android API.
The error message from `npx -p nativescript ns doctor android` clearly stated
The error message from `npx -y -p nativescript ns doctor android` clearly stated
supported versions:
<pre>
<span {...r}></span> No compatible version of the Android SDK Build-tools are installed on your system. You can install any version in the following range: '&gt;=23 &lt;=33'.
</pre>
If NativeScript does not properly supports the latest API level, a previous API
If NativeScript does not properly support the latest API level, an older API
version should be installed using Android Studio.
In a previous test run, the following packages were required:
@ -290,14 +306,14 @@ In a previous test run, the following packages were required:
- `Android SDK Build-Tools` Version `33.0.2`
It is recommended to install the SDK Platform and corresponding Android SDK
Build-Tools for the latest supported API level.ß
Build-Tools for the latest supported API level.
:::
2) Test the local system configuration for Android development:
```bash
npx -p nativescript ns doctor android
npx -y -p nativescript ns doctor android
```
In the last macOS test, the following output was displayed:
@ -316,7 +332,7 @@ In the last macOS test, the following output was displayed:
<span {...g}></span> Javac is installed and is configured properly.
<span {...g}></span> The Java Development Kit (JDK) is installed and is configured properly.
<span {...g}></span> Getting NativeScript components versions information...
<span {...g}></span> Component nativescript has 8.7.2 version and is up to date.
<span {...g}></span> Component nativescript has 8.9.2 version and is up to date.
</pre>
</details>
@ -324,7 +340,7 @@ In the last macOS test, the following output was displayed:
3) Test the local system configuration for iOS development (macOS only):
```bash
npx -p nativescript ns doctor ios
npx -y -p nativescript ns doctor ios
```
In the last macOS test, the following output was displayed:
@ -343,9 +359,9 @@ In the last macOS test, the following output was displayed:
<span {...g}></span> CocoaPods are configured properly.
<span {...g}></span> Your current CocoaPods version is newer than 1.0.0.
<span {...g}></span> Python installed and configured correctly.
<span {...g}></span> Xcode version 15.4.0 satisfies minimum required version 10.
<span {...g}></span> Xcode version 16.3.0 satisfies minimum required version 10.
<span {...g}></span> Getting NativeScript components versions information...
<span {...g}></span> Component nativescript has 8.7.2 version and is up to date.
<span {...g}></span> Component nativescript has 8.9.2 version and is up to date.
</pre>
</details>
@ -355,21 +371,21 @@ In the last macOS test, the following output was displayed:
4) Create a skeleton NativeScript + Angular app:
```bash
npx -p nativescript ns create SheetJSNS --ng
npx -y -p nativescript ns create SheetJSNS --ng
```
5) Launch the app in the android simulator to verify the app:
5) Launch the app in the Android simulator to verify the app:
```bash
cd SheetJSNS
npx -p nativescript ns run android
npx -y -p nativescript ns run android
```
(this may take a while)
Once the simulator launches and the test app is displayed, end the script by
selecting the terminal and pressing <kbd>CTRL</kbd>+<kbd>C</kbd>. On Windows, if
prompted to `Terminate batch job`, type `y` and press Enter.
prompted to `Terminate batch job`, type <kbd>Y</kbd> and press Enter.
:::note pass
@ -381,6 +397,23 @@ Emulator start failed with: No emulator image available for device identifier 'u
:::
:::caution pass
In the most recent test, the build failed with an exception:
```
WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by net.rubygrapefruit.platform.internal.NativeLibraryLoader in an unnamed module (file:/Users/sheetjs/.gradle/wrapper/dists/gradle-8.7-bin/bhs2wmbdwecv87pi65oeuq5iu/gradle-8.7/lib/native-platform-0.22-milestone-25.jar)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled
```
**The NativeScript Gradle version is incompatible with Java 24!**
It is strongly recommended to roll back to Java 21.
:::
### Add SheetJS
:::note pass
@ -406,11 +439,10 @@ import { Component, OnInit } from '@angular/core'
// ...
export class ItemsComponent implements OnInit {
items: Array<Item>
// highlight-next-line
version = `SheetJS - ${version}`;
constructor(private itemService: ItemService) {}
itemService = inject(ItemService)
page = inject(Page)
// ...
```
@ -428,7 +460,7 @@ in the title of the action bar:
9) End the script and relaunch the app in the Android simulator:
```bash
npx -p nativescript ns run android
npx -y -p nativescript ns run android
```
The title bar should show the version.
@ -449,7 +481,7 @@ The title bar should show the version.
<Button text="Export File" (tap)="export()" style="padding: 10px"></Button>
</StackLayout>
<!-- highlight-end -->
<ListView [items]="items">
<ListView [items]="itemService.items()">
<!-- ... -->
</ListView>
<!-- highlight-next-line -->
@ -458,15 +490,15 @@ The title bar should show the version.
11) Add the `import` and `export` methods in the component script:
```ts title="src/app/item/items.component.ts"
```ts title="src/app/item/items.component.ts (add highlighted lines)"
// highlight-start
import { version, utils, read, write } from 'xlsx';
import { Dialogs, getFileAccess } from '@nativescript/core';
import { Folder, knownFolders, path } from '@nativescript/core/file-system';
// highlight-end
import { Component, OnInit } from '@angular/core'
import { Item } from './item'
import { Component, NO_ERRORS_SCHEMA, inject } from '@angular/core'
import { NativeScriptCommonModule, NativeScriptRouterModule } from '@nativescript/angular'
import { Page } from '@nativescript/core'
import { ItemService } from './item.service'
// highlight-start
@ -476,19 +508,12 @@ function get_url_for_filename(filename: string): string {
}
// highlight-end
@Component({
selector: 'ns-items',
templateUrl: './items.component.html',
})
export class ItemsComponent implements OnInit {
items: Array<Item>
version: string = `SheetJS - ${version}`;
// ...
constructor(private itemService: ItemService) {}
ngOnInit(): void {
this.items = this.itemService.getItems()
}
export class ItemsComponent {
version = `SheetJS - ${version}`;
itemService = inject(ItemService)
page = inject(Page)
// highlight-start
/* Import button */
@ -499,13 +524,14 @@ export class ItemsComponent implements OnInit {
async export() {
}
// highlight-end
}
// ...
```
12) End the script and relaunch the app in the Android simulator:
```bash
npx -p nativescript ns run android
npx -y -p nativescript ns run android
```
Two buttons should appear just below the header:
@ -534,7 +560,7 @@ Two buttons should appear just below the header:
const ws = wb.Sheets[wsname];
/* update table */
this.items = utils.sheet_to_json<Item>(ws);
this.itemService.items.set(utils.sheet_to_json(ws));
} catch(e) { await Dialogs.alert(e.message); }
// highlight-end
}
@ -547,7 +573,7 @@ Two buttons should appear just below the header:
try {
/* create worksheet from data */
const ws = utils.json_to_sheet(this.items);
const ws = utils.json_to_sheet(this.itemService.items());
/* create workbook from worksheet */
const wb = utils.book_new();
@ -569,7 +595,7 @@ Two buttons should appear just below the header:
14) Launch the app in the Android Simulator:
```bash
npx -p nativescript ns run android
npx -y -p nativescript ns run android
```
If the app does not automatically launch, manually open the `SheetJSNS` app.
@ -611,8 +637,8 @@ $bytes = [Convert]::FromBase64String($b64)
After the header row, insert a row and make the following assignments:
- Set cell `A2` to `0`
- Set cell `B2` to `SheetJS` (type `'SheetJS` in the formula bar)
- Set cell `C2` to `Library` (type `'Library` in the formula bar)
- Set cell `B2` to `SheetJS` (type `'SheetJS` in the formula bar)
- Set cell `C2` to `Library` (type `'Library` in the formula bar)
After making the changes, the worksheet should look like the following:
@ -620,8 +646,6 @@ After making the changes, the worksheet should look like the following:
id | name | role
# highlight-next-line
0 | SheetJS | Library
1 | Ter Stegen | Goalkeeper
3 | Piqué | Defender
...
```
@ -671,7 +695,7 @@ Scroll down to ["Fetching Files"](#android-device) for Android device testing.
20) Launch the app in the iOS Simulator:
```bash
npx -p nativescript ns run ios
npx -y -p nativescript ns run ios
```
21) Tap "Export File". A dialog will print where the file was written.
@ -681,8 +705,8 @@ npx -p nativescript ns run ios
After the header row, insert a row and make the following assignments:
- Set cell `A2` to `0`
- Set cell `B2` to `SheetJS` (type `'SheetJS` in the formula bar)
- Set cell `C2` to `Library` (type `'Library` in the formula bar)
- Set cell `B2` to `SheetJS` (type `'SheetJS` in the formula bar)
- Set cell `C2` to `Library` (type `'Library` in the formula bar)
After making the changes, the worksheet should look like the following:
@ -690,8 +714,6 @@ After making the changes, the worksheet should look like the following:
id | name | role
# highlight-next-line
0 | SheetJS | Library
1 | Ter Stegen | Goalkeeper
3 | Piqué | Defender
...
```
@ -704,31 +726,21 @@ The first item in the list will change:
### Fetching Files
25) In `src/app/item/items.component.ts`, make `ngOnInit` asynchronous:
```ts title="src/app/item/items.component.ts (replace existing function)"
async ngOnInit(): Promise<void> {
this.items = await this.itemService.getItems()
}
```
26) Replace `item.service.ts` with the following:
25) Replace `item.service.ts` with the following:
```ts title="src/app/item/item.service.ts"
import { Injectable } from '@angular/core'
import { knownFolders, path, getFileAccess } from '@nativescript/core'
import { getFile } from '@nativescript/core/http';
import { read, utils } from 'xlsx';
import { Injectable, signal, effect } from '@angular/core'
import { knownFolders, path, getFileAccess } from '@nativescript/core';
import { getFile } from '@nativescript/core/http';
import { Item } from './item'
interface IPresident { Name: string; Index: number };
@Injectable({ providedIn: 'root' })
export class ItemService {
private items: Array<Item>;
async getItems(): Promise<Array<Item>> {
items = signal<Item[]>([]);
constructor() { effect(() => { (async() => {
/* fetch https://docs.sheetjs.com/pres.xlsx */
const temp: string = path.join(knownFolders.temp().path, "pres.xlsx");
const ab = await getFile("https://docs.sheetjs.com/pres.xlsx", temp)
@ -736,32 +748,33 @@ export class ItemService {
const wb = read(await getFileAccess().readBufferAsync(ab.path));
/* translate the first worksheet to the required Item type */
const data = utils.sheet_to_json<IPresident>(wb.Sheets[wb.SheetNames[0]]);
return this.items = data.map((pres, id) => ({id, name: pres.Name, role: ""+pres.Index} as Item));
}
/* update state */
this.items.set(data.map((pres, id) => ({id, name: pres.Name, role: ""+pres.Index} as Item)));
})(); }); }
getItem(id: number): Item {
return this.items.filter((item) => item.id === id)[0]
return this.items().find((item) => item.id === id)
}
}
```
27) End the script and relaunch the app in the Android simulator:
26) End the script and relaunch the app in the Android simulator:
```bash
npx -p nativescript ns run android
npx -y -p nativescript ns run android
```
The app should show Presidential data.
### Android Device
28) Connect an Android device using a USB cable.
27) Connect an Android device using a USB cable.
If the device asks to allow USB debugging, tap "Allow".
29) Close any Android / iOS emulators.
28) Close any Android / iOS emulators.
30) Enable "Legacy External Storage" in the Android app. The manifest is stored
29) Enable "Legacy External Storage" in the Android app. The manifest is stored
at `App_Resources/Android/src/main/AndroidManifest.xml`:
```xml title="App_Resources/Android/src/main/AndroidManifest.xml (add highlighted line)"
@ -776,13 +789,13 @@ at `App_Resources/Android/src/main/AndroidManifest.xml`:
android:hardwareAccelerated="true">
```
31) Install the `@nativescript-community/perms` dependency:
30) Install the `@nativescript-community/perms` dependency:
```bash
npm i --save @nativescript-community/perms
```
32) Add the highlighted lines to `items.component.ts`:
31) Add the highlighted lines to `items.component.ts`:
- Import `File` from NativeScript core and `request` from the new dependency:
@ -815,10 +828,10 @@ import { Component, OnInit } from '@angular/core'
} catch(e) { await Dialogs.alert(e.message); }
```
33) Build APK and run on device:
32) Build APK and run on device:
```bash
npx -p nativescript ns run android
npx -y -p nativescript ns run android
```
If the Android emulators are closed and an Android device is connected, the last
@ -839,22 +852,59 @@ file named `SheetJSNS.xls`.
### iOS Device
34) Connect an iOS device using a USB cable
33) Connect an iOS device using a USB cable
35) Close any Android / iOS emulators.
34) Close any Android / iOS emulators.
36) Enable developer code signing certificates:
35) Enable developer code signing certificates:
Open `platforms/ios/SheetJSNS.xcodeproj/project.xcworkspace` in Xcode. Select
the "Project Navigator" and select the "App" project. In the main view, select
"Signing & Capabilities". Under "Signing", select a team in the dropdown menu.
the "Project Navigator" and select `SheetJSNS`. In the main view, select the
`SheetJSNS` target. Click "Signing & Capabilities". Under "Signing", select a
team in the dropdown menu.
:::caution pass
When this demo was last tested, Xcode repeatedly crashed.
The issue was resolved by cleaning the project:
```bash
npx -y -p nativescript ns platform clean ios
```
:::
36) Add the following key/value pairs to `Info.plist`:
```xml title="App_Resources/iOS/Info.plist (add highlighted lines)"
<dict>
<!-- highlight-start -->
<key>UIFileSharingEnabled</key>
<true/>
<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<!-- highlight-end -->
```
37) Run on device:
```bash
npx -p nativescript ns run ios
npx -y -p nativescript ns run ios
```
:::info pass
If this is the first time testing an app on a device, the certificate must be
trusted on the device:
Under "Settings" > "General" > "VPN & Device Management", there should be a
"Apple Development" certificate in the "DEVELOPER APP" section. Select the
certificate and confirm that "SheetJSNS" is listed under "APPS". Tap "Trust ..."
and tap "Trust" in the popup.
:::
<details open>
<summary><b>iOS Device Testing</b> (click to hide)</summary>
@ -863,8 +913,9 @@ connected to the Internet, a list of Presidents should be displayed.
Tap "Export File". The app will show an alert. Tap "OK".
Switch to the "Files" app and open the "Downloads" folder. There should be a new
file named `SheetJSNS.xls`.
Switch to the "Files" app and repeatedly tap "&lt;". In the "Browse" window, tap
"On My iPhone". There should be a new folder named "SheetJSNS". Tap the folder
and look for the file named `SheetJSNS.xls`.
</details>

@ -59,7 +59,7 @@ This demo was tested in the following environments:
|:-----------|:------------------|:--------|:---------|:-------------|:-----------|
| Android 35 | Pixel 9 Pro XL | `3.7.2` | `3.29.2` | `darwin-x64` | 2025-03-31 |
| iOS 18.3 | iPhone 16 Pro Max | `3.7.2` | `3.29.2` | `darwin-x64` | 2025-03-31 |
| Android 35 | Pixel 3a | `3.5.0` | `3.24.0` | `win11-x64` | 2024-08-10 |
| Android 36 | Pixel 9 Pro XL | `3.7.2` | `3.29.3` | `win11-x64` | 2054-04-28 |
:::
@ -244,7 +244,7 @@ Run `flutter doctor` and confirm the following items are checked:
<TabItem value="win" label="Windows">
<pre>
<span {...g}>[✓]</span> Android toolchain - develop for Android devices (Android SDK version 35.0.0)
<span {...g}>[✓]</span> Android toolchain - develop for Android devices (Android SDK version 35.0.1)
</pre>
</TabItem>
@ -260,7 +260,7 @@ Run `flutter doctor` and confirm the following items are checked:
On first run, there may be a warning with "Android toolchain":
```
[!] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[!] Android toolchain - develop for Android devices (Android SDK version 35.0.1)
! Some Android licenses not accepted. To resolve this, run: flutter doctor
--android-licenses
```
@ -386,9 +386,9 @@ Pixel_9_Pro_XL_API_35 • Pixel 9 Pro XL API 35 • Google • android
There should be at least one `android` emulator:
```
Id • Name • Manufacturer • Platform
Id • Name • Manufacturer • Platform
Pixel_3a_API_35 • Pixel 3a API 35 • Google • android
Pixel_9_Pro_XL • Pixel 9 Pro XL • Google • android
```
</TabItem>
@ -445,14 +445,43 @@ emulator -avd Pixel_9_Pro_XL_API_35
:::note pass
If `emulator` cannot be found, the folder must be added to the system path.
<Tabs groupId="os">
<TabItem value="macos" label="macOS">
On macOS, `~/Library/Android/sdk/emulator/` is the typical location for the
`emulator` binary. If it cannot be found, add the folder to `PATH`:
`emulator` binary:
```bash
export PATH="$PATH":~/Library/Android/sdk/emulator
emulator -avd Pixel_9_Pro_XL_API_35
```
</TabItem>
<TabItem value="win" label="Windows">
The Android SDK folder can be found in the SDK manager in Android Studio. It is
typically `%LOCALAPPDATA%\Android\Sdk`.
If it is not assigned, create a User environment variable named `ANDROID_HOME`
with the value set to the Android SDK folder.
---
There are three folders within the Android SDK folder that should be added to
the User `PATH` environment variable. Each folder holds a different tool:
| Folder | Command-line Tool |
|:------------------------------------------|:------------------|
| `%ANDROID_HOME%\emulator` | `emulator` |
| `%ANDROID_HOME%\cmdline-tools\latest\bin` | `avdmanager` |
| `%ANDROID_HOME%\platform-tools` | `adb` |
</TabItem>
</Tabs>
:::
</details>
@ -645,6 +674,13 @@ flutter -v -d emulator-5554 run
</details>
:::caution pass
In some test runs on low-power devices, it took 20 seconds for the app to fetch
and display data!
:::
:::info Troubleshooting
In some demo runs, the build failed with an Android SDK error:

@ -39,7 +39,7 @@ This demo was tested in the following deployments:
|:-------------|:---------------|:----------|:----------|:-----------|
| `darwin-x64` | `5.0.0-beta.4` | `14.15.3` | Pre-built | 2025-04-21 |
| `darwin-arm` | `4.0.0-rc.6` | `22.14.0` | Compiled | 2025-04-03 |
| `win11-x64` | `4.0.0-rc.6` | `14.15.3` | Pre-built | 2024-12-19 |
| `win11-x64` | `5.0.0-beta.4` | `14.15.3` | Pre-built | 2025-05-07 |
| `win11-arm` | `4.0.0-rc.6` | `22.14.0` | Compiled | 2025-02-23 |
| `linux-x64` | `5.0.0-beta.4` | `14.15.3` | Pre-built | 2025-04-21 |
| `linux-arm` | `4.0.0-rc.6` | `22.13.0` | Compiled | 2025-02-15 |

@ -38,8 +38,8 @@ This demo was tested in the following deployments:
| Architecture | Version | NodeJS | Date |
|:-------------|:--------|:---------|:-----------|
| `darwin-x64` | `5.8.1` | `18.5.0` | 2025-04-21 |
| `darwin-arm` | `5.8.1` | `18.5.0` | 2025-02-13 |
| `win11-x64` | `5.8.1` | `18.5.0` | 2024-12-19 |
| `darwin-arm` | `5.8.1` | `18.5.0` | 2025-05-11 |
| `win11-x64` | `5.8.1` | `18.5.0` | 2025-05-07 |
| `win11-arm` | `5.8.1` | `18.5.0` | 2025-02-23 |
| `linux-x64` | `5.8.1` | `18.5.0` | 2025-04-21 |
| `linux-arm` | `5.8.1` | `18.5.0` | 2025-02-15 |
@ -78,7 +78,7 @@ When this demo was last tested, `pkg` failed with an error referencing `node20`:
> Error! No available node version satisfies 'node20'
```
**`pkg` does not support NodeJS 20 or 22!**
**`pkg` does not support NodeJS 20 or 22 or 24!**
The local NodeJS version must be rolled back to version 18.

@ -32,7 +32,7 @@ This demo was tested in the following deployments:
|:-------------|:--------|:----------|:-----------|
| `darwin-x64` | `2.4.4` | `23.11.0` | 2025-04-21 |
| `darwin-arm` | `2.4.4` | `22.14.0` | 2025-04-03 |
| `win11-x64` | `2.4.4` | `16.20.2` | 2024-12-19 |
| `win11-x64` | `2.4.4` | `16.20.2` | 2025-05-07 |
| `linux-x64` | `2.4.4` | `23.11.0` | 2025-04-21 |
| `linux-arm` | `2.4.4` | `23.8.0` | 2025-02-15 |
@ -136,7 +136,7 @@ workload, Python 3.11, and NASM[^2].
:::caution pass
When the demo was last tested, the build failed:
In some test runs, the build failed:
```
Not an executable Python program
@ -168,8 +168,11 @@ When the demo was last tested on Windows, the build failed:
error MSB8020: The build tools for Visual Studio 2019 (Platform Toolset = 'v142') cannot be found. To build using the v142 build tools, please install Visual Studio 2019 build tools.
```
This error was fixed by installing the `v142` build tools through the Visual
Studio installer.
This error was fixed by installing the following components from Visual Studio:
- `C++/CLI support for v142 build tools`
- `MSVC v142 - VS 2019 - C++ x64/x86 build tools`
- `MSVC v142 - VS 2019 - C++ x64/x86 Spectre-mitigated libs`
:::

@ -81,7 +81,7 @@ This demo was last tested in the following deployments:
|:-------------|:---------|:-----------|
| `darwin-x64` | `1.2.10` | 2025-04-21 |
| `darwin-arm` | `1.2.8` | 2025-04-03 |
| `win11-x64` | `1.1.40` | 2024-12-19 |
| `win11-x64` | `1.2.13` | 2025-05-07 |
| `win11-arm` | `1.2.3` | 2025-02-23 |
| `linux-x64` | `1.1.43` | 2025-01-10 |
| `linux-arm` | `1.2.2` | 2025-02-16 |

@ -228,7 +228,7 @@ order of todo items in the export matches the list displayed in the webpage.
5) Start a local web server:
```bash
npx http-server .
npx -y http-server .
```
The command will display a URL (typically `http://localhost:8080`) which can be

@ -35,7 +35,7 @@ will be available in the future.
:::note Tested Deployments
This demo was last tested on 2024-06-12.
This demo was last tested on 2025-05-11.
:::
@ -59,7 +59,8 @@ Azure Functions Core Tools (`func`) telemetry is controlled through the
<Tabs groupId="os">
<TabItem value="unix" label="Linux/MacOS">
Add the following line to `.profile`, `.bashrc` and `.zshrc`:
Add the following line to `.profile`, `.bash_profile`, `.bashrc`, `.zprofile`,
`.zshrc`, and any other configuration files:
```bash
export FUNCTIONS_CORE_TOOLS_TELEMETRY_OPTOUT=1
@ -131,7 +132,7 @@ Uploaded files can be pulled into `ArrayBuffer` objects.
This function returns a promise that resolves to an `ArrayBuffer` object:
```js
```js title="Get raw data from an uploaded file"
const { Blob } = require('buffer');
async function get_file_from_request(request, form_field_name) {
@ -158,7 +159,7 @@ SheetJS workbook objects[^3] which can be processed with other API functions.
For example, a handler can use `sheet_to_csv`[^4] to generate CSV text from
user-submitted spreadsheets:
```js
```js title="Function that reads uploaded workbooks and converts to CSV"
const { Blob } = require('buffer');
const { app } = require('@azure/functions');
const XLSX = require('xlsx');
@ -194,7 +195,7 @@ The following example generates a sample worksheet using the `aoa_to_sheet`[^6]
method, generates a sample workbook using worksheet helper methods[^7], writes
the workbook to XLSX format in a Buffer, and sends the Buffer in the response:
```js
```js title="Function that exports data and initiates a download to XLSX"
const { app } = require('@azure/functions');
const XLSX = require('xlsx');
@ -299,10 +300,20 @@ Until the bugs are resolved, JavaScript should be preferred over TypeScript.
npm start
```
7) While the server is running, open a new terminal window and make a request:
The process will display the functions and respective URLs:
```text title="Expected output"
Functions:
SheetJSAzure: [GET,POST] http://localhost:7071/api/SheetJSAzure
(access this URL)------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
7) While the server is running, open a new terminal window and make a GET
request to the URL listed in the previous step:
```bash
curl -L http://localhost:7071/api/SheetJSAzure
curl http://localhost:7071/api/SheetJSAzure
```
The terminal should display `Hello, world!`
@ -333,7 +344,7 @@ npm start
make a POST request to the dev server:
```bash
curl -LO https://docs.sheetjs.com/pres.numbers
curl -o pres.numbers https://docs.sheetjs.com/pres.numbers
curl -X POST -F "upload=@pres.numbers" http://localhost:7071/api/SheetJSAzure
```
@ -354,19 +365,20 @@ Open in Excel or another spreadsheet editor to confirm the file is valid.
15) Click "+ Create"
16) Select the following options:
16) In the "Create Function App" screen, click "Consumption" and click "Select".
- "Select a hosting option": "Consumption"
17) In the next screen, select the following options:
- Type a memorable "Function Name" ("sheetjsazure" when last tested)
- Look for the "Function App name" input field and type a memorable function
name. When this demo was last tested, the name "sheetjsazure" was chosen.
- "Operating System": "Windows"
- "Runtime stack": select `Node.js`
17) Click "Review + create", then click "Create" to create the function.
18) Click "Review + create", then click "Create" to create the function.
The page will display a status message
The page will redirect to a new page. It will display a status message:
> ... Deployment is in progress
@ -374,21 +386,19 @@ When the resources are configured, the status will change to
> Your deployment is complete
18) Click "Go to Resource".
19) Take note of the URL from the "Essentials" table.
19) Click "Go to Resource".
#### Deploy to Azure
20) Sign into Azure:
20) Sign into Azure from the command line:
```
```bash
az login
```
The login flow resumes in the browser.
21) Deploy to Azure. Replace `FUNCTION_NAME` with the name from Step 16:
21) Deploy to Azure. Replace `FUNCTION_NAME` with the name from Step 17:
```bash
func azure functionapp publish FUNCTION_NAME
@ -429,7 +439,7 @@ make a POST request to the production server. Replace `FUNCTION_URL` with the
Invoke URL from Step 21:
```bash
curl -LO https://docs.sheetjs.com/pres.numbers
curl -o pres.numbers https://docs.sheetjs.com/pres.numbers
curl -X POST -F "upload=@pres.numbers" FUNCTION_URL
```
@ -546,9 +556,9 @@ requests and 2000 write requests per month.
- "Redundancy": select LRS (Locally-redundant storage)
5) Click "Review", then click "Create" to create the storage.
5) Click "Review + create", then click "Create" to create the storage.
The page will display a status message
The page will redirect to a new page. It will display a status message:
> ... Deployment is in progress
@ -596,11 +606,64 @@ npm init -y
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @azure/storage-blob`}
</CodeBlock>
14) Copy the [`SheetJSReadFromAzure.mjs` code block](#downloading-data) and save
to `SheetJSReadFromAzure.mjs`.
14) Save the following codeblock to `SheetJSReadFromAzure.mjs`:
15) Copy the [`SheetJSWriteToAzure.mjs` code block](#uploading-data) and save
to `SheetJSWriteToAzure.mjs`.
```js title="SheetJSReadFromAzure.mjs"
import { BlobServiceClient } from "@azure/storage-blob";
import { read, utils } from "xlsx";
/* replace these constants */
// highlight-start
const connStr = "<REPLACE WITH CONNECTION STRING>";
const containerName = "<REPLACE WITH CONTAINER NAME>";
// highlight-end
/* Blob name */
const blobName = "SheetJSBloblobber.xlsx";
/* get a readable stream*/
const blobServiceClient = BlobServiceClient.fromConnectionString(connStr);
const containerClient = blobServiceClient.getContainerClient(containerName);
const blobClient = containerClient.getBlobClient(blobName);
const response = (await blobClient.download()).readableStreamBody;
/* collect data into a Buffer */
const bufs = [];
for await(const buf of response) bufs.push(buf);
const downloaded = Buffer.concat(bufs);
/* parse downloaded buffer */
const wb = read(downloaded);
/* print first worksheet */
console.log(utils.sheet_to_csv(wb.Sheets[wb.SheetNames[0]]));
```
15) Save the following codeblock to `SheetJSWriteToAzure.mjs`:
```js title="SheetJSWriteToAzure.mjs"
import { BlobServiceClient } from "@azure/storage-blob";
import { write, utils } from "xlsx";
/* replace these constants */
// highlight-start
const connStr = "<REPLACE WITH CONNECTION STRING>";
const containerName = "<REPLACE WITH CONTAINER NAME>";
// highlight-end
/* Blob name */
const blobName = "SheetJSBloblobber.xlsx";
/* Create a simple workbook and write XLSX to buffer */
const ws = utils.aoa_to_sheet(["SheetJS".split(""), [5,4,3,3,7,9,5]]);
const wb = utils.book_new(); utils.book_append_sheet(wb, ws, "Sheet1");
const buf = write(wb, {type: "buffer", bookType: "xlsx"});
/* upload buffer */
const blobServiceClient = BlobServiceClient.fromConnectionString(connStr);
const containerClient = blobServiceClient.getContainerClient(containerName);
const blockBlobClient = containerClient.getBlockBlobClient(blobName);
const uploadBlobResponse = await blockBlobClient.upload(buf, buf.length);
```
16) Edit both `SheetJSReadFromAzure.mjs` and `SheetJSWriteToAzure.mjs`:
@ -616,7 +679,7 @@ the buffer to a file named `SheetJSBloblobber.xlsx` on Azure Blob Storage.
The read demo fetches `SheetJSBloblobber.xlsx` and displays the data.
```
```text title="Data in SheetJSBloblobber.xlsx"
| A | B | C | D | E | F | G |
---+---|---|---|---|---|---|---|
1 | S | h | e | e | t | J | S |
@ -641,7 +704,7 @@ node SheetJSReadFromAzure.mjs
It will fetch the file created in the previous step and display CSV rows.
```
```text title="Expected output"
S,h,e,e,t,J,S
5,4,3,3,7,9,5
```

@ -111,6 +111,7 @@ const jwt = new google.auth.JWT({
key: creds.private_key,
scopes: [
'https://www.googleapis.com/auth/spreadsheets', // Google Sheets
'https://www.googleapis.com/auth/drive', // Google Drive
'https://www.googleapis.com/auth/drive.file', // Google Drive
]
});
@ -495,7 +496,7 @@ At this point `wb` is a SheetJS workbook object[^10].
:::note Tested Deployments
This demo was last tested on 2024-06-08 using `googleapis` version `140.0.0`.
This demo was last tested on 2025-05-14 using `googleapis` version `148.0.0`.
The demo uses Sheets v4 and Drive v3 APIs.
:::
@ -551,10 +552,10 @@ be a selection box. Click the `▼` icon to show the modal.
If the selection box is missing, expand the browser window.
3) Click "NEW PROJECT" in the top right corner of the modal.
3) Click "New project" in the top right corner of the modal.
4) In the New Project screen, enter "SheetJS Test" in the Project name textbox
and select "No organization" in the Location box. Click "CREATE".
and select "No organization" in the Location box. Click "Create".
A notification will confirm that the project was created:
@ -569,14 +570,13 @@ The goal of this section is to enable Google Sheets API and Google Drive API.
:::
5) Open the Project Selector (`▼` icon) and select "SheetJS Test"
5) Click "Select a project" and select "SheetJS Test" from the Recent tab.
6) In the search bar, type "Enabled" and select "Enabled APIs & services". This
item will be in the "PRODUCTS & PAGES" part of the search results.
6) In the search bar, type "Enabled" and select "Enabled APIs & services".
#### Enable Google Sheets API
7) Near the top of the page, click "+ ENABLE APIS AND SERVICES".
7) Near the top of the page, click "+ Enable APIs and services".
8) In the search bar near the middle of the page (not the search bar at the top),
type "Sheets" and press <kbd>Enter</kbd>.
@ -585,11 +585,11 @@ In the results page, look for "Google Sheets API". Click the card
9) In the Product Details screen, click the blue "ENABLE" button.
10) Click the left arrow (`<-`) next to "API/Service details".
10) Click the left arrow (`<-`) next to "API/Service Details".
#### Enable Google Drive API
11) Near the top of the page, click "+ ENABLE APIS AND SERVICES".
11) Near the top of the page, click "+ Enable APIs and services".
12) In the search bar near the middle of the page (not the search bar at the top),
type "Drive" and press <kbd>Enter</kbd>.
@ -614,13 +614,13 @@ the top bar.
15) Click the Project Selector (`:·` icon) and select "SheetJS Test".
16) In the search bar, type "Credentials" and select the "Credentials" item with
subtitle "APIs & Services". This item will be in the "PRODUCTS & PAGES" group:
subtitle "APIs & Services":
![Credentials](pathname:///gsheet/creds.png)
17) Click "+ CREATE CREDENTIALS". In the dropdown, select "Service Account"
17) Click "+ Create credentials". In the dropdown, select "Service account"
18) Enter "SheetJService" for Service account name. Click "CREATE AND CONTINUE"
18) Enter "SheetJService" for Service account name. Click "Create and continue".
:::note pass
@ -628,24 +628,24 @@ The Service account ID is generated automatically.
:::
19) In Step 2 "Grant this service account access to project", click CONTINUE
19) In Step 2 "Grant this service account access to project", click Continue.
20) In Step 3 click "DONE". You will be taken back to the credentials screen
20) In Step 3 click "Done". You will be taken back to the credentials screen
#### Create JSON Key
21) Look for "SheetJService" in the "Service Accounts" table and click the email
address in the row.
22) Click "KEYS" in the horizontal bar near the top of the page.
22) Click "Keys" in the horizontal bar near the top of the page.
23) Click "ADD KEY" and select "Create new key" in the dropdown.
23) Click "Add key" and select "Create new key" in the dropdown.
24) In the popup, select the "JSON" radio button and click "CREATE".
24) In the popup, select the "JSON" radio button and click "Create".
The page will download a JSON file. If prompted, allow the download.
25) Click "CLOSE"
25) Click "Close"
### Create Document
@ -675,7 +675,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz googlea
29) Download [`init.mjs`](pathname:///gsheet/init.mjs):
```bash
curl -LO https://docs.sheetjs.com/gsheet/init.mjs
curl -o init.mjs https://docs.sheetjs.com/gsheet/init.mjs
```
Edit the marked lines near the top of the file:
@ -713,11 +713,12 @@ Shared a-long-string-of-characters with YOUR_ACCOUNT@gmail.com
The long string of characters after "Created Google Workbook" is the ID. Take
note of this ID.
31) Sign into Google Sheets. A shared document "SheetJS Test" should be
displayed in the table. It will be owned by the service account.
31) Sign into Google Drive and select "Shared with me" from the left sidebar. A
shared document "SheetJS Test" should be displayed in the table. It will be
owned by the service account.
32) Open the shared document from step 31 and confirm that the document has two
worksheets named "SheetJS1" and "SheetJS2".
32) Click `⋮` next to "SheetJS Test" and select "Open with" > "Google Sheets".
Confirm that the document has two worksheets named "SheetJS1" and "SheetJS2".
Confirm the worksheet data matches the following screenshots:
@ -786,13 +787,13 @@ NUMBERS file.
34) Download the [test file `pres.numbers`](https://docs.sheetjs.com/pres.numbers):
```bash
curl -LO https://docs.sheetjs.com/pres.numbers
curl -o pres.numbers https://docs.sheetjs.com/pres.numbers
```
35) Download [`load.mjs`](pathname:///gsheet/load.mjs):
```bash
curl -LO https://docs.sheetjs.com/gsheet/load.mjs
curl -o load.mjs https://docs.sheetjs.com/gsheet/load.mjs
```
Edit the marked lines near the top of the file:
@ -830,7 +831,7 @@ The goal of this section is to export the raw data from Google Sheets to XLSB.
38) Download [`dump.mjs`](pathname:///gsheet/dump.mjs):
```bash
curl -LO https://docs.sheetjs.com/gsheet/dump.mjs
curl -o dump.mjs https://docs.sheetjs.com/gsheet/dump.mjs
```
Edit the marked lines near the top of the file:
@ -876,7 +877,7 @@ assign a grid of values
43) Download [`raw.mjs`](pathname:///gsheet/raw.mjs):
```bash
curl -LO https://docs.sheetjs.com/gsheet/raw.mjs
curl -o raw.mjs https://docs.sheetjs.com/gsheet/raw.mjs
```
Edit the marked lines near the top of the file:

@ -266,7 +266,7 @@ function SheetJSEnregistrez() {
:::note Tested Deployments
This demo was last tested on 2024-05-27.
This demo was last tested on 2025-05-14.
:::

@ -0,0 +1,336 @@
---
title: Visualizing Data in VS Code
sidebar_label: Visual Studio Code
description: View Excel files directly in VS Code. Seamlessly browse spreadsheet data without leaving your editor using SheetJS. Navigate between worksheets and pages of data with a responsive
pagination_prev: demos/cloud/index
pagination_next: demos/bigdata/index
sidebar_custom_props:
summary: View Excel files directly within Visual Studio Code
---
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
[Visual Studio Code](https://code.visualstudio.com) is a popular code editor
that supports JavaScript extensions for customizing and enhancing functionality.
The ["Complete Example"](#complete-example) uses SheetJS in a VS Code extension
to view Excel files directly within the editor. The extension leverages the VS
Code "Custom Editor API"[^2] and "WebView API"[^1] to display spreadsheet data
as HTML tables.
:::tip pass
["SheetJS Spreadsheet Viewer"](https://marketplace.visualstudio.com/items?itemName=asadbek.sheetjs-demo)
is a sample extension based on this demo.
[The source code](https://git.sheetjs.com/asadbek064/sheetjs-vscode-extension)
is available on the SheetJS Git server. Feedback and contributions are welcome!
:::
![Expected output](pathname:///vscode/extension-viewing-xls-file.png)
:::note Tested Deployments
This demo was verified in the following deployments:
| Platform | Architecture | Date |
|:-----------------|:-------------|:-----------|
| VS Code 1.100.0 | `darwin-arm` | 2025-05-15 | TODO
| VSCodium 1.100.0 | `darwin-arm` | 2025-05-15 | TODO
| Cursor | `win11-arm` | 2025-05-15 | TODO
| Windsurf | `win11-arm` | 2025-05-15 | TODO
| Void | `win11-arm` | 2025-05-15 | TODO
:::
## Integration Details
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
imported from any component or script in the extension.
:::caution pass
The module must be installed as a development dependency. If the module is
installed as a normal dependency, `vsce`[^5] (Visual Studio Code Extension
Manager) will fail to package or publish your extension correctly.
<Tabs groupId="pm">
<TabItem value="npm" label="npm">
<CodeBlock language="bash">{`\
npm rm --save xlsx
npm i --save-dev https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
<TabItem value="pnpm" label="pnpm">
<CodeBlock language="bash">{`\
pnpm rm xlsx
pnpm install -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
<TabItem value="yarn" label="Yarn" default>
<CodeBlock language="bash">{`\
yarn remove xlsx
yarn add -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
</Tabs>
:::
## Extension Architecture
The VS Code Spreadsheet viewer extension has three main components:
- **Extension Entry Point:** Registers the extension with VS Code
- **Custom Editor Provider:** Handles Excel files and converts them to web content
- **WebView Content:** Displays Excel data as HTML tables
The extension uses VS Code's `Custom Editor API`[^2] to register as a handler for Excel files. When a file is opened,
SheetJS parses it and displays the data in a WebView component.
### Extension Entry Point
The main entry point registers the custom editor provider:
```ts title="src/extension.ts"
import * as vscode from 'vscode';
// highlight-start
import { ExcelEditorProvider } from './excelEditorProvider';
// highlight-end
export function activate(context: vscode.ExtensionContext) {
// SheetJS Spreadsheet Viewer extension activating...
// highlight-start
const provider = ExcelEditorProvider.register(context);
context.subscriptions.push(provider);
// highlight-end
}
export function deactivate() {}`}
```
The `custom editor`[^3] is configured to support specific file types, giving us complete control over how each file is
presented to the user. Additionally, `custom document`[^4] enables us to maintain and persist the state of each individual
file that's opened.
<CodeBlock language="typescript" value="typescript" title="src/excelEditorProvider.ts">
{`import * as vscode from 'vscode';
// highlight-start
import * as XLSX from 'xlsx';
import { ExcelDocument } from './excelDocument';
// highlight-end
// A simple class to store document state (one per opened file)
class ExcelDocument implements vscode.CustomDocument {
constructor(public readonly uri: vscode.Uri) {}
dispose() {}
}
export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
// ...
public static register(context: vscode.ExtensionContext): vscode.Disposable {
return vscode.window.registerCustomEditorProvider(
'excelViewer.spreadsheet',
new ExcelEditorProvider(),
{ webviewOptions: { retainContextWhenHidden: true } } // keep webview state when hidden
);
}
// ...
}`}
</CodeBlock>
### Reading Files
The extension reads Excel files using the VS Code filesystem API and passes
the data to SheetJS for parsing:
<CodeBlock language="typescript" value="typescript" title="src/excelEditorProvider.ts">
{`export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
// ...
private async loadWorkbook(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<XLSX.WorkBook> {
const data: Uint8Array = await vscode.workspace.fs.readFile(document.uri);
const options: XLSX.ParsingOptions = {
type: 'array',
cellStyles: true,
cellDates: true,
};
return XLSX.read(new Uint8Array(data), options); // returns a XLSX.WorkBook
}
// This is called when the first time an editor for a given resource is opened
async openCustomDocument(uri: vscode.Uri): Promise<ExcelDocument> {
return new ExcelDocument(uri);
}
// This is called whenever the user opens a new editor
async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<void> {
const wb: XLSX.WorkBook = await this.loadWorkbook(document, webviewPanel);
const htmlTable = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
webviewPanel.webview.html = \`<!DOCTYPE html><html><body>\${htmlTable}</body></html>\`;
}
}`}
</CodeBlock>
### Usage Flow
```mermaid
sequenceDiagram
actor User
participant VSCode as VS Code
participant Provider as ExcelEditorProvider
participant SheetJS
participant WebView
User->>VSCode: Open .xlsx file
VSCode->>Provider: openCustomDocument(uri)
Provider-->>VSCode: return ExcelDocument
VSCode->>Provider: resolveCustomEditor(document, webviewPanel)
Provider->>VSCode: workspace.fs.readFile(document.uri)
VSCode-->>Provider: return file data
Provider->>SheetJS: XLSX.read(data, options)
SheetJS-->>Provider: return workbook
Provider->>SheetJS: XLSX.utils.sheet_to_html(sheet)
SheetJS-->>Provider: return HTML
Provider->>WebView: set webview.html
WebView-->>User: Display Excel data
```
## Complete Example
1) Create a new VS Code extension
```bash
npx --package yo --package generator-code -- yo code
```
When prompted, enter the following options:
- `What type of extension do you want to create?`: Select `New Extension (TypeScript)` and press <kbd>Enter</kbd>
- `What's the name of your extension?`: Type `sheetjs-demo` and press <kbd>Enter</kbd>
- `What's the identifier of your extension?`: Press <kbd>Enter</kbd>
- `What's the description of your extension?`: Press <kbd>Enter</kbd>
- `Initialize a git repository?`: Type `n` and press <kbd>Enter</kbd>
- `Which bundler to use?`: Select `webpack` and press <kbd>Enter</kbd>
- `Which package manager to use?`: Select `pnpm` and press <kbd>Enter</kbd>
![Expected output](pathname:///vscode/yeo-code.png)
- `Do you want to open the new folder with Visual Studio Code?`: Press <kbd>Enter</kbd>
2) [Install the dependencies](#integration-details) and start the dev server:
<CodeBlock language="bash">{`\
cd sheetjs-demo
pnpm install -D https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
pnpm run watch
`}
</CodeBlock>
3) Save the following code snippet to `src/excelEditorProvider.ts`:
<CodeBlock language="typescript" value="typescript" title="src/excelEditorProvider.ts">{`\
import * as vscode from 'vscode';
import * as XLSX from 'xlsx';
class ExcelDocument implements vscode.CustomDocument {
constructor(public readonly uri: vscode.Uri) { }
dispose() { }
}
export class ExcelEditorProvider implements vscode.CustomReadonlyEditorProvider<ExcelDocument> {
public static register(context: vscode.ExtensionContext): vscode.Disposable {
return vscode.window.registerCustomEditorProvider(
'excelViewer.spreadsheet',
new ExcelEditorProvider(),
{ webviewOptions: { retainContextWhenHidden: true } } // keep webview state when hidden
);
}
private async loadWorkbook(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<XLSX.WorkBook> {
const data: Uint8Array = await vscode.workspace.fs.readFile(document.uri);
const options: XLSX.ParsingOptions = {
type: 'array',
cellStyles: true,
cellDates: true,
};
return XLSX.read(new Uint8Array(data), options); // returns a XLSX.WorkBook
}
// This is called when the first time an editor for a given resource is opened
async openCustomDocument(uri: vscode.Uri): Promise<ExcelDocument> {
return new ExcelDocument(uri);
}
// This is called whenever the user opens a new editor
async resolveCustomEditor(document: ExcelDocument, webviewPanel: vscode.WebviewPanel): Promise<void> {
const wb: XLSX.WorkBook = await this.loadWorkbook(document, webviewPanel);
const htmlTable = XLSX.utils.sheet_to_html(wb.Sheets[wb.SheetNames[0]]);
webviewPanel.webview.html = \`<!DOCTYPE html><html><body>\${htmlTable}</body></html>\`;
}
}`}
</CodeBlock>
4) Register the custom editor provider in `src/extension.ts`:
<CodeBlock language="typescript" value="typescript" title="src/extension.ts (replace contents)">{`\
import * as vscode from 'vscode';
import { ExcelEditorProvider } from './excelEditorProvider';
export function activate(context: vscode.ExtensionContext) {
// SheetJS Spreadsheet Viewer extension activating...
const provider = ExcelEditorProvider.register(context);
context.subscriptions.push(provider);
}
export function deactivate() {}`}
</CodeBlock>
5) Register the custom editor in the `contributes` section of `package.json`:
<CodeBlock language="json" value="json" title="package.json (add highlighted lines)">{`\
"main": "./dist/extension.js",
"contributes": {
// highlight-start
"customEditors": [
{
"viewType": "excelViewer.spreadsheet",
"displayName": "SheetJS Demo",
"selector": [
{ "filenamePattern": "*.xlsx" },
{ "filenamePattern": "*.xls" }
]
}
],
// highlight-end
"commands": [
{
"command": "sheetjs-demo.helloWorld",
"title": "Hello World"
}
]
},
`}
</CodeBlock>
6. Inside the editor, open `src/extension.ts` and press <kbd>F5</kbd> or run the command **Debug: Start Debugging**
from the Command Palette (<kbd>⇧⌘P</kbd>). This will compile and run the extension in a new Extension Development Host window.
7. Select the new VSCode Window and open a `.xlsx` or `.xls` file.
---
[^1]: See [`Webview API`](https://code.visualstudio.com/api/extension-guides/webview) for more details.
[^2]: See [`Custom Editor API`](https://code.visualstudio.com/api/extension-guides/custom-editors) documentation for more details.
[^3]: See [`Custom Editor`](https://code.visualstudio.com/api/extension-guides/custom-editors#custom-editor) for more details.
[^4]: See [`CustomDocument`](https://code.visualstudio.com/api/extension-guides/custom-editors#customdocument) for more details.
[^5]: See [`Visual Studio Code Extension Manager`](https://code.visualstudio.com/api/working-with-extensions/publishing-extension) for more details.

@ -55,7 +55,7 @@ This demo was tested in the following deployments:
|:-------------|:------------------|:-----------|
| `darwin-x64` | `18.5` (StataNow) | 2025-01-08 |
| `darwin-arm` | `18.5` (StataNow) | 2025-04-24 |
| `win11-x64` | `18.5` (StataNow) | 2024-12-19 |
| `win11-x64` | `18.5` (StataNow) | 2025-04-28 |
| `win11-arm` | `18.5` (StataNow) | 2025-02-23 |
| `linux-x64` | `18.5` (StataNow) | 2025-01-09 |
@ -257,6 +257,22 @@ curl -LO https://www.stata.com/plugins/stplugin.c
curl -LO https://www.stata.com/plugins/stplugin.h
```
:::danger pass
**When this demo was last tested, `stplugin.h` was removed from the website!**
If the official links do not work, the following files should be used:
- [`stplugin.c`](pathname:///stata/stplugin.c)
- [`stplugin.h`](pathname:///stata/stplugin.h)
```bash
curl -LO https://docs.sheetjs.com/plugins/stplugin.c
curl -LO https://docs.sheetjs.com/plugins/stplugin.h
```
:::
4) Download Duktape. In Windows, the following commands should be run in WSL. In
macOS, the commands should be run in the same Terminal session.
@ -463,67 +479,32 @@ The output will show the import result:
(2 vars, 5 obs)
</pre>
20) Open the Data Editor (in Browse or Edit mode) and compare to the screenshot:
20) List the dataset:
```stata
browse Name Index
list Name Index
```
The result should match the following listing:
```
. list Name Index
+----------------------+
| Name Index |
|----------------------|
1. | Bill Clinton 42 |
2. | GeorgeW Bush 43 |
3. | Barack Obama 44 |
4. | Donald Trump 45 |
5. | Joseph Biden 46 |
+----------------------+
```
In the Stata GUI, the Data Editor should match the following screenshot:
![Data Editor showing data from the file](pathname:///stata/data-editor.png)
:::info pass
In the terminal version of Stata, `browse` does not work:
```
. browse Name Index
command browse is unrecognized
r(199);
```
The `codebook` command will display details.
<details>
<summary><b>Expected Output</b> (click to show)</summary>
```text title="Expected output for 80-column terminal windows"
-------------------------------------------------------------------------------
Name Name
-------------------------------------------------------------------------------
Type: String (str12)
Unique values: 5 Missing "": 0/5
Tabulation: Freq. Value
1 "Barack Obama"
1 "Bill Clinton"
1 "Donald Trump"
1 "GeorgeW Bush"
1 "Joseph Biden"
Warning: Variable has embedded blanks.
-------------------------------------------------------------------------------
Index Index
-------------------------------------------------------------------------------
Type: Numeric (byte)
Range: [42,46] Units: 1
Unique values: 5 Missing .: 0/5
Tabulation: Freq. Value
1 42
1 43
1 44
1 45
1 46
```
</details>
:::
[^1]: Run `help import excel` in Stata or see ["import excel"](https://www.stata.com/manuals/dimportexcel.pdf) in the Stata documentation.
[^2]: See [`read` in "Reading Files"](/docs/api/parse-options)

@ -30,7 +30,7 @@ This demo was tested by SheetJS users in the following deployments:
| Architecture | Version | Date |
|:-------------|:--------|:-----------|
| `darwin-x64` | R2024b | 2025-03-31 |
| `win11-x64` | R2024b | 2024-12-21 |
| `win11-x64` | R2024b | 2025-05-10 |
:::
@ -234,14 +234,14 @@ run in the macOS Terminal or Windows PowerShell:
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz exit-on-epipe commander@2
curl -LO https://docs.sheetjs.com/cli/xlsx-cli.js
curl -o xlsx-cli.js https://docs.sheetjs.com/cli/xlsx-cli.js
npx -y nexe -t 14.15.3 xlsx-cli.js`}
</CodeBlock>
2) Download https://docs.sheetjs.com/pres.numbers to the workspace folder:
```bash
curl -LO https://docs.sheetjs.com/pres.numbers
curl -o pres.numbers https://docs.sheetjs.com/pres.numbers
```
4) Save the following to `SheetJSMATLAB.m` in the workspace folder:

@ -23,7 +23,7 @@ library to read data from spreadsheets and converts to a Maple-friendly format.
```mermaid
flowchart LR
ofile[(workbook\nXLSB file)]
ofile[(generic\nworkbook)]
nfile[(clean file\nXLSX)]
data[[Maple\nTable]]
ofile --> |Maple Extension\nSheetJS + Duktape| nfile
@ -37,7 +37,7 @@ This demo was tested by SheetJS users in the following deployments:
| Architecture | Version | Date |
|:-------------|:---------|:-----------|
| `darwin-x64` | `2024.0` | 2025-01-10 |
| `win11-x64` | `2024.0` | 2024-12-19 |
| `win11-x64` | `2024.2` | 2025-05-07 |
:::
@ -60,7 +60,7 @@ and generates clean XLSX files that Maple can import.
The extension function ultimately pairs the SheetJS `read`[^2] and `write`[^3]
methods to read data from the old file and write a new file:
```js
```js title="Script that will be run by Maple extension"
var workbook = XLSX.read(original_file_data, { type: "buffer" });
var new_file_data = XLSX.write(workbook, { type: "array", bookType: "xlsx" });
```
@ -84,6 +84,7 @@ flowchart LR
wb --> |SheetJS\n`write`| njbuf
njbuf --> |Duktape\nBuffer Ops| nbuf
nbuf --> |C\nWrite File| nfile
linkStyle 2,3 color:blue,stroke:blue;
```
### C Extensions
@ -128,7 +129,7 @@ file, exports data to `sheetjsw.xlsx` and returns the string `"sheetjsw.xlsx"`.
This can be chained with `Import` from `ExcelTools`:
```maple
```maple title="Sample usage of SheetToXLSX extension"
with(ExcelTools);
Import(SheetToXLSX("pres.numbers"))
```

@ -130,7 +130,7 @@ This demo was tested in the following deployments:
|:-------------|:--------|:-----------|
| `darwin-x64` | `2.7.0` | 2025-03-31 |
| `darwin-arm` | `2.7.0` | 2025-02-13 |
| `win11-x64` | `2.7.0` | 2024-12-20 |
| `win11-x64` | `2.7.0` | 2025-04-28 |
| `win11-arm` | `2.7.0` | 2025-02-23 |
| `linux-x64` | `2.7.0` | 2025-04-21 |
| `linux-arm` | `2.7.0` | 2025-02-15 |
@ -692,7 +692,7 @@ The main Duktape code can be added to the Zig build pipeline.
:::note pass
The following explanation was verified against Zig 0.12.0.
The following explanation was verified against Zig 0.14.0.
:::
@ -710,7 +710,7 @@ folder must be added to the include path list:
```
The `duktape.c` source file must be added to the build sequence. For Zig version
0.12.0, Duktape must be compiled with flags `-std=c99 -fno-sanitize=undefined`
0.14.0, Duktape must be compiled with flags `-std=c99 -fno-sanitize=undefined`
and linked against `libc` and `libm`:
```zig title="build.zig"
@ -786,7 +786,7 @@ This demo was tested in the following deployments:
|:-------------|:--------|:---------|:-----------|
| `darwin-x64` | `2.7.0` | `0.14.0` | 2025-03-31 |
| `darwin-arm` | `2.7.0` | `0.13.0` | 2025-02-13 |
| `win11-x64` | `2.7.0` | `0.13.0` | 2024-12-20 |
| `win11-x64` | `2.7.0` | `0.14.0` | 2025-04-28 |
| `win11-arm` | `2.7.0` | `0.13.0` | 2025-02-23 |
| `linux-x64` | `2.7.0` | `0.14.0` | 2025-04-21 |
| `linux-arm` | `2.7.0` | `0.13.0` | 2025-02-15 |
@ -855,8 +855,8 @@ The following commands should be run within WSL bash.
For X64 Windows:
```bash
curl -LO https://ziglang.org/download/0.13.0/zig-windows-x86_64-0.13.0.zip
unzip zig-windows-x86_64-0.13.0.zip
curl -LO https://ziglang.org/download/0.14.0/zig-windows-x86_64-0.14.0.zip
unzip zig-windows-x86_64-0.14.0.zip
```
For ARM64 Windows:

@ -148,7 +148,7 @@ This demo was tested in the following deployments:
|:--------------|:-------------|:--------------|:-----------------|:-----------|
| `13.7.5` | `darwin-x64` | macOS 15.3.2 | `clang 16.0.0` | 2025-03-31 |
| `13.5.92` | `darwin-arm` | macOS 14.5 | `clang 16.0.0` | 2025-02-15 |
| `12.7.130` | `win11-x64` | Windows 11 | `CL 19.42.34435` | 2024-12-20 |
| `13.8.124` | `win11-x64` | Windows 11 | `CL 19.43.34810` | 2025-05-11 |
| `12.7.130` | `linux-x64` | HoloOS 3.6.20 | `gcc 13.2.1` | 2025-01-02 |
| `13.5.92` | `linux-arm` | Debian 12 | `gcc 12.2.0` | 2025-02-15 |
@ -204,13 +204,15 @@ installation steps.
Using the installer tool, the "Desktop development with C++" workload must be
installed. In the sidebar, verify the following components are checked:
- "C++ ATL for latest ... build tools" (`v143` when last tested)
- "C++ MFC for latest ... build tools" (`v143` when last tested)
- "C++ ATL for latest ... build tools (x86 & x64)" (`v143` when last tested)
- "C++ ATL for latest ... build tools with Spectre Mitigations (x86 & x64)" (`v143` when last tested)
- "C++ MFC for latest ... build tools (x86 & x64)" (`v143` when last tested)
- "C++ MFC for latest ... build tools with Spectre Mitigations (x86 & x64)" (`v143` when last tested)
In the "Individual components" tab, search for "Windows 11 SDK" and verify that
"Windows 11 SDK (10.0.22621.0)" is checked.
"Windows 11 SDK (10.0.26100.0)" is checked.
**Even though newer SDKs exist, Windows 11 SDK 10.0.22621.0 must be installed!**
**Even though newer SDKs may exist, V8 expects specific Windows SDK versions!**
Click "Modify" and allow the installer to finish.
@ -222,7 +224,7 @@ The SDK debugging tools must be installed after the SDK is installed.
available, search for "Installed apps".
2) When the setting panel opens, scroll down to "Windows Software Development
Kit - Windows 10.0.22621" and click "Modify".
Kit - Windows 10.0.26100" and click "Modify".
3) In the new window, select "Change" and click "Next"
@ -266,13 +268,12 @@ sudo chmod 777 /usr/local/lib
</TabItem>
<TabItem value="win" label="Windows">
[The bundle](https://storage.googleapis.com/chrome-infra/depot_tools.zip) is a
ZIP file that should be downloaded and extracted.
The demo was last tested on a NTFS-formatted drive (mounted at `C:\`). The ZIP
was extracted to `C:\src\depot_tools`.
After extracting, verify that the `depot_tools` folder is not read-only.
```bash
cd c:\
mkdir src
cd src
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
```
</TabItem>
</Tabs>
@ -334,7 +335,22 @@ gclient
gclient
```
:::caution pass
:::info Troubleshooting
In test runs on fresh machines, `gclient` failed with the following message:
```
Error: client not configured; see 'gclient config'
```
This was fixed by setting `user.name` and `user.email` in the Git configuration:
```bash
git config --global user.name "John Doe"
git config --global user.email "jdoe@email.com"
```
---
`gclient` may throw errors related to `git` and permissions issues:
@ -349,9 +365,7 @@ To add an exception for this directory, call:
These issues are related to the exFAT file system. They were resolved by running
the recommended commands and re-running `gclient`.
:::
:::caution pass
---
There may be errors pertaining to `gitconfig`:
@ -435,11 +449,11 @@ The recommended fix is to delete the referenced folder and re-run `gclient sync`
</Tabs>
5) Checkout the desired version. The following command pulls `13.7.5`:
5) Checkout the desired version. The following command pulls `13.8.124`:
```bash
git checkout tags/13.7.5 -b sample
git checkout tags/13.8.124 -b sample
```
:::caution pass
@ -447,14 +461,14 @@ git checkout tags/13.7.5 -b sample
The official documentation recommends:
```bash
git checkout refs/tags/13.7.5 -b sample -t
git checkout refs/tags/13.8.124 -b sample -t
```
This command failed in local testing:
```
E:\v8\v8>git checkout refs/tags/13.7.5 -b sample -t
fatal: cannot set up tracking information; starting point 'refs/tags/13.7.5' is not a branch
E:\v8\v8>git checkout refs/tags/13.8.124 -b sample -t
fatal: cannot set up tracking information; starting point 'refs/tags/13.8.124' is not a branch
```
:::
@ -643,6 +657,24 @@ python3 tools\dev\v8gen.py -vv x64.release.sample
ninja -C out.gn\x64.release.sample v8_monolith
```
:::info pass
If the expected Windows SDK version is missing or the debugging tools are not
installed, the build will fail with an error referencing `include`:
```
Exception: Path "C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um" from environment variable "include" does not exist. Make sure the necessary SDK is installed.
```
In the error message, the expected Windows SDK version is listed in the path.
For example, in the aforementioned message, `10.0.26100.0` is the SDK version.
The expected version of the Windows SDK should be installed from Visual Studio
Installer. After installing the SDK, the corresponding SDK debugging tools
should be installed using the procedure from Step 0.
:::
:::caution pass
In local testing, the build sometimes failed with a `dbghelp.dll` error:
@ -744,7 +776,7 @@ ld: multiple errors: unknown file type in '/Users/sheetjs/dev/v8/v8/out.gn/x64.r
```bash
g++ -I. -Iinclude samples/hello-world.cc -o hello_world -fno-rtti -lv8_monolith \
-lv8_libbase -lv8_libplatform -ldl -Lout.gn/x64.release.sample/obj/ -pthread \
-std=c++17 -DV8_COMPRESS_POINTERS=1 -DV8_ENABLE_SANDBOX
-std=c++20 -DV8_COMPRESS_POINTERS=1 -DV8_ENABLE_SANDBOX
./hello_world
```
@ -762,10 +794,32 @@ g++ -I. -Iinclude samples/hello-world.cc -o hello_world -fno-rtti -lv8_monolith
<TabItem value="win11-x64" label="Windows">
```bash
cl /I. /Iinclude samples/hello-world.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++17 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:hello_world.exe /LIBPATH:out.gn\x64.release.sample\obj\
cl /I. /Iinclude samples/hello-world.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++20 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:hello_world.exe /LIBPATH:out.gn\x64.release.sample\obj\
.\hello_world.exe
```
:::caution pass
When this demo was last tested, the build failed with a `C++` standard error:
```
c:\v8\v8\include\v8config.h(13): fatal error C1189: #error: "C++20 or later required."
```
The `/std:c++20` option sets the `C++` standard in use. The workaround is to
suppress the broken version check:
```c++ title="include\v8config.h (edit highlighted line)"
#if __cplusplus <= 201703L
// highlight-next-line
//#error "C++20 or later required."
#endif
```
After suppressing the error, re-run the build commands.
:::
</TabItem>
</Tabs>
@ -901,7 +955,7 @@ g++ -I. -Iinclude hello-world.cc -o hello_world -fno-rtti -lv8_monolith \
<TabItem value="win" label="Windows">
```bash
cl /MT /I..\v8\v8\ /I..\v8\v8\include hello-world.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++17 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:hello_world.exe /LIBPATH:..\v8\v8\out.gn\x64.release.sample\obj\
cl /MT /I..\v8\v8\ /I..\v8\v8\include hello-world.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++20 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:hello_world.exe /LIBPATH:..\v8\v8\out.gn\x64.release.sample\obj\
.\hello_world.exe
```
@ -974,7 +1028,7 @@ g++ -I. -Iinclude sheetjs.v8.cc -o sheetjs.v8 -fno-rtti -lv8_monolith \
<TabItem value="win" label="Windows">
```bash
cl /MT /I..\v8\v8\ /I..\v8\v8\include sheetjs.v8.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++17 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:sheetjs.v8.exe /LIBPATH:..\v8\v8\out.gn\x64.release.sample\obj\
cl /MT /I..\v8\v8\ /I..\v8\v8\include sheetjs.v8.cc /GR- v8_monolith.lib Advapi32.lib Winmm.lib Dbghelp.lib /std:c++20 /DV8_COMPRESS_POINTERS=1 /DV8_ENABLE_SANDBOX /link /out:sheetjs.v8.exe /LIBPATH:..\v8\v8\out.gn\x64.release.sample\obj\
```
</TabItem>
@ -1036,7 +1090,7 @@ This demo was last tested in the following deployments:
|:-------------|:----------|:-----------|
| `darwin-x64` | `136.0.0` | 2025-04-21 |
| `darwin-arm` | `134.3.0` | 2025-02-13 |
| `win11-x64` | `130.0.2` | 2024-12-20 |
| `win11-x64` | `137.1.0` | 2025-05-11 |
| `linux-x64` | `130.0.7` | 2025-01-09 |
| `linux-arm` | `134.4.0` | 2025-02-15 |
@ -1070,12 +1124,45 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.numbers`}
</CodeBlock>
:::note pass
In PowerShell, the command may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be invoked directly:
<CodeBlock language="bash">{`\
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl.exe -LO https://docs.sheetjs.com/pres.numbers`}
</CodeBlock>
:::
4) Download [`main.rs`](pathname:///v8/main.rs) and replace `src/main.rs`:
```bash
curl -L -o src/main.rs https://docs.sheetjs.com/v8/main.rs
```
:::note pass
In PowerShell, the command may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be invoked directly:
```bash
curl.exe -L -o src/main.rs https://docs.sheetjs.com/v8/main.rs
```
:::
:::info pass
There was a breaking change in version `0.102.0` affecting `v8::Context::new`.
@ -1119,7 +1206,7 @@ This demo was last tested in the following deployments:
|:-------------|:--------------|:--------|:----------|:-----------|
| `darwin-x64` | `13.2.152.16` | `4.1.1` | `24.0.1` | 2025-04-21 |
| `darwin-arm` | `13.2.152.16` | `4.1.1` | `17.0.14` | 2025-03-30 |
| `win11-x64` | `12.6.228.13` | `3.1.3` | `21.0.5` | 2024-12-20 |
| `win11-x64` | `13.2.152.16` | `4.1.1` | `17.0.13` | 2025-05-11 |
| `linux-x64` | `13.2.152.16` | `4.1.1` | `21.0.6` | 2025-04-21 |
| `linux-arm` | `13.2.152.16` | `4.1.1` | `17.0.14` | 2025-02-16 |
@ -1176,9 +1263,27 @@ curl -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet-v8-linux-arm64/4
<TabItem value="win" label="Windows">
```bash
curl -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet/3.1.3/javet-3.1.3.jar
curl -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet/4.1.1/javet-4.1.1.jar
curl -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet-v8-windows-x86_64/4.1.1/javet-v8-windows-x86_64-4.1.1.jar
```
:::note pass
In PowerShell, the command may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be invoked directly:
```bash
curl.exe -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet/4.1.1/javet-4.1.1.jar
curl.exe -LO https://repo1.maven.org/maven2/com/caoccao/javet/javet-v8-windows-x86_64/4.1.1/javet-v8-windows-x86_64-4.1.1.jar
```
:::
</TabItem>
</Tabs>
@ -1195,12 +1300,45 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.xlsx`}
</CodeBlock>
:::note pass
In PowerShell, the command may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be invoked directly:
<CodeBlock language="bash">{`\
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl.exe -LO https://docs.sheetjs.com/pres.xlsx`}
</CodeBlock>
:::
4) Download [`SheetJSJavet.java`](pathname:///v8/SheetJSJavet.java):
```bash
curl -LO https://docs.sheetjs.com/v8/SheetJSJavet.java
```
:::note pass
In PowerShell, the command may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be invoked directly:
```bash
curl.exe -LO https://docs.sheetjs.com/v8/SheetJSJavet.java
```
:::
5) Build and run the Java application:
<Tabs groupId="os">
@ -1245,8 +1383,8 @@ java -cp ".:javet-4.1.1.jar:javet-v8-linux-arm64-4.1.1.jar" SheetJSJavet pres.xl
<TabItem value="win" label="Windows">
```bash
javac -cp ".;javet-3.1.3.jar" SheetJSJavet.java
java -cp ".;javet-3.1.3.jar" SheetJSJavet pres.xlsx
javac -cp ".;javet-4.1.1.jar;javet-v8-windows-x86_64-4.1.1.jar" SheetJSJavet.java
java -cp ".;javet-4.1.1.jar;javet-v8-windows-x86_64-4.1.1.jar" SheetJSJavet pres.xlsx
```
</TabItem>
@ -1282,7 +1420,7 @@ This demo was last tested in the following deployments:
|:-------------|:--------------|:-----------|
| `darwin-x64` | `13.3.415.23` | 2025-03-31 |
| `darwin-arm` | `13.3.415.23` | 2025-03-31 |
| `win11-x64` | `12.3.219.12` | 2024-12-20 |
| `win11-x64` | `13.3.415.23` | 2025-05-11 |
| `win11-arm` | `12.3.219.12` | 2025-02-23 |
| `linux-x64` | `12.3.219.12` | 2025-01-10 |
| `linux-arm` | `12.3.219.12` | 2025-02-16 |
@ -1376,6 +1514,23 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.xlsx`}
</CodeBlock>
:::note pass
In PowerShell, the command may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be invoked directly:
<CodeBlock language="bash">{`\
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl.exe -LO https://docs.sheetjs.com/pres.xlsx`}
</CodeBlock>
:::
6) Replace `Program.cs` with the following:
```csharp title="Program.cs"
@ -1484,6 +1639,7 @@ This demo was last tested in the following deployments:
|:-------------|:--------------|:---------|:-----------|
| `darwin-x64` | `13.1.201.22` | `3.13.1` | 2025-03-31 |
| `darwin-arm` | `13.1.201.22` | `3.13.2` | 2025-04-24 |
| `win11-x64` | `13.1.201.22` | `3.11.9` | 2025-04-28 |
:::
@ -1548,6 +1704,26 @@ python sheetjs-stpyv8.py pres.xlsx
The script will display CSV rows from the first worksheet. It will also create
`SheetJSSTPyV8.xlsb`, a workbook that can be opened with a spreadsheet editor.
:::caution pass
On Windows, this may fail with a `charmap` error:
```
return codecs.charmap_decode(input,self.errors,decoding_table)[0]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 380: character maps to <undefined>
```
`sheetjs-stpyv8.py` must be altered to read `xlsx.full.min.js` with mode `rb`:
```python title="sheetjs-stpyv8.py (edit highlighted line)"
# Read xlsx.full.min.js
# highlight-next-line
with open("xlsx.full.min.js", "rb") as f:
```
:::
## Snapshots
At a high level, V8 snapshots are raw dumps of the V8 engine state. It is much
@ -1574,7 +1750,7 @@ This demo was last tested in the following deployments:
|:-------------|:--------------|:----------|:-----------|
| `darwin-x64` | `13.5.212.10` | `136.0.0` | 2025-04-21 |
| `darwin-arm` | `13.5.212.10` | `136.0.0` | 2025-04-24 |
| `win11-x64` | `12.6.228.3` | `0.92.0` | 2024-12-20 |
| `win11-x64` | `13.5.212.10` | `136.0.0` | 2025-05-11 |
| `linux-x64` | `12.6.228.3` | `0.92.0` | 2025-01-02 |
| `linux-arm` | `13.4.114.9` | `134.4.0` | 2025-02-15 |

@ -30,22 +30,23 @@ This demo was tested in the following deployments:
| OpenJDK | Rhino | Date |
|:--------|:---------|:-----------|
| 23.0.1 | `1.7.15` | 2025-01-10 |
| 22.0.2 | `1.7.15` | 2025-01-10 |
| 21.0.5 | `1.7.15` | 2025-01-10 |
| 20.0.2 | `1.7.15` | 2025-01-10 |
| 19.0.2 | `1.7.15` | 2025-01-10 |
| 18.0.2 | `1.7.15` | 2025-01-10 |
| 17.0.13 | `1.7.15` | 2025-01-10 |
| 16.0.2 | `1.7.15` | 2025-01-10 |
| 15.0.2 | `1.7.15` | 2025-01-10 |
| 14.0.2 | `1.7.15` | 2025-01-10 |
| 13.0.2 | `1.7.15` | 2025-01-10 |
| 12.0.2 | `1.7.15` | 2025-01-10 |
| 11.0.25 | `1.7.15` | 2025-01-10 |
| 10.0.2 | `1.7.15` | 2025-01-10 |
| 9.0.4 | `1.7.15` | 2025-01-10 |
| 1.8.0 | `1.7.15` | 2025-01-10 |
| 24.0.1 | `1.7.15` | 2025-05-06 |
| 23.0.2 | `1.7.15` | 2025-05-06 |
| 22.0.2 | `1.7.15` | 2025-05-06 |
| 21.0.7 | `1.7.15` | 2025-05-06 |
| 20.0.2 | `1.7.15` | 2025-05-06 |
| 19.0.2 | `1.7.15` | 2025-05-06 |
| 18.0.2 | `1.7.15` | 2025-05-06 |
| 17.0.15 | `1.7.15` | 2025-05-06 |
| 16.0.1 | `1.7.15` | 2025-05-06 |
| 15.0.10 | `1.7.15` | 2025-05-06 |
| 14.0.2 | `1.7.15` | 2025-05-06 |
| 13.0.2 | `1.7.15` | 2025-05-06 |
| 12.0.1 | `1.7.15` | 2025-05-06 |
| 11.0.27 | `1.7.15` | 2025-05-06 |
| 10 | `1.7.15` | 2025-05-06 |
| 9.0.4 | `1.7.15` | 2025-05-06 |
| 1.8.0 | `1.7.15` | 2025-05-06 |
:::

@ -165,7 +165,7 @@ This demo was tested in the following deployments:
|:-------------|:--------|:-----------|
| `darwin-x64` | `4.2.1` | 2025-03-31 |
| `darwin-arm` | `4.2.0` | 2025-02-13 |
| `win11-x64` | `4.1.0` | 2024-12-20 |
| `win11-x64` | `4.2.2` | 2026-04-28 |
| `win11-arm` | `4.2.0` | 2025-02-23 |
| `linux-x64` | `4.1.0` | 2025-01-09 |
| `linux-arm` | `4.2.0` | 2025-02-15 |
@ -248,7 +248,7 @@ dotnet run
```bash
dotnet nuget add source https://www.myget.org/F/jint/api/v3/index.json
dotnet add package Jint --version 4.2.1
dotnet add package Jint --version 4.2.2
```
To verify Jint is installed, replace `Program.cs` with the following:
@ -283,6 +283,25 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.xlsx`}
</CodeBlock>
:::caution pass
PowerShell `curl` is incompatible with the official `curl` program. The command
may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be used instead:
<CodeBlock language="bash">{`\
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl.exe -LO https://docs.sheetjs.com/pres.xlsx`}
</CodeBlock>
:::
6) Replace `Program.cs` with the following:
```csharp title="Program.cs"
@ -499,7 +518,7 @@ cp bin/Release/net*/linux-arm64/publish/SheetJSJint .
For Windows 11 x64, the RID is `win-x64` and the command is:
```powershell
copy .\bin\Release\net9.0\win-x64\publish\SheetJSJint.exe .
copy .\bin\Release\net*\win-x64\publish\SheetJSJint.exe .
```
:::caution pass
@ -513,7 +532,7 @@ The system cannot find the path specified.
The correct command was
```powershell
copy .\bin\x64\Release\net9.0\win-x64\publish\SheetJSJint.exe .
copy .\bin\x64\Release\net*\win-x64\publish\SheetJSJint.exe .
```
:::

@ -107,7 +107,7 @@ This demo was tested in the following deployments:
|:-------------|:-----------|:-----------|:-----------|
| `darwin-x64` | `bcd7cc6` | `1.24.1` | 2025-03-31 |
| `darwin-arm` | `5ef83b8` | `1.24.0` | 2025-02-13 |
| `win11-x64` | `79f3a7e` | `1.23.4` | 2024-12-20 |
| `win11-x64` | `bcd7cc6` | `1.24.2` | 2025-04-28 |
| `win11-arm` | `5ef83b8` | `1.24.0` | 2025-02-23 |
| `linux-x64` | `79f3a7e` | `1.22.0` | 2025-01-02 |
| `linux-arm` | `5ef83b8` | `1.19.8` | 2025-02-15 |
@ -141,12 +141,48 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.numbers`}
</CodeBlock>
:::caution pass
PowerShell `curl` is incompatible with the official `curl` program. The command
may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be used instead:
<CodeBlock language="bash">{`\
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl.exe -LO https://docs.sheetjs.com/pres.numbers`}
</CodeBlock>
:::
2) Download [`SheetGoja.go`](pathname:///goja/SheetGoja.go):
```bash
curl -LO https://docs.sheetjs.com/goja/SheetGoja.go
```
:::caution pass
PowerShell `curl` is incompatible with the official `curl` program. The command
may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be used instead:
```bash
curl.exe -LO https://docs.sheetjs.com/goja/SheetGoja.go
```
:::
3) Build the standalone `SheetGoja` binary:
```bash

@ -105,22 +105,23 @@ This demo was tested in the following deployments:
| OpenJDK | Nashorn | Date |
|:--------|:----------------|:-----------|
| 23.0.1 | 15.4 standalone | 2024-12-17 |
| 22.0.2 | 15.4 standalone | 2024-12-17 |
| 21.0.5 | 15.4 standalone | 2024-12-17 |
| 20.0.2 | 15.4 standalone | 2024-12-17 |
| 19.0.2 | 15.4 standalone | 2024-12-17 |
| 18.0.2 | 15.4 standalone | 2024-12-17 |
| 17.0.13 | 15.4 standalone | 2024-12-17 |
| 16.0.1 | 15.4 standalone | 2024-12-17 |
| 15.0.10 | 15.4 standalone | 2024-12-17 |
| 14.0.2 | Built-in | 2024-12-17 |
| 13.0.14 | Built-in | 2024-12-17 |
| 12.0.2 | Built-in | 2024-12-17 |
| 11.0.25 | Built-in | 2024-12-17 |
| 10.0.2 | Built-in | 2024-12-17 |
| 9 | Built-in | 2024-12-17 |
| 1.8.0 | Built-in | 2024-12-17 |
| 24.0.1 | 15.4 standalone | 2025-05-06 |
| 23.0.2 | 15.4 standalone | 2025-05-06 |
| 22.0.2 | 15.4 standalone | 2025-05-06 |
| 21.0.7 | 15.4 standalone | 2025-05-06 |
| 20.0.2 | 15.4 standalone | 2025-05-06 |
| 19.0.2 | 15.4 standalone | 2025-05-06 |
| 18.0.2 | 15.4 standalone | 2025-05-06 |
| 17.0.15 | 15.4 standalone | 2025-05-06 |
| 16.0.1 | 15.4 standalone | 2025-05-06 |
| 15.0.10 | 15.4 standalone | 2025-05-06 |
| 14.0.2 | Built-in | 2025-05-06 |
| 13.0.2 | Built-in | 2025-05-06 |
| 12.0.1 | Built-in | 2025-05-06 |
| 11.0.27 | Built-in | 2025-05-06 |
| 10 | Built-in | 2025-05-06 |
| 9.0.4 | Built-in | 2025-05-06 |
| 1.8.0 | Built-in | 2025-05-06 |
:::

@ -374,33 +374,33 @@ fork, which powers React Native for Windows, does have built-in support[^5]
| Architecture | Git Commit | Date |
|:-------------|:-----------|:-----------|
| `win11-x64` | `4c64b05` | 2024-12-20 |
| `win11-x64` | `254fb48` | 2025-04-28 |
| `win11-arm` | `4c64b05` | 2025-02-23 |
The ["Windows Example"](#windows-example) covers `hermes-windows`.
:::
0) Install [dependencies](https://hermesengine.dev/docs/building-and-running/#dependencies)
0) Install [dependencies](https://github.com/facebook/hermes/blob/eda3c083a57e9aa3b5b04df12ef8588b2961c02e/doc/BuildingAndRunning.md#dependencies)
<details>
<summary><b>Installation Notes</b> (click to show)</summary>
The official guidance[^6] has been verified in macOS and HoloOS (Linux).
On macOS:
On macOS, the Xcode command-line tools ship with `git`. The other dependencies
should be installed with `brew`:
```bash
brew install icu4c cmake ninja
```
On HoloOS (and other Arch Linux distros):
On HoloOS (and other Arch Linux distros), the dependencies must be installed
from the root user (using `sudo`):
```bash
sudo pacman -Syu cmake git ninja icu python zip readline
```
On Debian and Ubuntu:
On Debian and Ubuntu, `python-is-python3` should be installed:
```bash
sudo apt install cmake git ninja-build libicu-dev python3 python-is-python3 zip libreadline-dev
@ -408,7 +408,7 @@ sudo apt install cmake git ninja-build libicu-dev python3 python-is-python3 zip
:::note pass
When using virtual machines, Linux builds require at least 8 GB memory.
Linux builds require at least 8 GB memory.
:::
@ -690,7 +690,7 @@ cd sheetjs-hermes
```bash
git clone https://github.com/microsoft/hermes-windows
cd hermes-windows
git checkout 4c64b05
git checkout 254fb48
cd ..
```
@ -849,7 +849,7 @@ This demo was tested in the following deployments:
|:-------------|:---------|:-----------|
| `darwin-x64` | `0.13.0` | 2025-03-31 |
| `darwin-arm` | `0.13.0` | 2025-04-23 |
| `win11-x64` | `0.13.0` | 2024-12-20 |
| `win11-x64` | `0.13.0` | 2025-04-28 |
| `win11-arm` | `0.13.0` | 2025-02-23 |
| `linux-x64` | `0.13.0` | 2025-04-21 |
@ -978,6 +978,5 @@ If successful, the script will print CSV data from the test file.
[^3]: See ["Workbook Object"](/docs/csf/book)
[^4]: See [`sheet_to_csv` in "Utilities"](/docs/api/utilities/csv#csv-output)
[^5]: See [`microsoft/hermes-windows`](https://github.com/microsoft/hermes-windows) on GitHub
[^6]: See ["Dependencies" in "Building and Running"](https://hermesengine.dev/docs/building-and-running/#dependencies) in the Hermes Documentation. If this page redirects to the source repo, [see the following `archive.org` snapshot.](https://web.archive.org/web/20240103234151/http://hermesengine.dev/docs/building-and-running/)
[^7]: See ["Download Python"](https://www.python.org/downloads/) in the Python website. When the demo was last tested, Python 3.11.9 was installed.
[^8]: See [the Visual Studio website](https://visualstudio.microsoft.com/#vs-section) for download links.

@ -89,7 +89,7 @@ This demo was tested in the following deployments:
|:-------------|:---------|:---------|:-----------|
| `darwin-x64` | `2.6.10` | `2.10.0` | 2025-03-31 |
| `darwin-arm` | `2.6.10` | `2.10.0` | 2025-02-13 |
| `win11-x64` | `3.3.6` | `2.10.0` | 2024-12-20 |
| `win11-x64` | `3.3.8` | `2.10.0` | 2025-04-28 |
| `win11-arm` | `3.2.3` | `2.10.0` | 2025-02-23 |
| `linux-x64` | `3.2.3` | `2.10.0` | 2025-04-21 |
| `linux-arm` | `3.1.2` | `2.10.0` | 2025-02-15 |
@ -157,12 +157,47 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.numbers`}
</CodeBlock>
:::caution pass
PowerShell `curl` is incompatible with the official `curl` program. The command
may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be used instead:
<CodeBlock language="bash">{`\
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl.exe -LO https://docs.sheetjs.com/pres.numbers`}
</CodeBlock>
:::
3) Download [`ExecSheetJS.rb`](pathname:///execjs/ExecSheetJS.rb):
```bash
curl -LO https://docs.sheetjs.com/execjs/ExecSheetJS.rb
```
:::caution pass
PowerShell `curl` is incompatible with the official `curl` program. The command
may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be used instead:
```bash
curl.exe -LO https://docs.sheetjs.com/execjs/ExecSheetJS.rb
```
:::
4) Run the demo:
```bash

@ -134,7 +134,7 @@ This demo was tested in the following deployments:
|:-------------|:-----------|:-----------|
| `darwin-x64` | `36becec` | 2025-03-31 |
| `darwin-arm` | `e26c81f` | 2025-01-13 |
| `win11-x64` | `e26c81f` | 2024-12-19 |
| `win11-x64` | `36becec` | 2025-04-28 |
| `win11-arm` | `e26c81f` | 2025-02-23 |
| `linux-x64` | `e26c81f` | 2025-01-09 |
@ -575,7 +575,7 @@ If successful, the program will print the contents of the first sheet as CSV.
:::note Tested Deployments
This demo was last tested on 2025-03-31 against `ch` commit `36becec`.
This demo was last tested on 2025-04-28 against `ch` commit `36becec`.
:::

@ -106,7 +106,7 @@ This demo was tested in the following deployments:
|:-------------|:---------|:-----------|
| `darwin-x64` | `0.20.0` | 2025-03-31 |
| `darwin-arm` | `0.20.0` | 2025-02-13 |
| `win11-x64` | `0.20.0` | 2024-12-19 |
| `win11-x64` | `0.20.0` | 2025-04-28 |
| `win11-arm` | `0.20.0` | 2025-02-23 |
| `linux-x64` | `0.20.0` | 2025-04-21 |
| `linux-arm` | `0.20.0` | 2025-02-15 |
@ -152,12 +152,47 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://docs.sheetjs.com/pres.xlsx`}
</CodeBlock>
:::caution pass
PowerShell `curl` is incompatible with the official `curl` program. The command
may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be used instead:
<CodeBlock language="bash">{`\
curl.exe -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl.exe -LO https://docs.sheetjs.com/pres.xlsx`}
</CodeBlock>
:::
4) Download [`main.rs`](pathname:///boa/main.rs) and replace `src/main.rs`:
```bash
curl -L -o src/main.rs https://docs.sheetjs.com/boa/main.rs
```
:::caution pass
PowerShell `curl` is incompatible with the official `curl` program. The command
may fail with a parameter error:
```
Invoke-WebRequest : A parameter cannot be found that matches parameter name 'LO'.
```
`curl.exe` must be used instead:
```bash
curl.exe -L -o src/main.rs https://docs.sheetjs.com/boa/main.rs
```
:::
5) Build and run the app in release mode:
```bash

@ -54,13 +54,14 @@ This demo was tested in the following deployments:
| OpenJDK | GraalJS | Date |
|:--------|:--------|:-----------|
| 23.0.1 | 24.1.1 | 2024-12-17 |
| 22.0.2 | 24.1.1 | 2024-12-17 |
| 21.0.5 | 24.1.1 | 2024-12-17 |
| 20.0.2 | 24.1.1 | 2024-12-17 |
| 19.0.2 | 24.1.1 | 2024-12-17 |
| 18.0.2 | 24.1.1 | 2024-12-17 |
| 17.0.13 | 24.1.1 | 2024-12-17 |
| 24.0.1 | 24.2.1 | 2025-05-06 |
| 23.0.2 | 24.2.1 | 2025-05-06 |
| 22.0.2 | 24.2.1 | 2025-05-06 |
| 21.0.7 | 24.2.1 | 2025-05-06 |
| 20.0.2 | 24.2.1 | 2025-05-06 |
| 19.0.2 | 24.2.1 | 2025-05-06 |
| 18.0.2 | 24.2.1 | 2025-05-06 |
| 17.0.15 | 24.2.1 | 2025-05-06 |
:::
@ -69,14 +70,14 @@ This demo was tested in the following deployments:
0) Download GraalJS and its dependencies:
```bash
curl -LO "https://repo1.maven.org/maven2/org/graalvm/js/js-scriptengine/24.1.1/js-scriptengine-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/js/js-language/24.1.1/js-language-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/polyglot/polyglot/24.1.1/polyglot-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/sdk/collections/24.1.1/collections-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/truffle/truffle-api/24.1.1/truffle-api-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/sdk/nativeimage/24.1.1/nativeimage-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/shadowed/icu4j/24.1.1/icu4j-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/regex/regex/24.1.1/regex-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/js/js-scriptengine/24.2.1/js-scriptengine-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/js/js-language/24.2.1/js-language-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/polyglot/polyglot/24.2.1/polyglot-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/sdk/collections/24.2.1/collections-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/truffle/truffle-api/24.2.1/truffle-api-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/sdk/nativeimage/24.2.1/nativeimage-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/shadowed/icu4j/24.2.1/icu4j-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/regex/regex/24.2.1/regex-24.2.1.jar"
```
1) Download the SheetJS Standalone script, shim script and test file. Move all
@ -117,14 +118,14 @@ CSV rows from the first worksheet.
<TabItem value="unix" label="Linux/MacOS">
```bash
java -cp ".:js-scriptengine-24.1.1.jar:js-language-24.1.1.jar:polyglot-24.1.1.jar:collections-24.1.1.jar:truffle-api-24.1.1.jar:nativeimage-24.1.1.jar:icu4j-24.1.1.jar:regex-24.1.1.jar" -Dpolyglot.js.nashorn-compat=true SheetJSNashorn pres.xlsx
java -cp ".:js-scriptengine-24.2.1.jar:js-language-24.2.1.jar:polyglot-24.2.1.jar:collections-24.2.1.jar:truffle-api-24.2.1.jar:nativeimage-24.2.1.jar:icu4j-24.2.1.jar:regex-24.2.1.jar" -Dpolyglot.js.nashorn-compat=true SheetJSNashorn pres.xlsx
```
</TabItem>
<TabItem value="win" label="Windows">
```bash
java -cp ".;js-scriptengine-24.1.1.jar;js-language-24.1.1.jar;polyglot-24.1.1.jar;collections-24.1.1.jar;truffle-api-24.1.1.jar;nativeimage-24.1.1.jar;icu4j-24.1.1.jar;regex-24.1.1.jar" -D"polyglot.js.nashorn-compat=true" SheetJSNashorn pres.xlsx
java -cp ".;js-scriptengine-24.2.1.jar;js-language-24.2.1.jar;polyglot-24.2.1.jar;collections-24.2.1.jar;truffle-api-24.2.1.jar;nativeimage-24.2.1.jar;icu4j-24.2.1.jar;regex-24.2.1.jar" -D"polyglot.js.nashorn-compat=true" SheetJSNashorn pres.xlsx
```
</TabItem>
@ -154,14 +155,14 @@ cd sheethorn
<TabItem value="unix" label="Linux/MacOS">
```bash
java -cp ".:js-scriptengine-24.1.1.jar:js-language-24.1.1.jar:polyglot-24.1.1.jar:collections-24.1.1.jar:truffle-api-24.1.1.jar:nativeimage-24.1.1.jar:icu4j-24.1.1.jar:regex-24.1.1.jar:SheetJSNashorn.jar" -Dpolyglot.js.nashorn-compat=true SheetJSNashorn pres.xlsx
java -cp ".:js-scriptengine-24.2.1.jar:js-language-24.2.1.jar:polyglot-24.2.1.jar:collections-24.2.1.jar:truffle-api-24.2.1.jar:nativeimage-24.2.1.jar:icu4j-24.2.1.jar:regex-24.2.1.jar:SheetJSNashorn.jar" -Dpolyglot.js.nashorn-compat=true SheetJSNashorn pres.xlsx
```
</TabItem>
<TabItem value="win" label="Windows">
```bash
java -cp ".;js-scriptengine-24.1.1.jar;js-language-24.1.1.jar;polyglot-24.1.1.jar;collections-24.1.1.jar;truffle-api-24.1.1.jar;nativeimage-24.1.1.jar;icu4j-24.1.1.jar;regex-24.1.1.jar;SheetJSNashorn.jar" -D"polyglot.js.nashorn-compat=true" SheetJSNashorn pres.xlsx
java -cp ".;js-scriptengine-24.2.1.jar;js-language-24.2.1.jar;polyglot-24.2.1.jar;collections-24.2.1.jar;truffle-api-24.2.1.jar;nativeimage-24.2.1.jar;icu4j-24.2.1.jar;regex-24.2.1.jar;SheetJSNashorn.jar" -D"polyglot.js.nashorn-compat=true" SheetJSNashorn pres.xlsx
```
</TabItem>

@ -1,4 +1,4 @@
{
"label": "Other Languages",
"label": "JavaScript Engines",
"position": 42
}

@ -39,7 +39,7 @@ It is strongly recommended to create a separate page listing all embedded open
source software. The "open source disclosure" should be linked from relevant
pages including Terms of Service (ToS) and End User License Agreement (EULA)
[Office 365](https://web.archive.org/web/20240412032204/https://tasks.office.com/license.html)
[Office 365](https://web.archive.org/web/20250511192103/https://tasks.office.com/license.html)
includes the short-form attribution in a special license page.
<details>

@ -367,7 +367,7 @@ This,is,a,Test
The test suite is regularly run against a number of modern and legacy browsers
using [Sauce Labs](https://saucelabs.com/).
The following chart shows test results on 2024-10-20 for version `0.20.3`:
The following chart shows test results on 2025-05-15 for version `0.20.3`:
[![Build Status](pathname:///test/sheetjs.svg)](https://saucelabs.com/u/sheetjs)

@ -15,6 +15,10 @@
},
"overrides": {
"@cmfcmf/docusaurus-search-local": {
"@algolia/autocomplete-theme-classic": "1.19.1",
"@algolia/autocomplete-js": "1.19.1",
"@algolia/client-search": "5.25.0",
"algoliasearch": "5.25.0",
"@docusaurus/core": "3.7.0"
}
},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 12 KiB

@ -1,4 +1,4 @@
import SheetJSModule from './sheetmodule'
import SheetJSModule from './sheetmodule';
export default defineNuxtConfig({
// @ts-ignore

@ -2,7 +2,7 @@
import { defineTransformer } from "@nuxt/content/transformers/utils";
import { read, utils } from "xlsx";
import { readFileSync } from "node:fs";
import { resolve } from 'node:path';
import { resolve } from "node:path";
export default defineTransformer({
name: 'sheetformer',

@ -0,0 +1,14 @@
/*
stplugin.c, version 3.0
copyright (c) 2003, 2006, 2015 StataCorp LP
*/
#include "stplugin.h"
ST_plugin *_stata_ ;
STDLL pginit(ST_plugin *p)
{
_stata_ = p ;
return(SD_PLUGINVER) ;
}

@ -0,0 +1,246 @@
/*
stplugin.h, version 3.0.0
copyright (c) 2003, 2004, 2006, 2015 StataCorp LP
*/
#if !defined(STPLUGIN_H)
#define STPLUGIN_H
#if !defined(SD_FASTMODE)
#define SD_SAFEMODE
#endif
#define HP9000 1
#define OPUNIX 2
#define APPLEMAC 3
#define STWIN32 4
#ifndef SYSTEM
#define SYSTEM STWIN32
#endif
typedef signed char ST_sbyte ;
typedef unsigned char ST_ubyte ;
typedef int ST_int ;
typedef unsigned ST_unsigned ;
typedef short int ST_int2 ;
typedef int ST_int4 ;
typedef long ST_long ;
typedef unsigned int ST_uint4 ;
typedef float ST_float ;
typedef double ST_double ;
typedef unsigned char ST_boolean ;
typedef int ST_retcode ;
typedef double * ST_dmkey ;
#if !defined(bTrue)
#define bTrue 1
#define bFalse 0
#endif
#define SF_HIWORD(x) ((ST_int2)((ST_int4)(x)>>16))
#define SF_LOWORD(x) ((ST_int2)(x))
#define SF_MAKELONG(x,y) ((ST_int4)(((ST_int2)(x))|((ST_int4)((ST_int2)(y)))<<16))
#if SYSTEM==STWIN32
#if __cplusplus
#define STDLL extern "C" __declspec(dllexport) ST_retcode
#else
#define STDLL extern __declspec(dllexport) ST_retcode
#endif
#endif
#if SYSTEM!=STWIN32
#if SYSTEM==HP9000
#include <dl.h>
#endif
#if SYSTEM==OPUNIX
#include <dlfcn.h>
#endif
#if __cplusplus
#define STDLL extern "C" ST_retcode
#else
#define STDLL ST_retcode
#endif
#define LPSTR char *
#endif
typedef struct {
ST_int type ;
ST_int nel ;
ST_int m ;
ST_int n ;
} ST_matinfo ;
#define SD_PLUGINMAJ 3
#define SD_PLUGINMIN 0
#define SD_PLUGINVER SF_MAKELONG(SD_PLUGINMAJ,SD_PLUGINMIN)
typedef void (* ST_VV) (void) ;
typedef ST_int (* ST_IV) (void) ;
typedef ST_int (* ST_IS) (char *) ;
typedef void (* ST_VU) (ST_ubyte) ;
typedef ST_boolean (* ST_BI) (ST_int) ;
typedef ST_boolean (* ST_BII) (ST_int,ST_int) ;
typedef ST_boolean (* ST_BD) (ST_double) ;
typedef ST_int (* ST_III) (ST_int,ST_int) ;
typedef ST_double (* ST_DII) (ST_int,ST_int) ;
typedef ST_double (* ST_DV) (void) ;
typedef ST_double (* ST_DD) (ST_double) ;
typedef ST_double (* ST_DDD) (ST_double,ST_double) ;
typedef ST_int (* ST_ISS) (char *,char *) ;
typedef ST_int (* ST_ISI) (char *,ST_int) ;
typedef ST_int (* ST_ISSI) (char *,char *,ST_int) ;
typedef void (* ST_VSD) (char *,ST_double) ;
typedef ST_int (* ST_ISD) (char *, ST_double) ;
typedef ST_int (* ST_ISDp) (char *,ST_double *) ;
typedef ST_int (* ST_ISDpIIIII) (char *,ST_int,ST_double *,ST_int,ST_int,ST_int,ST_int,ST_int) ;
typedef ST_int (* ST_ISIID) (char *, ST_int, ST_int, ST_double) ;
typedef ST_int (* ST_ISIIDp) (char *,ST_int,ST_int,ST_double *) ;
typedef ST_int (* ST_ISDpI) (char *,ST_double *,ST_int) ;
typedef void (* ST_VSMip) (char *,ST_matinfo *) ;
typedef ST_int (* ST_IIIDp) (ST_int, ST_int, ST_double *) ;
typedef ST_int (* ST_IIID) (ST_int, ST_int, ST_double) ;
typedef char * (* ST_SSI) (char *,ST_int) ;
typedef char * (* ST_SSSD) (char *,char *,ST_double) ;
typedef char * (* ST_SSSDM) (char *,char *,ST_double, ST_dmkey) ;
typedef ST_int (* ST_IIIS) (ST_int, ST_int, char *) ;
typedef ST_int (* ST_IIISI) (ST_int, ST_int, char *, ST_int) ;
typedef struct {
ST_IS spoutsml ;
ST_IS spoutnosml ;
ST_VV spoutflush ;
ST_VU set_outputlevel ;
ST_ISI get_input ;
ST_IV pollstd ;
ST_IV pollnow ;
ST_SSSD safereforms ;
ST_SSSDM safereforml ;
ST_SSI gettok ;
ST_ISS macresave ;
ST_ISSI macuse ;
ST_ISDp scalaruse ;
ST_ISDp scalarsave ;
ST_ISDpIIIII matrixstore ;
ST_ISDpI matrixload ;
ST_VSMip matrixinfo ;
ST_ISIIDp matrixel ;
ST_int matsize ;
ST_DII data, safedata ;
ST_IV nobs ;
ST_IV nvar ;
ST_double missval ;
ST_BD ismissing ;
ST_ISI stfindvar ;
ST_BI isstr ;
ST_VSD abvarfcn ;
ST_int *stopflag ;
ST_DDD stround ;
ST_DD stsqrt ;
ST_DDD stpow ;
ST_DD stlog ;
ST_DD stexp ;
ST_DV strandom ;
ST_IIID store ;
ST_IIID safestore ;
ST_IIIS sstore ;
ST_BI selobs ;
ST_IV nobs1 ;
ST_IV nobs2 ;
ST_IV nvars ;
ST_IS spouterr ;
ST_ISIIDp safematel ;
ST_ISIID safematstore ;
ST_ISIIDp matel ;
ST_ISIID matstore ;
ST_IIIDp safevdata ;
ST_IIIDp vdata ;
ST_IS colsof ;
ST_IS rowsof ;
ST_ISD scalsave ;
ST_IIIS sdata ;
ST_int2 major ;
ST_int2 minor ;
ST_BI isstrl ;
ST_BII isbinary ;
ST_III sdatalen ;
ST_IIISI strldata ;
} ST_plugin ;
#if __cplusplus
extern "C" ST_plugin *_stata_ ;
#else
extern ST_plugin *_stata_ ;
#endif
STDLL pginit(ST_plugin *p) ;
#define SF_display(a) ((_stata_)->spoutsml((a)))
#define SF_error(a) ((_stata_)->spouterr((a)))
#define SF_poll ((_stata_)->pollstd)
#define SW_stopflag (*((_stata_)->stopflag))
#define SF_macro_save(m,t) ((_stata_)->macresave((m),(t)))
#define SF_macro_use(m,d,l) ((_stata_)->macuse((m),(d),(l)))
#define SF_scal_use(s,d) ((_stata_)->scalaruse((s),(d)))
#define SF_scal_save(s,d) ((_stata_)->scalsave((s),(d)))
#if defined(SD_SAFEMODE)
#define SF_mat_el(s,r,c,d) ((_stata_)->safematel((s),(r),(c),(d)))
#define SF_mat_store(s,r,c,d) ((_stata_)->safematstore((s),(r),(c),(d)))
#else
#define SF_mat_el(s,r,c,d) ((_stata_)->matel((s),(r),(c),(d)))
#define SF_mat_store(s,r,c,d) ((_stata_)->matstore((s),(r),(c),(d)))
#endif
#define SV_matsize ((_stata_)->matsize)
#define SF_col(s) ((_stata_)->colsof((s)))
#define SF_row(s) ((_stata_)->rowsof((s)))
#if defined(SD_SAFEMODE)
#define SF_vdata(i,j,d) ((_stata_)->safevdata((i),(j),(d)))
#define SF_vstore(i,j,v) ((_stata_)->safestore((i),(j),(v)))
#else
#define SF_vdata(i,j,d) ((_stata_)->vdata((i),(j),(d)))
#define SF_vstore(i,j,v) ((_stata_)->store((i),(j),(v)))
#endif
#define SF_nobs ((_stata_)->nobs)
#define SF_in1 ((_stata_)->nobs1)
#define SF_in2 ((_stata_)->nobs2)
#define SF_nvar ((_stata_)->nvar)
#define SF_nvars ((_stata_)->nvars)
#define SF_sstore(i,j,s) ((_stata_)->sstore((i),(j),(s)))
#define SF_sdata(i,j,s) ((_stata_)->sdata((i),(j),(s)))
#define SF_strldata(i,j,s,l) ((_stata_)->strldata((i),(j),(s),(l)))
#define SF_sdatalen(i,j) ((_stata_)->sdatalen((i),(j)))
#define SF_var_is_string(a) ((_stata_)->isstr(a))
#define SF_var_is_strl(a) ((_stata_)->isstrl(a))
#define SF_var_is_binary(i,j) ((_stata_)->isbinary((i),(j)))
#define SV_missval ((_stata_)->missval)
#define SF_is_missing(z) ((_stata_)->ismissing(z))
#define SF_ifobs(z) ((_stata_)->selobs(z))
#endif

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="890" height="480" data-created="2024-10-20T20:28:10.455635">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="890" height="480" data-created="2025-05-16T06:48:51.357946">
<defs>
<style>
@font-face {
@ -114,7 +114,7 @@
<svg x="5" y="68" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">131</text>
<text x="7" y="22" text-anchor="left" class="browser_version">138</text>
<use xlink:href="#windows" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10</text>
<use xlink:href="#passing" x="90" width="10"></use>
@ -123,7 +123,7 @@
</svg>
<svg x="220" y="0" width="119" height="280">
<svg x="220" y="0" width="119" height="315">
<use x="12" y="7" width="20" height="20" xlink:href="#chrome" fill="#333f4b"></use>
<text x="42" y="24" text-anchor="left" class="head">Chrome</text>
@ -197,6 +197,16 @@
</svg>
<svg x="5" y="272" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">136</text>
<use xlink:href="#windows" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
</svg>
<svg x="330" y="0" width="119" height="105">
@ -225,33 +235,13 @@
</svg>
<svg x="440" y="0" width="119" height="140">
<svg x="440" y="0" width="119" height="70">
<use x="12" y="7" width="20" height="20" xlink:href="#ios" fill="#333f4b"></use>
<text x="42" y="24" text-anchor="left" class="head">iPad</text>
<svg x="5" y="34" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">11</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10.13</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
<svg x="5" y="68" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">13</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10.15</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
<svg x="5" y="102" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">15</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">12</text>
@ -261,36 +251,16 @@
</svg>
<svg x="550" y="0" width="119" height="140">
<svg x="550" y="0" width="119" height="70">
<use x="12" y="7" width="20" height="20" xlink:href="#ios" fill="#333f4b"></use>
<text x="42" y="24" text-anchor="left" class="head">iPhone</text>
<svg x="5" y="34" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">10</text>
<text x="7" y="22" text-anchor="left" class="browser_version">15</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10.12</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
<svg x="5" y="68" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">12</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10.15</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
<svg x="5" y="102" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">14</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">11</text>
<text x="53" y="22" text-anchor="left" class="platform_version">12</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
@ -414,7 +384,7 @@
<svg x="5" y="408" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">130</text>
<text x="7" y="22" text-anchor="left" class="browser_version">135</text>
<use xlink:href="#windows" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10</text>
<use xlink:href="#passing" x="90" width="10"></use>
@ -423,83 +393,13 @@
</svg>
<svg x="770" y="0" width="119" height="350">
<svg x="770" y="0" width="119" height="105">
<use x="12" y="7" width="20" height="20" xlink:href="#safari" fill="#333f4b"></use>
<text x="42" y="24" text-anchor="left" class="head">Safari</text>
<svg x="5" y="34" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">8</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10.10</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
<svg x="5" y="68" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">9</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10.11</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
<svg x="5" y="102" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">10</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10.12</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
<svg x="5" y="136" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">11</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10.13</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
<svg x="5" y="170" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">12</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10.13</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
<svg x="5" y="204" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">13</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">10.15</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
<svg x="5" y="238" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">14</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">11</text>
<use xlink:href="#passing" x="90" width="10"></use>
</svg>
<svg x="5" y="272" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">15</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">12</text>
@ -508,9 +408,9 @@
<svg x="5" y="306" width="109" height="33" viewBox="0 0 109 33">
<svg x="5" y="68" width="109" height="33" viewBox="0 0 109 33">
<rect x="0" y="0" fill="#69cc01" width="109" height="33" />
<text x="7" y="22" text-anchor="left" class="browser_version">16</text>
<text x="7" y="22" text-anchor="left" class="browser_version">17</text>
<use xlink:href="#mac" x="34" width="15" fill="#000"></use>
<text x="53" y="22" text-anchor="left" class="platform_version">13</text>
<use xlink:href="#passing" x="90" width="10"></use>

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

@ -83,11 +83,11 @@ app.listen(7262, async() => {
});
EOF
npm i --save puppeteer express
npm i --save puppeteer express@4
node -e 'var pjson = JSON.parse(fs.readFileSync("./package.json")); console.log(pjson); delete pjson.main; fs.writeFileSync("package.json", JSON.stringify(pjson))'
for n in 1.12.3 2.13.3; do
for n in 2.14.4 1.12.3; do
npm i --save parcel@$n
npx -y parcel@$n build index.html
node test.js

@ -13,7 +13,7 @@ npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz exit-on-epipe c
## NOTE: must downgrade to node 18
npx -y pkg xlsx-cli.js
npx -y pkg -t 'node18-win-arm64,node18-linux-arm64,node18-macos-arm64' xlsx-cli.js
## NOTE: these steps are for darwin

17
tests/email/pst.sh Executable file

@ -0,0 +1,17 @@
#!/bin/bash
# https://docs.sheetjs.com/docs/demos/net/email/pst
cd /tmp
rm -rf sheetjs-pst
mkdir sheetjs-pst
cd sheetjs-pst
npm init -y
curl -LO https://docs.sheetjs.com/pst/SheetJSPST.js
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz pst-extractor@1.11.0
node --version
node SheetJSPST.js
bun --version
bun SheetJSPST.js

@ -5,14 +5,14 @@ rm -rf sheetjs-graaljs
mkdir -p sheetjs-graaljs
cd sheetjs-graaljs
curl -LO "https://repo1.maven.org/maven2/org/graalvm/js/js-scriptengine/24.1.1/js-scriptengine-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/js/js-language/24.1.1/js-language-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/polyglot/polyglot/24.1.1/polyglot-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/sdk/collections/24.1.1/collections-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/truffle/truffle-api/24.1.1/truffle-api-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/sdk/nativeimage/24.1.1/nativeimage-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/shadowed/icu4j/24.1.1/icu4j-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/regex/regex/24.1.1/regex-24.1.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/js/js-scriptengine/24.2.1/js-scriptengine-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/js/js-language/24.2.1/js-language-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/polyglot/polyglot/24.2.1/polyglot-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/sdk/collections/24.2.1/collections-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/truffle/truffle-api/24.2.1/truffle-api-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/sdk/nativeimage/24.2.1/nativeimage-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/shadowed/icu4j/24.2.1/icu4j-24.2.1.jar"
curl -LO "https://repo1.maven.org/maven2/org/graalvm/regex/regex/24.2.1/regex-24.2.1.jar"
curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js
curl -LO https://cdn.sheetjs.com/xlsx-latest/package/dist/shim.min.js
@ -20,19 +20,19 @@ curl -LO https://sheetjs.com/pres.xlsx
curl -LO https://docs.sheetjs.com/nashorn/SheetJSNashorn.java
for n in {17..23}; do
for n in {17..24}; do
export JAVA_HOME=`/usr/libexec/java_home -v $n`
java -version
rm -fr SheetJSNashorn.class SheetJSNashorn.jar sheethorn
javac SheetJSNashorn.java
java -cp ".:js-scriptengine-24.1.1.jar:js-language-24.1.1.jar:polyglot-24.1.1.jar:collections-24.1.1.jar:truffle-api-24.1.1.jar:nativeimage-24.1.1.jar:icu4j-24.1.1.jar:regex-24.1.1.jar" -Dpolyglot.js.nashorn-compat=true SheetJSNashorn pres.xlsx
java -cp ".:js-scriptengine-24.2.1.jar:js-language-24.2.1.jar:polyglot-24.2.1.jar:collections-24.2.1.jar:truffle-api-24.2.1.jar:nativeimage-24.2.1.jar:icu4j-24.2.1.jar:regex-24.2.1.jar" -Dpolyglot.js.nashorn-compat=true SheetJSNashorn pres.xlsx
jar -cf SheetJSNashorn.jar SheetJSNashorn.class xlsx.full.min.js shim.min.js
mkdir -p sheethorn
cp *.jar pres.xlsx sheethorn
cd sheethorn
java -cp ".:js-scriptengine-24.1.1.jar:js-language-24.1.1.jar:polyglot-24.1.1.jar:collections-24.1.1.jar:truffle-api-24.1.1.jar:nativeimage-24.1.1.jar:icu4j-24.1.1.jar:regex-24.1.1.jar:SheetJSNashorn.jar" -Dpolyglot.js.nashorn-compat=true SheetJSNashorn pres.xlsx
java -cp ".:js-scriptengine-24.2.1.jar:js-language-24.2.1.jar:polyglot-24.2.1.jar:collections-24.2.1.jar:truffle-api-24.2.1.jar:nativeimage-24.2.1.jar:icu4j-24.2.1.jar:regex-24.2.1.jar:SheetJSNashorn.jar" -Dpolyglot.js.nashorn-compat=true SheetJSNashorn pres.xlsx
cd -
done

@ -18,7 +18,7 @@ curl -L -o asm-analysis-9.5.jar "https://search.maven.org/remotecontent?filepath
curl -L -o asm-util-9.5.jar "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-util/9.5/asm-util-9.5.jar"
# Standalone Nashorn
for n in {15..23}; do
for n in {15..24}; do
echo $n
export JAVA_HOME=`/usr/libexec/java_home -v $n`
echo $JAVA_HOME

@ -42,7 +42,7 @@ public class SheetJSRhino {
}
EOF
for n in 1.8 {9..23}; do
for n in 1.8 {9..24}; do
export JAVA_HOME=`/usr/libexec/java_home -v $n`
java -version
find . -name \*.class | while read x; do rm $x; done

@ -13,7 +13,7 @@ curl -Lo _data/pres.xlsx https://docs.sheetjs.com/pres.xlsx
curl -L -o .eleventy.js https://docs.sheetjs.com/eleventy/_eleventy.js
curl -LO https://docs.sheetjs.com/eleventy/index.njk
for n in 2.0.1 3.0.0; do
for n in 2.0.1 3.0.0 3.1.0-beta.1; do
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz @11ty/eleventy@$n
npx @11ty/eleventy@$n