This commit is contained in:
SheetJS 2024-03-12 02:47:52 -04:00
parent 17d9d3d7cf
commit 2450d115db
51 changed files with 890 additions and 241 deletions

@ -21,6 +21,12 @@ $ make spell # spell check (.spelling custom dictionary)
$ make graph # build format graph and legend
```
### Engine Compatibility Tables
`docz/src/data/engines.xls` is an XLML workbook that controls the compatibility
tables in <https://docs.sheetjs.com/docs/demos/engines/>. The component script
`docz/src/data/engines.js` parses the file and generates content.
### Formats Graph
The formats graph and legend are written in the DOT language. Rebuilding the

@ -77,14 +77,15 @@
<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:Index="7" ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
</Row>
<Row>
<Cell><Data ss:Type="String">Rhino</Data></Cell>
<Cell><Data ss:Type="String">Java</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
@ -114,7 +115,7 @@
<Cell><Data ss:Type="String">Nashorn</Data></Cell>
<Cell><Data ss:Type="String">Java</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
@ -164,7 +165,7 @@
<Cell><Data ss:Type="String">JE</Data></Cell>
<Cell><Data ss:Type="String">Perl</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
@ -207,7 +208,7 @@
</WorksheetOptions>
</Worksheet>
<Worksheet ss:Name="Bindings">
<Table ss:ExpandedColumnCount="8" ss:ExpandedRowCount="7" x:FullColumns="1"
<Table ss:ExpandedColumnCount="8" ss:ExpandedRowCount="11" x:FullColumns="1"
x:FullRows="1" ss:DefaultColumnWidth="65" ss:DefaultRowHeight="16">
<Column ss:Index="3" ss:Width="24"/>
<Column ss:Width="31"/>
@ -235,7 +236,7 @@
<Cell><Data ss:Type="String">Duktape</Data></Cell>
<Cell><Data ss:Type="String">Perl</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
@ -245,7 +246,7 @@
<Cell><Data ss:Type="String">Duktape</Data></Cell>
<Cell><Data ss:Type="String">PHP</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
@ -255,8 +256,18 @@
<Cell><Data ss:Type="String">Duktape</Data></Cell>
<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"/>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
</Row>
<Row>
<Cell><Data ss:Type="String">Duktape</Data></Cell>
<Cell><Data ss:Type="String">Zig</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
@ -267,7 +278,8 @@
<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:Index="7" ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"/>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
<Cell ss:StyleID="s16"><Data ss:Type="String">✔</Data></Cell>
</Row>
<Row>

@ -1,4 +1,5 @@
---
title: NodeJS
pagination_prev: getting-started/index
pagination_next: getting-started/examples/index
sidebar_position: 3
@ -11,8 +12,6 @@ import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
# NodeJS
Package tarballs are available on <https://cdn.sheetjs.com>.
<p><a href={`https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}>https://cdn.sheetjs.com/xlsx-{current}/xlsx-{current}.tgz</a> is the URL for version {current}</p>
@ -158,7 +157,7 @@ The package supports CommonJS `require` and ESM `import` module systems.
:::
#### CommonJS `require`
### CommonJS `require`
By default, the module supports `require` and it will automatically add support
for streams and file system access:
@ -167,10 +166,16 @@ for streams and file system access:
var XLSX = require("xlsx");
```
#### ESM `import`
### ESM `import`
The module also ships with `xlsx.mjs` for use with `import`. The `mjs` version
does not automatically load native node modules, so they must be added manually:
The package also ships with `xlsx.mjs`, a script compatible with the ECMAScript
module system. When using the ESM build in NodeJS, some dependencies must be
loaded manually.
#### Filesystem Operations
The `set_fs` method accepts a `fs` instance for reading and writing files using
`readFile` and `writeFile`:
```js
import * as XLSX from 'xlsx';
@ -178,10 +183,29 @@ import * as XLSX from 'xlsx';
/* load 'fs' for readFile and writeFile support */
import * as fs from 'fs';
XLSX.set_fs(fs);
```
#### Stream Operations
The `set_readable` method accepts a `stream.Readable` instance for use in stream
methods such as `XLSX.stream.to_csv`:
```js
import * as XLSX from 'xlsx';
/* load 'stream' for stream support */
import { Readable } from 'stream';
XLSX.stream.set_readable(Readable);
```
#### Encoding Support
The `set_cptable` method accepts an instance of the SheetJS codepage library for
use in legacy file format processing. The `cpexcel.full.mjs` script must be
manually loaded. `xlsx/dist/cpexcel.full.mjs` can be imported:
```js
import * as XLSX from 'xlsx';
/* load the codepage support library for extended support with older formats */
import * as cpexcel from 'xlsx/dist/cpexcel.full.mjs';
@ -205,7 +229,8 @@ set_fs(fs);
:::
`fs` should be loaded with a dynamic import within a lifecycle function:
For server-side file processing, `fs` should be loaded with a dynamic import
within a lifecycle function:
```js title="index.js"
/* it is safe to import the library from the top level */

@ -8,9 +8,11 @@ sidebar_custom_props:
---
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
Tarballs are available on <https://cdn.sheetjs.com>.
Package tarballs are available on <https://cdn.sheetjs.com>.
<p><a href={`https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}>https://cdn.sheetjs.com/xlsx-{current}/xlsx-{current}.tgz</a> is the URL for version {current}</p>
@ -23,7 +25,7 @@ be reported to the Bun project for further diagnosis.
## Installation
Tarballs can be directly installed with `bun install`[^1]:
Tarballs can be directly installed with `bun install`:
<CodeBlock language="bash">{`\
bun install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
@ -37,15 +39,27 @@ new versions are released!
:::
:::warning pass
### Vendoring
At the time of writing `bun install` does not support vendored tarballs[^2].
For general stability, "vendoring" modules is the recommended approach:
:::
<p>1) Download the tarball (<code parentName="pre">xlsx-{current}.tgz</code>) for the desired version. The current
version is available at <a href={`https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}>https://cdn.sheetjs.com/xlsx-{current}/xlsx-{current}.tgz</a></p>
2) Create a `vendor` subfolder at the root of your project and move the tarball
to that folder. Add it to your project repository.
3) Install the tarball:
<CodeBlock language="bash">{`\
bun install file:vendor/xlsx-${current}.tgz`}
</CodeBlock>
The package will be installed and accessible as `xlsx`.
## Usage
Bun supports both "CommonJS" and "ESM" modules.
The package supports CommonJS `require` and ESM `import` module systems.
:::info pass
@ -53,7 +67,7 @@ Bun supports both "CommonJS" and "ESM" modules.
:::
#### CommonJS `require`
### CommonJS `require`
By default, the module supports `require` and it will automatically add support
for streams and file system access:
@ -63,7 +77,13 @@ const { readFile } = require("xlsx");
const wb = readFile("pres.numbers"); // works!
```
#### ESM `import`
:::caution pass
In the BunJS REPL, `require` incorrectly loads the ESM build.
:::
### ESM `import`
When importing the library using ESM `import` statements, the native NodeJS
modules are not loaded. They must be added manually:
@ -91,7 +111,7 @@ builder requires a proper `package.json` that includes the SheetJS dependency.
:::note Tested Deployments
This example was last tested on 2023 November 05 against BunJS 1.0.8.
This example was last tested on 2024-02-21 against BunJS 1.0.28 on macOS 14.3.1.
:::
@ -100,7 +120,7 @@ This example was last tested on 2023 November 05 against BunJS 1.0.8.
```bash
mkdir sheetjs-bun-dle
cd sheetjs-bun-dle
echo "{}" >> package.json
echo "{}" > package.json
```
1) Install the library:
@ -109,9 +129,9 @@ echo "{}" >> package.json
bun install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
2) Save the following script to `bun.js`:
2) Save the following script to `SheetJSBun.js`:
```js title="bun.js"
```js title="SheetJSBun.js"
// highlight-next-line
import * as XLSX from 'xlsx';
// highlight-next-line
@ -155,18 +175,20 @@ XLSX.writeFile(workbook, "Presidents.xlsx");
3) Bundle the script with `bun build`:
```bash
bun build --target=bun bun.js --outfile=app.js
bun build --target=bun SheetJSBun.js --outfile=app.js
```
This procedure will generate `app.js`.
4) Remove the `node_modules` directory and `package.json` file:
4) Remove the module artifacts and original script:
```bash
rm package.json
rm package.json bun.lockb SheetJSBun.js
rm -rf ./node_modules
```
At this point, `app.js` will be the only file in the project folder.
5) Run the script:
```bash
@ -175,6 +197,3 @@ bun app.js
If the script succeeded, the file `Presidents.xlsx` will be created. That file
can be opened in a spreadsheet editor.
[^1]: Bun releases before the official 1.0.0 release did not support tarball dependencies. If a pre-1.0.0 release must be used, the [ES Module script can be vendored](/docs/getting-started/installation/standalone#ecmascript-module-imports) or the [NodeJS module can be installed with a NodeJS-compatible package manager](/docs/getting-started/installation/nodejs).
[^2]: See [the relevant issue in the Bun issue tracker](https://github.com/oven-sh/bun/issues/101)

@ -3,7 +3,7 @@ pagination_prev: getting-started/index
pagination_next: getting-started/examples/index
hide_table_of_contents: true
title: Installation
------
---
import DocCardList from '@theme/DocCardList';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';

@ -41,6 +41,7 @@ This demo was tested in the following deployments:
| Architecture | JS Engine | Pandas | Python | Date |
|:-------------|:----------------|:-------|:-------|:-----------|
| `darwin-x64` | Duktape `2.7.0` | 2.0.3 | 3.11.7 | 2024-01-29 |
| `darwin-arm` | Duktape `2.7.0` | 2.0.3 | 3.11.7 | 2024-02-13 |
| `linux-x64` | Duktape `2.7.0` | 1.5.3 | 3.11.3 | 2024-01-29 |
:::
@ -358,6 +359,7 @@ This demo was tested in the following deployments:
| Architecture | JS Engine | Polars | Python | Date |
|:-------------|:----------------|:-------|:-------|:-----------|
| `darwin-x64` | Duktape `2.7.0` | 0.20.6 | 3.11.7 | 2024-01-30 |
| `darwin-arm` | Duktape `2.7.0` | 0.20.7 | 3.11.7 | 2024-02-13 |
| `linux-x64` | Duktape `2.7.0` | 0.20.6 | 3.11.3 | 2024-01-30 |
:::

@ -40,7 +40,7 @@ This demo was tested in the following environments:
| RequireJS | Date |
|:----------|:-----------|
| `2.3.6` | 2023-12-04 |
| `2.3.6` | 2024-03-01 |
| `2.1.22` | 2023-12-04 |
:::
@ -201,7 +201,7 @@ require(["xlsx"], function(XLSX) {
The `r.js` optimizer does not handle `async` functions or ES6 arrow functions.
To demonstrate compatibility with older versions of Webpack, `SheetJSRequire.js`
To demonstrate compatibility with older RequireJS releases, `SheetJSRequire.js`
uses normal functions and traditional Promise chains.
:::

@ -108,7 +108,7 @@ Each browser demo was tested in the following environments:
| Browser | Date |
|:------------|:-----------|
| Chrome 120 | 2024-01-15 |
| Safari 17.2 | 2023-01-15 |
| Safari 17.3 | 2024-02-21 |
:::

@ -20,10 +20,10 @@ with downloadable spreadsheets.
The ["Complete Example"](#complete-example) section includes a complete server.
:::note
:::note Tested Deployments
This demo was tested on 2023 October 16 using `express-formidable@1.2.0` and
ExpressJS `4.18.2`
This demo was tested on 2024 March 11 using `express-formidable@1.2.0` and
ExpressJS `4.18.3`
:::
@ -142,7 +142,7 @@ app.listen(+process.env.PORT||3000);
2) Install dependencies:
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz express@4.18.2 express-formidable@1.2.0`}
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz express@4.18.3 express-formidable@1.2.0`}
</CodeBlock>
3) Start server (note: it will not print anything to console when running)
@ -151,7 +151,8 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz express
node SheetJSExpressCSV.js
```
4) Test POST requests using <https://sheetjs.com/pres.numbers>:
4) Test POST requests using <https://sheetjs.com/pres.numbers> . The following
commands should be run in a new terminal window:
```bash
curl -LO https://sheetjs.com/pres.numbers

@ -20,9 +20,9 @@ downloadable spreadsheets.
The ["Complete Example"](#complete-example) section includes a complete server.
:::note
:::note Tested Deployments
This demo was last tested on 2023 October 16 against Drash 2.8.1 and Deno 1.37.2.
This demo was last tested on 2024 March 11 against Drash 2.8.1 and Deno 1.41.2.
:::

@ -19,9 +19,9 @@ downloadable spreadsheets.
The ["Complete Example"](#complete-example) section includes a complete server.
:::note
:::note Tested Deployments
This demo was last tested on 2023 October 17 against ElysiaJS 0.7.17 and BunJS 1.0.6.
This demo was last tested on 2024 March 11 with ElysiaJS 0.8.17 and BunJS 1.0.30.
:::
@ -151,7 +151,8 @@ app.listen(3000);
bun run src/SheetJSElysia.ts
```
5) Test POST requests using <https://sheetjs.com/pres.numbers>:
5) Test POST requests using <https://sheetjs.com/pres.numbers> . The following
commands should be run in a new terminal window:
```bash
curl -LO https://sheetjs.com/pres.numbers

@ -20,9 +20,9 @@ downloadable spreadsheets.
The ["Complete Example"](#complete-example) section includes a complete server.
:::note
:::note Tested Deployments
This demo was tested on 2023 October 15 using NestJS `10.2.7`.
This demo was tested on 2024 March 11 using NestJS `10.3.3`.
:::
@ -150,7 +150,7 @@ npx @nestjs/cli generate controller sheetjs
6) Replace `src/sheetjs/sheetjs.controller.ts` with the following code block:
```ts title="src/sheetjs/sheetjs.controller.js"
```ts title="src/sheetjs/sheetjs.controller.ts"
import { Controller, Get, Header, Post, StreamableFile, UploadedFile, UseInterceptors } from '@nestjs/common';
import { FileInterceptor } from '@nestjs/platform-express';
import { read, utils, write } from 'xlsx';
@ -204,11 +204,13 @@ The recommended fix is to install `@types/multer` again:
```bash
npm i --save-dev @types/multer
npx @nestjs/cli start
```
:::
8) Test POST requests in the terminal with <https://sheetjs.com/pres.numbers>:
8) Test POST requests using <https://sheetjs.com/pres.numbers> . The following
commands should be run in a new terminal window:
```bash
curl -LO https://sheetjs.com/pres.numbers

@ -19,9 +19,9 @@ with downloadable spreadsheets.
The ["Complete Example"](#complete-example) section includes a complete server.
:::note
:::note Tested Deployments
This demo was verified on 2023 October 16 using `fastify@4.24.2`
This demo was verified on 2024 March 11 using `fastify@4.26.2`
:::
@ -157,7 +157,7 @@ fastify.listen({port: process.env.PORT || 3000}, (err, addr) => { if(err) throw
1) Install dependencies:
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz fastify@4.24.2 @fastify/multipart@8.0.0`}
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz fastify@4.26.2 @fastify/multipart@8.1.0`}
</CodeBlock>
2) Start server
@ -166,7 +166,8 @@ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz fastify
node SheetJSFastify.js
```
3) Test POST requests using <https://sheetjs.com/pres.numbers>:
3) Test POST requests using <https://sheetjs.com/pres.numbers> . The following
commands should be run in a new terminal window:
```bash
curl -LO https://sheetjs.com/pres.numbers

@ -122,23 +122,29 @@ That approach is not explored in this demo.
<details><summary><b>Complete Example</b> (click to show)</summary>
:::note
:::note Tested Deployments
This demo was last tested on 2023 August 27 with NodeJS 20.5.1 + ExpressJS
4.18.2 + Formidable 2.1.1
This demo was tested in the following environments:
| NodeJS | Date | Dependencies |
|:----------|:-----------|:------------------------------------|
| `18.19.1` | 2024-02-23 | ExpressJS 4.18.2 + Formidable 2.1.2 |
| `20.11.1` | 2024-02-23 | ExpressJS 4.18.2 + Formidable 2.1.2 |
:::
0) Create a simple ECMAScript-Module-enabled `package.json`:
0) Create a new project with a ESM-enabled `package.json`:
```json title="package.json"
{ "type": "module" }
```bash
mkdir sheetjs-worker
cd sheetjs-worker
echo '{ "type": "module" }' > package.json
```
1) Install the dependencies:
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz express@4.18.2 formidable@2.1.1`}
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz express@4.18.2 formidable@2.1.2`}
</CodeBlock>
2) Create a worker script `worker.js` that listens for messages. When a message
@ -221,7 +227,10 @@ app.listen(7262, () => { console.log(`Example app listening on port 7262`); });
node main.mjs
```
Test with the [`pres.numbers` sample file](https://sheetjs.com/pres.numbers):
Keep the server process running during the test.
6) Test with the [`pres.numbers` sample file](https://sheetjs.com/pres.numbers).
The following commands should be run in a new terminal window:
```bash
curl -LO https://sheetjs.com/pres.numbers

@ -32,9 +32,9 @@ and generate HTML and CSV views of the underlying data.
The ["Live Demo"](#live-demo) reads PST files. Individual spreadsheets within
the file can be downloaded or previewed in the browser.
:::note
:::note Tested Deployments
This demo was last tested on 2023 October 22 against `pst-extractor` 1.9.0
This demo was last tested on 2024 March 11 against `pst-extractor` 1.9.0
:::
@ -197,6 +197,12 @@ This demo will fetch a [test PST](pathnamme:///pst/enron.pst) and extract all
embedded spreadsheets. The script can be adapted to read local PST files or pull
PST files from a different URL.
:::caution pass
The demo uses `fetch` and requires NodeJS 18 or later.
:::
0) Initialize a new project:
```bash

@ -37,17 +37,18 @@ or ban from Google services.
:::
### Email Details
#### App Passwords
### App Passwords
Many email providers (including Fastmail, GMail, and Yahoo Mail) require "app
passwords" or passwords for "less secure apps". Attempting to connect and send
using the account password will throw errors.
#### Test Account
### Test Account
It is strongly recommended to first test with an independent service provider.
#### Fastmail
This demo will start with a free 30-day trial of Fastmail. At the time the demo
was last tested, no payment details were required.
@ -74,6 +75,38 @@ the second drop-down, select "Mail (IMAP/POP/SMTP)". Click "Generate password".
A new password will be displayed. This is the app password that will be used in
the demo script. **Copy the displayed password or write it down.**
#### Gmail
This demo will start with a free Gmail account. At the time the demo was last
tested, no payment details were required.
:::caution pass
A valid phone number (for SMS verification and 2FA) was required.
:::
0) Create a new Gmail email account and verify with a mobile number.
_Create App Password_
1) Click the icon in the top-right corner and click "Manage your Google Account"
2) Click "Security" in the left column
3) Enable 2-Step Verification (if it is not currently enabled)
4) Click "2-Step Verification"
5) Click the right arrow (`>`) next to "App passwords".
6) Type a name ("SheetJS Test") and click "Create".
A new password will be displayed. This is the app password that will be used in
the demo script. **Copy the displayed password or write it down.**
## Operations
### Sending Mail
Many SheetJS users deploy the `nodemailer` module in production.
@ -113,14 +146,14 @@ includes a table showing the file extension required for each supported type.
#### Send Demo
:::note
:::note Tested Deployments
This demo was tested in the following deployments:
| Email Provider | Date | Library | Version |
|:---------------|:-----------|:-------------|:--------|
| `gmail.com` | 2023-06-03 | `nodemailer` | `6.9.3` |
| `fastmail.com` | 2023-06-03 | `nodemailer` | `6.9.3` |
| Email Provider | Date | Library | Version |
|:---------------|:-----------|:-------------|:---------|
| `gmail.com` | 2024-03-11 | `nodemailer` | `6.9.12` |
| `fastmail.com` | 2024-03-11 | `nodemailer` | `6.9.12` |
:::
@ -131,7 +164,7 @@ This demo was tested in the following deployments:
<CodeBlock language="bash">{`\
mkdir sheetjs-send
cd sheetjs-send
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz nodemailer@6.9.3`}
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz nodemailer@6.9.12`}
</CodeBlock>
2) Save the following script to `SheetJSend.js`:
@ -141,6 +174,7 @@ const XLSX = require('xlsx');
const nodemailer = require('nodemailer');
const transporter = nodemailer.createTransport({
// highlight-next-line
service: 'fastmail',
auth: {
// highlight-start
@ -176,6 +210,7 @@ transporter.sendMail(mailOptions, function (err, info) {
3) Edit `SheetJSend.js` and replace the highlighted lines:
- `service: 'fastmail',` the value should be one of the supported providers[^1]
- `user: "**",` the value should be the sender email address
- `pass: "**"` the value should be the app password from earlier
- `from: "**",` the value should be the sender email address
@ -259,13 +294,14 @@ function process_buf(buf, name) {
#### Receive Demo
:::note
:::note Tested Deployments
This demo was tested in the following deployments:
| Email Provider | Date | Library | Version |
|:---------------|:-----------|:-----------|:----------|
| `fastmail.com` | 2023-06-03 | `imapflow` | `1.0.128` |
| `gmail.com` | 2024-03-11 | `imapflow` | `1.0.156` |
| `fastmail.com` | 2024-03-11 | `imapflow` | `1.0.156` |
:::
@ -276,7 +312,7 @@ This demo was tested in the following deployments:
<CodeBlock language="bash">{`\
mkdir sheetjs-recv
cd sheetjs-recv
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz imapflow@1.0.128`}
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz imapflow@1.0.156`}
</CodeBlock>
2) Save the following script to `SheetJSIMAP.js`:
@ -286,7 +322,9 @@ const XLSX = require('xlsx');
const { ImapFlow } = require('imapflow');
const client = new ImapFlow({
host: 'imap.fastmail.com', port: 993, secure: true, logger: false,
// highlight-next-line
host: 'imap.fastmail.com',
port: 993, secure: true, logger: false,
auth: {
// highlight-start
user: '**',
@ -333,6 +371,12 @@ const concat_RS = (stream) => new Promise((res, rej) => {
- `user: "**",` the value should be the account address
- `pass: "**"` the value should be the app password from earlier
- `host: 'imap.fastmail.com',` the value should be the host name:
| Service | `host` value |
|:---------------|:--------------------|
| `gmail.com` | `imap.gmail.com` |
| `fastmail.com` | `imap.fastmail.com` |
4) Download <https://sheetjs.com/pres.numbers>. Using a different account, send
an email to the test account and attach the file. At the end of this step, the
@ -364,3 +408,5 @@ proprietary mail and email account file formats.
### PST
**[The exposition has been moved to a separate page.](/docs/demos/net/email/pst)**
[^1]: The list of services can be found in [`lib/well-known/services.json`](https://github.com/nodemailer/nodemailer/blob/master/lib/well-known/services.json) in the NodeMailer project.

@ -400,7 +400,12 @@ strongly recommended to add verbose logging and to lint scripts before use.
:::note Tested Deployments
This demo was last tested on 2023 September 14 against PhantomJS 2.1.1
This demo was tested in the following environments:
| Architecture | PhantomJS | Date |
|:-------------|:----------|:-----------|
| `darwin-x64` | `2.1.1` | 2024-02-23 |
| `win10-x64` | `2.1.1` | 2024-02-23 |
:::

@ -219,9 +219,9 @@ This demo was tested in the following environments:
| OS | Type | Device | RN | Date |
|:-----------|:-----|:--------------------|:---------|:-----------|
| Android 34 | Sim | Pixel 3a | `0.73.1` | 2023-12-21 |
| Android 34 | Sim | Pixel 3a | `0.73.5` | 2024-03-05 |
| iOS 17.2 | Sim | iPhone 15 Pro Max | `0.73.1` | 2023-12-21 |
| Android 29 | Real | NVIDIA Shield | `0.73.1` | 2023-12-21 |
| Android 29 | Real | NVIDIA Shield | `0.73.5` | 2024-03-05 |
| iOS 15.1 | Real | iPad Pro | `0.73.1` | 2023-12-21 |
:::

@ -190,7 +190,7 @@ This demo was tested in the following environments:
|:---------------|:-------------|:---------|:-----------|
| macOS 13.5.1 | `darwin-x64` | `27.1.3` | 2023-12-09 |
| macOS 14.1.2 | `darwin-arm` | `27.1.3` | 2023-12-01 |
| Windows 10 | `win10-x64` | `27.1.3` | 2023-12-09 |
| Windows 10 | `win10-x64` | `28.2.0` | 2024-03-04 |
| Windows 11 | `win11-arm` | `27.1.3` | 2023-12-01 |
| Linux (HoloOS) | `linux-x64` | `28.2.0` | 2024-01-26 |
| Linux (Debian) | `linux-arm` | `27.1.3` | 2023-12-01 |

@ -115,7 +115,7 @@ This demo was tested in the following environments:
|:---------------|:-------------|:---------|:-----------|
| macOS 13.5.2 | `darwin-x64` | `0.78.1` | 2023-09-27 |
| macOS 14.1.2 | `darwin-arm` | `0.82.0` | 2023-12-01 |
| Windows 10 | `win10-x64` | `0.82.0` | 2023-12-09 |
| Windows 10 | `win10-x64` | `0.83.0` | 2024-03-04 |
| Windows 11 | `win11-arm` | `0.82.0` | 2023-12-01 |
| Linux (HoloOS) | `linux-x64` | `0.83.0` | 2024-01-26 |

@ -299,7 +299,7 @@ This demo was tested in the following environments:
|:---------------|:-------------|:---------|:-----------|
| macOS 13.6 | `darwin-x64` | `v2.6.0` | 2023-11-05 |
| macOS 14.1.2 | `darwin-arm` | `v2.6.0` | 2023-12-01 |
| Windows 10 | `win10-x64` | `v2.6.0` | 2023-12-09 |
| Windows 10 | `win10-x64` | `v2.8.0` | 2024-03-10 |
| Windows 11 | `win11-arm` | `v2.6.0` | 2023-12-01 |
| Linux (HoloOS) | `linux-x64` | `v2.7.1` | 2024-01-22 |
| Linux (Debian) | `linux-arm` | `v2.6.0` | 2023-12-01 |
@ -402,7 +402,7 @@ curl -o frontend/src/App.svelte https://docs.sheetjs.com/wails/App.svelte
wails build
```
At the end, it will print the path to the generated program.
It will print the path to the generated program (typically in `build/bin/`).
6) Run the generated application.

@ -434,7 +434,7 @@ During the last Linux x64 test, the build failed with the error message:
'openssl/opensslv.h' file not found
```
This error was resolved installing OpenSSL. On Arch Linux and HoloOS:
OpenSSL must be installed. On Arch Linux and HoloOS (Steam Deck):
```bash
sudo pacman -S openssl

@ -53,7 +53,7 @@ This demo was tested in the following deployments:
|:-------------|:-------------|:----------|:----------|:-----------|
| `darwin-x64` | `4.0.0-rc.2` | `14.15.3` | Pre-built | 2023-10-10 |
| `darwin-arm` | `4.0.0-rc.2` | `18.18.0` | Compiled | 2023-12-01 |
| `win10-x64` | `4.0.0-rc.2` | `14.15.3` | Pre-built | 2023-10-09 |
| `win10-x64` | `4.0.0-rc.4` | `14.15.3` | Pre-built | 2024-03-04 |
| `win11-arm` | `4.0.0-rc.2` | `20.10.0` | Compiled | 2023-12-01 |
| `linux-x64` | `4.0.0-rc.4` | `14.15.3` | Pre-built | 2024-01-26 |
| `linux-arm` | `4.0.0-rc.2` | `20.10.0` | Compiled | 2023-12-01 |

@ -62,7 +62,7 @@ async function push_first_sheet_to_pouchdb(db, wb, _id_) {
/* get first worksheet */
const ws = wb.Sheets[wb.SheetNames[0]];
/* generate array of arrays */
/* generate array of objects */
const aoo = XLSX.utils.sheet_to_json(ws);
/* if a prefix is specified, add a unique _id to each row based on index */

@ -9,22 +9,22 @@ sidebar_custom_props:
import CodeBlock from '@theme/CodeBlock';
:::warning pass
WebSQL is no longer enabled by default in Chrome. Chrome 123 will officially
remove support. For SQL in the browser, there are a few alternatives:
- [SQL.js](/docs/demos/data/sqlite#browser) is a compiled version of SQLite
- [AlaSQL](/docs/demos/data/alasql) is a pure-JS SQL engine backed by IndexedDB
:::
WebSQL (formally "Web SQL Database") is a popular SQL-based in-browser database
available in Chromium and related browsers including Google Chrome. In practice,
it is powered by SQLite. Many SQLite-compatible queries work as-is in WebSQL.
The public demo <https://sheetjs.com/sql> generates a database from workbook.
:::caution pass
WebSQL is only supported in Chromium-based browsers including Chrome.
Safari historically supported WebSQL but Safari 13 dropped support.
Legacy browsers including Internet Explorer and Firefox never added support.
:::
:::info pass
WebSQL is not commonly available on server-side platforms. Typically scripts
@ -150,14 +150,15 @@ This browser demo was tested in the following environments:
| Browser | Date |
|:------------|:-----------|
| Chrome 119 | 2023-11-30 |
| Chrome 118 | 2024-02-11 |
Some lesser-used browsers do not support WebSQL:
Browsers that do not support WebSQL will throw errors:
| Browser | Date | Support |
|:------------|:-----------|:------------------------------------|
| Safari 17.0 | 2023-10-13 | Error `Web SQL is deprecated` |
| Firefox 118 | 2023-10-13 | Error `openDatabase is not defined` |
| Browser | Date | Error Message |
|:------------|:-----------|:------------------------------|
| Chrome 120 | 2024-02-11 | `openDatabase is not defined` |
| Safari 17.3 | 2024-02-11 | `Web SQL is deprecated` |
| Firefox 118 | 2023-10-13 | `openDatabase is not defined` |
:::

@ -20,11 +20,11 @@ Not all Clipboard APIs offer access to all clipboard types.
Each browser demo was tested in the following environments:
| Browser | Date |
|:------------|:-----------|
| Chrome 119 | 2023-11-30 |
| Safari 16.6 | 2023-09-01 |
| Brave 1.57 | 2023-09-01 |
| Browser | Date | Notes
|:------------|:-----------|:-------------------------|
| Chrome 121 | 2024-02-21 | |
| Safari 17.3 | 2024-02-21 | `text/rtf` not supported |
| Brave 1.59 | 2024-02-21 | |
:::

@ -33,7 +33,7 @@ versions of Photoshop and InDesign:
- ["Unified Extensibility Platform" (UXP)](#uxp): This platform supports modern
JavaScript but has limited support (Photoshop 2021+ and InDesign 2022+)
:::note
:::note Tested Deployments
This demo was verified in the following deployments:
@ -42,7 +42,7 @@ This demo was verified in the following deployments:
| Photoshop | ExtendScript | 2023-09-24 |
| InDesign | ExtendScript | 2023-09-24 |
| InDesign | CEP | 2023-09-24 |
| InDesign | UXP | 2023-09-24 |
| InDesign | UXP | 2024-03-11 |
:::

@ -4,14 +4,6 @@ pagination_prev: demos/cloud/index
pagination_next: demos/bigdata/index
---
:::note pass
This demo showcases Manifest V2 and Manifest V3 extensions. Chrome Web Store
will not accept new V2 extensions, but these can be sideloaded using the
"Load unpacked" extension option in Developer mode.
:::
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
can be integrated in a Chromium extension.
@ -20,9 +12,20 @@ tables with a content script and a background script.
[The demo](#demo) includes unpacked extensions for Manifest V2 and Manifest V3.
:::note
:::note Tested Deployments
This demo was last tested on 2023 October 14 against Chrome 117.
This demo was last tested on 2024 March 11 against Chrome 122.
:::
:::caution pass
This demo showcases Manifest V2 and Manifest V3 extensions.
Chrome Web Store will not accept new V2 extensions, but these can be sideloaded
using the "Load unpacked" extension option in Developer mode.
**New Chrome and Chromium Extensions should use Manifest V3!**
:::

@ -14,23 +14,24 @@ writing Excel files, [other demos](/docs/demos/) cover a wide variety of use cas
:::
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
Office 2016 introduced a JavaScript API for interacting with the application.
It offers solutions for custom functions as well as task panes.
Excel currently does not provide support for working with Apple Numbers files
and some legacy file formats. SheetJS fills the gap.
and some legacy file formats. SheetJS fills the gap.
This demo creates a new custom function `SHEETJS.EXTERN()` which tries to fetch
an external spreadsheet and insert the data into the worksheet.
In the ["Complete Demo"](#complete-demo), we'll create a new custom function
`SHEETJS.EXTERN()` which tries to fetch an external spreadsheet and insert the
data into the worksheet.
![`SHEETJS.EXTERN` output](pathname:///xlapi/xlfetch.png)
This demo focuses on the basic mechanics. Advanced topics like Excel Custom
Function parameters are covered in the official Office JavaScript API docs.
:::note Tested Deployments
:::note
This demo was last tested on 2023 September 03 against Excel 365 (version 2308)
This demo was last tested on 2024 March 04 against Excel 365 (version 2402).
:::
@ -42,10 +43,26 @@ Excel 365 before running the demo.
:::
:::warning Telemetry
The Office Add-in CLI collects telemetry by default. It can be disabled:
```js
npx office-addin-usage-data off
```
The setting can be verified by running:
```js
npx office-addin-usage-data list
```
:::
## Integration Details
The [NodeJS module](/docs/getting-started/installation/nodejs) can be imported
in an Excel Custom Functions project.
The [SheetJS NodeJS module](/docs/getting-started/installation/nodejs) can be
imported from scripts in an Excel Custom Functions project.
The [`sheet_to_json`](/docs/api/utilities#json) helper function can generate
arrays of arrays of values based on the worksheet data. Excel custom functions
@ -62,7 +79,7 @@ var XLSX = require("xlsx");
* @param {string} url URL to fetch and parse
* @returns {any[][]} Worksheet data
*/
async function extern(url) {
export async function extern(url) {
try {
/* Fetch Data */
const res = await fetch(url);
@ -101,7 +118,15 @@ after testing is finished.
1) Install [NodeJS LTS](https://nodejs.org/en/download/).
2) Install dependencies in a new PowerShell window:
2) After installing NodeJS, launch a new PowerShell window.
3) Disable telemetry:
```bash
npx office-addin-usage-data off
```
4) Install dependencies:
```bash
npm i -g yo bower generator-office
@ -109,7 +134,13 @@ npm i -g yo bower generator-office
### Creating a new Add-in
3) Run `yo office` from the command line. It will ask a few questions:
5) Run the generator:
```bash
npx yo office
```
The generator will ask a few questions:
- "Choose a project type": "Excel Custom Functions using a Shared Runtime"
@ -117,7 +148,9 @@ npm i -g yo bower generator-office
- "What do you want to name your add-in?": "SheetJSImport"
4) Start the dev process:
The generator will create the project and install dependencies.
6) Start the development process:
```bash
cd SheetJSImport
@ -125,13 +158,34 @@ npm run build
npm start
```
Running `npm start` will open up a terminal window and a new Excel window with
the loaded add-in. Keep the terminal window open.
If prompted to `Allow localhost loopback for Microsoft Edge WebView`, type "N"
and press Enter.
5) In `manifest.xml` , search for `Functions.NameSpace` . There will be an XML
If prompted to install "Developer CA for Microsoft Office Add-ins" certificate,
select "Yes"
If Windows Firewall prompts to allow Node.js on private networks, select "Yes"
A new terminal window running NodeJS will be created. Keep the window open.
A new Excel window with the loaded add-in will launch.
:::caution pass
In some tests, the taskpane showed an error:
```
Script error.
```
[Webview2](https://developer.microsoft.com/en-us/microsoft-edge/webview2/)
should be installed manually.
:::
7) In `manifest.xml` , search for `Functions.Namespace` . There will be an XML
element with name `bt:String`. Change the `DefaultValue` attribute to `SHEETJS`:
```xml title="manifest.xml"
```xml title="manifest.xml (change highlighted line)"
<bt:ShortStrings>
// highlight-next-line
<bt:String id="Functions.Namespace" DefaultValue="SHEETJS"/>
@ -139,17 +193,23 @@ element with name `bt:String`. Change the `DefaultValue` attribute to `SHEETJS`:
```
6) Close the Excel window and the terminal window, then run `npm start` again.
8) Close the Excel window and the terminal window. Do not save the XLSX file.
9) In the PowerShell window, start the development process again:
```bash
npm start
```
### Integrating the SheetJS Library
7) Install the SheetJS library in the project
10) Install the SheetJS library in the project
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
8) Replace `src\functions\functions.js` with the following:
11) Replace `src\functions\functions.js` with the following:
```js title="src\functions\functions.js"
var XLSX = require("xlsx");
@ -159,15 +219,20 @@ var XLSX = require("xlsx");
* @customfunction
* @returns {string[][]} The SheetJS Library Version.
*/
function version() {
export function version() {
return [[XLSX.version]];
}
```
9) After making the change, save the files. Close the terminal window and the
Excel window (do not save the Excel file). Re-run `npm start`.
12) Close the terminal window and the Excel window. Do not save the Excel file.
10) In the new Excel window, enter the formula `=SHEETJS.VERSION()` in cell
13) In the PowerShell window, start the development process again:
```bash
npm start
```
14) In the new Excel window, enter the formula `=SHEETJS.VERSION()` in cell
`D1`. You should see something similar to the following screenshot:
![`SHEETJS.VERSION` output](pathname:///xlapi/xlvers.png)
@ -176,7 +241,7 @@ This indicates that the SheetJS library has been loaded.
### Fetching Files from the Internet
11) Add the following code snippet to `src\functions\functions.js`:
15) Add the following code snippet to `src\functions\functions.js`:
```js title="src\functions\functions.js (add to end)"
/**
@ -185,7 +250,7 @@ This indicates that the SheetJS library has been loaded.
* @param {string} url URL to fetch and parse
* @returns {any[][]} Worksheet data
*/
async function extern(url) {
export async function extern(url) {
try {
/* Fetch Data */
const res = await fetch(url);
@ -204,12 +269,14 @@ async function extern(url) {
}
```
12) After making the change, save the files. Close the terminal window and the
16) After making the change, save the files. Close the terminal window and the
Excel window (do not save the Excel file). Re-run `npm start`.
13) Enter the text `https://sheetjs.com/pres.numbers` in cell `D1`. Enter the
formula `=SHEETJS.EXTERN(D1)` in cell `D2` and press Enter. Excel should pull
in the data and generate a dynamic array.
17) Enter the text `https://sheetjs.com/pres.numbers` in cell `D1`. Enter the
formula `=SHEETJS.EXTERN(D1)` in cell `D2` and press Enter.
Excel should pull in the data and generate a dynamic array. The worksheet should
match the screenshot at the top of this page.
:::tip pass

@ -27,9 +27,9 @@ remote file, parses the contents, and writes data to the sheet:
![Screenshot of final result](pathname:///gsheet/udf.png)
:::note
:::note Tested Deployments
This demo was last tested on 2023 September 16.
This demo was last tested on 2024 March 11.
:::

@ -9,23 +9,30 @@ import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
Open Scripting Architecture (OSA), a built-in feature in macOS introduced in
1993, enables users to communicate with applications with a standardized
language and grammar. macOS releases starting from Yosemite (OSX 10.10) include
native support for scripting with JavaScript.
Open Scripting Architecture (OSA)[^1] enables macOS app automation with scripts.
OSA originally supported the "AppleScript" language. Modern macOS releases
(OSX 10.10 and later) natively support JavaScript scripts using "JXA"[^2].
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
can be parsed and evaluated from the JS engine. Once evaluated, the `XLSX`
global will be defined. A JS stub can expose methods from AppleScript scripts.
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
:::note
:::note Tested Environments
This demo was last tested on 2023-09-03 in macOS Ventura.
This demo was tested in the following environments:
| macOS | Language | Date |
|:---------|:------------------|:-----------|
| `14.3.1` | AppleScript (OSA) | 2024-02-21 |
| `14.3.1` | JavaScript (JXA) | 2024-02-21 |
:::
## Integration details
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
can be parsed and evaluated from the JS engine. Once evaluated, the `XLSX`
global will be defined. A JS stub can expose methods from AppleScript scripts.
<Tabs groupId="osa">
<TabItem value="js" label="JavaScript">
@ -252,4 +259,7 @@ chmod +x sheetosa.scpt
```
</TabItem>
</Tabs>
</Tabs>
[^1]: See ["Introduction to AppleScript Overview"](https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptX/AppleScriptX.html) in the Apple Developer documentation for more details.
[^2]: See ["Introduction to JavaScript for Automation Release Notes"](https://developer.apple.com/library/archive/releasenotes/InterapplicationCommunication/RN-JavaScriptForAutomation/Articles/Introduction.html) in the Apple Developer documentation for more details.

@ -137,22 +137,23 @@ XLSX.stream.to_json(ws, {raw: true}).pipe(conv).pipe(process.stdout);
**Demo**
:::note
:::note Tested Deployments
This demo was last tested in the following deployments:
This demo was tested in the following deployments:
| Node Version | Date | Node Status when tested |
|:-------------|:-----------|:------------------------|
| `0.12.18` | 2023-09-02 | End-of-Life |
| `4.9.1` | 2023-09-02 | End-of-Life |
| `6.17.1` | 2023-09-02 | End-of-Life |
| `8.17.0` | 2023-09-02 | End-of-Life |
| `10.24.1` | 2023-09-02 | End-of-Life |
| `12.22.12` | 2023-09-02 | End-of-Life |
| `14.21.3` | 2023-09-02 | End-of-Life |
| `16.20.0` | 2023-09-02 | Maintenance LTS |
| `18.17.1` | 2023-09-02 | Active LTS |
| `20.5.1` | 2023-09-02 | Current |
| `0.12.18` | 2024-02-23 | End-of-Life |
| `4.9.1` | 2024-02-23 | End-of-Life |
| `6.17.1` | 2024-02-23 | End-of-Life |
| `8.17.0` | 2024-02-23 | End-of-Life |
| `10.24.1` | 2024-02-23 | End-of-Life |
| `12.22.12` | 2024-02-23 | End-of-Life |
| `14.21.3` | 2024-02-23 | End-of-Life |
| `16.20.2` | 2024-02-23 | End-of-Life |
| `18.19.1` | 2024-02-23 | Maintenance LTS |
| `20.11.1` | 2024-02-23 | Active LTS |
| `21.6.2` | 2024-02-23 | Current |
While streaming methods work in End-of-Life versions of NodeJS, production
deployments should upgrade to a Current or LTS version of NodeJS.
@ -210,9 +211,14 @@ Joseph Biden,46
### Browser
:::note
:::note Tested Deployments
The live demo was last tested on 2023-09-02 in Chromium 116.
Each browser demo was tested in the following environments:
| Browser | Date |
|:------------|:-----------|
| Chrome 121 | 2024-02-23 |
| Safari 17.3 | 2024-02-23 |
:::
@ -441,9 +447,9 @@ const ws = workbook.Sheets[workbook.SheetNames[0]];
stream.to_csv(wb.Sheets[wb.SheetNames[0]]).resume();`}
</CodeBlock>
:::note
:::note Tested Deployments
This demo was last tested on 2023-09-02 against Deno `1.36.4`
This demo was last tested on 2024-02-23 against Deno `1.41.0`.
:::
@ -451,4 +457,11 @@ This demo was last tested on 2023-09-02 against Deno `1.36.4`
example script that downloads <https://sheetjs.com/pres.numbers> and prints
CSV row objects.
1) Run `deno run -A https://docs.sheetjs.com/stream/SheetJSDenoStream.ts`
1) Run the script:
```bash
deno run -A https://docs.sheetjs.com/stream/SheetJSDenoStream.ts
```
This script will fetch [`pres.numbers`](https://sheetjs.com/pres.numbers) and
generate CSV rows. The result will be printed to the terminal window.

@ -184,13 +184,13 @@ const worker = new Worker(
## Live Demos
:::note
:::note Tested Deployments
Each browser demo was tested in the following environments:
| Browser | Date | Comments |
|:------------|:-----------|:----------------------------------------|
| Chrome 116 | 2023-09-02 | |
| Chrome 121 | 2024-02-25 | |
| Edge 116 | 2023-09-02 | |
| Safari 16.6 | 2023-09-02 | File System Access API is not supported |
| Brave 1.57 | 2023-09-02 | File System Access API is not supported |

@ -98,7 +98,7 @@ duk_config_buffer(ctx, -1, buf, len);
duk_put_global_string(ctx, "buf");
/* parse with SheetJS */
duk_eval_string_noresult("workbook = XLSX.read(buf.slice(0, buf.length), {type:'buffer'});");
duk_eval_string_noresult(ctx, "workbook = XLSX.read(buf.slice(0, buf.length), {type:'buffer'});");
```
`workbook` will be a variable in the JS environment that can be inspected using
@ -347,11 +347,57 @@ sequenceDiagram
Bindings exist for many languages. As these bindings require "native" code, they
may not work on every platform.
The Duktape source distribution includes a separate Makefile for building a
shared library. This library can be loaded in other programs.
#### Blingos
Duktape includes a number of "blingos" (function-like macros) which will not be
included in the shared library. The macros must be manually expanded.
For example, `duk_create_heap_default` is defined as follows:
```c
#define duk_create_heap_default() \
duk_create_heap(NULL, NULL, NULL, NULL, NULL)
```
The `duk_create_heap_default` blingo will not be defined in the shared library.
Instead, `duk_create_heap` must be called directly. Using PHP FFI:
```php
/* create new FFI object */
$ffi = FFI::cdef(/* ... arguments */);
/* call duk_create_heap directly */
// highlight-next-line
$context = $ffi->duk_create_heap(null, null, null, null, null);
```
#### Null Pointers
The C `NULL` pointer must be used in some functions. Some FFI implementations
have special values distinct from the language-native null value. Using Python,
return type hints are specified with the `restype` property:
```py
from ctypes import CDLL, c_void_p
duk = CDLL("libduktape.so")
# highlight-next-line
duk.duk_create_heap.restype = c_void_p
context = duk.duk_create_heap(None, None, None, None, None)
```
### PHP
There is no official PHP binding to the Duktape library. Instead, this demo uses
the raw `FFI` interface[^1] to the Duktape shared library.
The [`SheetJSDuk.php`](pathname:///duk/SheetJSDuk.php) demo script parses a
file, prints CSV rows from the first worksheet, and creates a XLSB workbook.
#### PHP Demo
:::note Tested Deployments
@ -361,6 +407,7 @@ This demo was tested in the following deployments:
| Architecture | Version | PHP Version | Date |
|:-------------|:--------|:------------|:-----------|
| `darwin-x64` | `2.7.0` | `8.3.2` | 2024-01-26 |
| `darwin-arm` | `2.7.0` | `8.3.2` | 2024-02-13 |
| `linux-x64` | `2.7.0` | `8.2.7` | 2024-01-29 |
:::
@ -487,6 +534,7 @@ This demo was tested in the following deployments:
| Architecture | Version | Python | Date |
|:-------------|:--------|:---------|:-----------|
| `darwin-x64` | `2.7.0` | `3.11.7` | 2024-01-29 |
| `darwin-arm` | `2.7.0` | `3.11.7` | 2024-02-13 |
| `linux-x64` | `2.7.0` | `3.11.3` | 2024-01-29 |
:::
@ -579,6 +627,302 @@ python3 SheetJSDuk.py pres.numbers
If the program succeeded, the CSV contents will be printed to console and the
file `sheetjsw.xlsb` will be created. That file can be opened with Excel.
### Zig
:::caution Zig support is considered experimental.
Great open source software grows with user tests and reports. Any issues should
be reported to the Zig project for further diagnosis.
:::
#### Zig Compilation
The main Duktape code can be added to the Zig build pipeline.
:::note pass
The following explanation was verified against Zig 0.11.0.
:::
Due to restrictions in the Zig C integration, the path to the Duktape `src`
folder must be added to the include path list:
```zig title="build.zig"
const exe = b.addExecutable(.{
// ...
});
// highlight-start
// this line is required to make @cInclude("duktape.h") work
exe.addIncludePath(.{ .path = "duktape-2.7.0/src" });
// highlight-end
```
The `duktape.c` source file must be added to the build sequence. For Zig version
0.11.0, Duktape must be compiled with flags `-std=c99 -fno-sanitize=undefined`
and linked against `libc` and `libm`:
```zig title="build.zig"
const exe = b.addExecutable(.{
// ...
});
// highlight-start
exe.addCSourceFile(.{:
.file = .{ .path = "duktape-2.7.0/src/duktape.c" },
.flags = &.{ "-std=c99", "-fno-sanitize=undefined" }
});
exe.linkSystemLibrary("c");
exe.linkSystemLibrary("m");
// highlight-end
```
#### Zig Import
`duktape.h` can be imported using the `@cImport` directive:
```zig title="main.zig"
const duktape = @cImport({
@cInclude("duktape.h");
});
```
Once imported, many API functions can be referenced from the `duktape` scope.
For example, `duk_peval_string` in the C interface will be available to Zig code
using the name `duktape.duk_peval_string`.
It is strongly recommended to colocate allocations and cleanup methods using
`defer`. For example, a Duktape context is created with `duk_create_heap` and
destroyed with `duk_destroy_heap`. The latter call can be deferred:
```zig
const ctx = duktape.duk_create_heap(null, null, null, null, null);
defer _ = duktape.duk_destroy_heap(ctx);
```
#### Zig Translator Caveats
The Zig translator does not properly handle blingo `void` casts. For example,
`duk_eval_string_noresult` is a function-like macro defined in `duktape.h`:
```c title="duk_eval_string_noresult blingo"
#define duk_eval_string_noresult(ctx,src) \
((void) duk_eval_raw((ctx), (src), 0, 0 /*args*/ | DUK_COMPILE_EVAL | DUK_COMPILE_NOSOURCE | DUK_COMPILE_STRLEN | DUK_COMPILE_NORESULT | DUK_COMPILE_NOFILENAME))
```
The compiler will throw an error involving `anyopaque` (C `void`):
```
error: opaque return type 'anyopaque' not allowed
```
The blingo performs a `void` cast to suppress certain C compiler warnings. The
spiritual equivalent in Zig is to assign to `_`.
The `duk_eval_raw` method and each compile-time constant are available in the
`duktape` scope. A manual translation is shown below:
```zig
_ = duktape.duk_eval_raw(ctx, src, 0, 0 | duktape.DUK_COMPILE_EVAL | duktape.DUK_COMPILE_NOSOURCE | duktape.DUK_COMPILE_STRLEN | duktape.DUK_COMPILE_NORESULT | duktape.DUK_COMPILE_NOFILENAME);
```
#### Zig Demo
:::note Tested Deployments
This demo was tested in the following deployments:
| Architecture | Version | Zig | Date |
|:-------------|:--------|:---------|:-----------|
| `darwin-x64` | `2.7.0` | `0.11.0` | 2024-03-10 |
| `win10-x64` | `2.7.0` | `0.11.0` | 2024-03-10 |
| `linux-x64` | `2.7.0` | `0.11.0` | 2024-03-10 |
On Windows, due to incompatibilities between WSL and PowerShell, some commands
must be run in WSL Bash.
:::
0) Create a new project folder:
```bash
mkdir sheetjs-zig
cd sheetjs-zig
```
1) Download Zig 0.11.0 from <https://ziglang.org/download/> and extract to the
project folder.
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="MacOS">
```bash
curl -LO https://ziglang.org/download/0.11.0/zig-macos-x86_64-0.11.0.tar.xz
tar -xzf zig-macos-x86_64-0.11.0.tar.xz
```
</TabItem>
<TabItem value="linux-x64" label="Linux">
```bash
curl -LO https://ziglang.org/download/0.11.0/zig-linux-x86_64-0.11.0.tar.xz
xz -d zig-linux-x86_64-0.11.0.tar.xz
tar -xf zig-linux-x86_64-0.11.0.tar
```
</TabItem>
<TabItem value="win10-x64" label="Windows">
:::note pass
The following commands should be run within WSL bash.
:::
```bash
curl -LO https://ziglang.org/download/0.11.0/zig-windows-x86_64-0.11.0.zip
unzip zig-windows-x86_64-0.11.0.zip
```
</TabItem>
</Tabs>
2) Initialize a project:
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="MacOS">
```bash
./zig-macos-x86_64-0.11.0/zig init-exe
```
</TabItem>
<TabItem value="linux-x64" label="Linux">
```bash
./zig-linux-x86_64-0.11.0/zig init-exe
```
</TabItem>
<TabItem value="win10-x64" label="Windows">
:::note pass
The following command should be run within Powershell.
:::
```bash
.\zig-windows-x86_64-0.11.0\zig.exe init-exe
```
</TabItem>
</Tabs>
3) Download the Duktape source and extract in the current directory. On Windows,
the commands should be run within WSL:
```bash
curl -LO https://duktape.org/duktape-2.7.0.tar.xz
tar -xJf duktape-2.7.0.tar.xz
```
4) Download the SheetJS Standalone script, shim script and test file. Move all
three files to the `src` subdirectory:
<ul>
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js`}>shim.min.js</a></li>
<li><a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>xlsx.full.min.js</a></li>
<li><a href="https://sheetjs.com/pres.numbers">pres.numbers</a></li>
</ul>
The following commands can be run within a shell on macOS and Linux. On Windows,
the commands should be run within WSL bash:
<CodeBlock language="bash">{`\
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/shim.min.js
curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://sheetjs.com/pres.numbers
mv *.js src`}
</CodeBlock>
5) Add the highlighted lines to `build.zig` just after the `exe` definition:
```zig title="build.zig (add highlighted lines)"
const exe = b.addExecutable(.{
.name = "sheetjs-zig",
// In this case the main source file is merely a path, however, in more
// complicated build scripts, this could be a generated file.
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
// highlight-start
exe.addCSourceFile(.{ .file = .{ .path = "duktape-2.7.0/src/duktape.c" }, .flags = &.{ "-std=c99", "-fno-sanitize=undefined" } });
exe.addIncludePath(.{ .path = "duktape-2.7.0/src" });
exe.linkSystemLibrary("c");
exe.linkSystemLibrary("m");
// highlight-end
```
6) Download [`main.zig`](pathname:///duk/main.zig) and replace `src/main.zig`.
The following command should be run in WSL bash or the macOS or Linux terminal:
```bash
curl -L -o src/main.zig https://docs.sheetjs.com/duk/main.zig
```
7) Build and run the program:
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="MacOS">
```bash
./zig-macos-x86_64-0.11.0/zig build run -- pres.numbers
```
</TabItem>
<TabItem value="linux-x64" label="Linux">
```bash
./zig-linux-x86_64-0.11.0/zig build run -- pres.numbers
```
:::caution pass
On Arch Linux and HoloOS (Steam Deck), compilation may fail:
```
zig build-exe sheetjs-zig Debug native: error: error: unable to create compilation: LibCStdLibHeaderNotFound
```
`glibc` and `linux-api-headers` must be installed:
```bash
sudo pacman -Syu glibc linux-api-headers
```
:::
</TabItem>
<TabItem value="win10-x64" label="Windows">
```bash
.\zig-windows-x86_64-0.11.0\zig.exe build run -- pres.numbers
```
</TabItem>
</Tabs>
This step builds and runs the program. The generated program will be placed in
the `zig-out/bin/` subdirectory.
It should display some metadata along with CSV rows from the first worksheet.
It will also generate `sheetjs.zig.xlsx`, which can be opened with a spreadsheet
editor such as Excel.
### Perl
The Perl binding for Duktape is available as `JavaScript::Duktape::XS` on CPAN.
@ -594,6 +938,7 @@ This demo was tested in the following deployments:
| Architecture | Version | Date |
|:-------------|:--------|:-----------|
| `darwin-x64` | `2.2.0` | 2024-01-26 |
| `darwin-arm` | `2.2.0` | 2024-02-13 |
| `linux-x64` | `2.2.0` | 2024-01-26 |
:::
@ -616,42 +961,10 @@ sudo cpan install JavaScript::Duktape::XS
:::
2) Save the following codeblock to `SheetJSDuk.pl`:
2) Download [`SheetJSDuk.pl`](pathname:///duk/SheetJSDuk.pl):
```perl title="SheetJSDuk.pl"
# usage: perl SheetJSDuk.pl path/to/file
use JavaScript::Duktape::XS;
use File::Slurp;
use MIME::Base64 qw( encode_base64 decode_base64 );
# Initialize
my $js = JavaScript::Duktape::XS->new({ max_memory_bytes => 256 * 1024 * 1024 });
$js->eval("var global = (function(){ return this; }).call(null);");
# Load the ExtendScript build
my $src = read_file('xlsx.extendscript.js', { binmode => ':raw' });
$src =~ s/^\xEF\xBB\xBF//;
my $XLSX = $js->eval($src);
# Print version number
$js->set('log' => sub { print $_[0], "\n"; });
$js->eval("log('SheetJS library version ' + XLSX.version);");
# Parse File
my $raw_data = encode_base64(read_file($ARGV[0], { binmode => ':raw' }), "");
$js->set("b64", $raw_data);
$js->eval(qq{
global.wb = XLSX.read(b64, {type: "base64", WTF:1});
global.ws = wb.Sheets[wb.SheetNames[0]];
void 0;
});
# Print first worksheet CSV
$js->eval('log(XLSX.utils.sheet_to_csv(global.ws))');
# Write XLSB file
my $xlsb = $js->eval("XLSX.write(global.wb, {type:'base64', bookType:'xlsb'})");
write_file("SheetJSDuk.xlsb", decode_base64($xlsb));
```bash
curl -LO https://docs.sheetjs.com/duk/SheetJSDuk.pl
```
3) Download the SheetJS ExtendScript build and test file:

@ -127,14 +127,14 @@ try? out.write(to: out_path, atomically: false, encoding: String.Encoding.isoLat
## Complete Example
:::note
:::note pass
This demo was tested in the following environments:
| Architecture | Swift | Date |
|:-------------|:--------|:-----------|
| `darwin-x64` | `5.9.0` | 2023-10-26 |
| `darwin-arm` | `5.9.0` | 2023-10-18 |
| `darwin-x64` | `5.9.2` | 2024-02-21 |
| `darwin-arm` | `5.9.2` | 2024-02-21 |
:::

@ -165,7 +165,7 @@ This demo was tested in the following deployments:
|:-------------|:------------------|:-----------|
| `darwin-x64` | `3.0.0` | 2024-01-22 |
| `darwin-arm` | `3.0.0-beta-2056` | 2023-12-01 |
| `win10-x64` | `3.0.0-beta-2053` | 2023-10-28 |
| `win10-x64` | `3.0.0` | 2024-03-04 |
| `win11-arm` | `3.0.0-beta-2056` | 2023-12-01 |
| `linux-x64` | `3.0.0` | 2024-01-22 |
| `linux-arm` | `3.0.0-beta-2056` | 2023-12-01 |

@ -115,7 +115,7 @@ This demo was tested in the following deployments:
| 14.0.2 | Built-in | 2023-12-01 |
| 13.0.14 | Built-in | 2023-12-01 |
| 12.0.2 | Built-in | 2023-12-01 |
| 11.0.20 | Built-in | 2023-12-01 |
| 11.0.20 | Built-in | 2024-02-13 |
| 10.0.2 | Built-in | 2023-12-01 |
| 9 | Built-in | 2023-12-01 |
| 1.8.0 | Built-in | 2023-12-01 |

@ -264,7 +264,7 @@ This demo was tested in the following deployments:
|:-------------|:-----------|:-----------|
| `darwin-x64` | `daa35bc` | 2023-12-09 |
| `darwin-arm` | `2788d71` | 2023-10-18 |
| `win10-x64` | `daa35bc` | 2023-12-09 |
| `win10-x64` | `9e561d5` | 2024-03-04 |
| `win11-arm` | `03cc5ec` | 2023-12-01 |
| `linux-x64` | `9e561d5` | 2024-01-22 |
| `linux-arm` | `03cc5ec` | 2023-12-01 |
@ -342,7 +342,7 @@ This demo was tested in the following environments:
| Git Commit | Date |
|:-----------|:-----------|
| `9e561d5` | 2024-01-22 |
| `9e561d5` | 2024-03-04 |
When the demo was tested, commit `9e561d5` corresponded to the latest release.

@ -72,7 +72,7 @@ This demo was tested in the following deployments:
|:-------------|:---------|:--------|:-----------|
| `darwin-x64` | `2.6.10` | `2.9.1` | 2023-11-14 |
| `darwin-arm` | `2.6.10` | `2.9.1` | 2023-12-01 |
| `win10-x64` | `3.2.2` | `2.9.1` | 2023-10-28 |
| `win10-x64` | `3.2.3` | `2.9.1` | 2024-03-10 |
| `win11-arm` | `3.0.2` | `2.9.1` | 2023-12-01 |
| `linux-x64` | `3.0.5` | `2.9.1` | 2024-01-26 |
| `linux-arm` | `2.7.4` | `2.9.1` | 2023-12-01 |
@ -97,7 +97,14 @@ sudo gem install execjs
:::
1) Download the SheetJS Standalone script and the test file. Save both files in
1) Create a new project folder:
```bash
mkdir sheetjs-rb
cd sheetjs-rb
```
2) Download the SheetJS Standalone script and the test file. Save both files in
the project directory:
<ul>
@ -110,13 +117,13 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js
curl -LO https://sheetjs.com/pres.numbers`}
</CodeBlock>
2) Download [`ExecSheetJS.rb`](pathname:///execjs/ExecSheetJS.rb):
3) Download [`ExecSheetJS.rb`](pathname:///execjs/ExecSheetJS.rb):
```bash
curl -LO https://docs.sheetjs.com/execjs/ExecSheetJS.rb
```
3) Run the demo:
4) Run the demo:
```bash
ruby ExecSheetJS.rb pres.numbers

@ -134,7 +134,7 @@ This demo was tested in the following deployments:
|:-------------|:-----------|:-----------|
| `darwin-x64` | `c3ead3f` | 2023-11-04 |
| `darwin-arm` | `c3ead3f` | 2023-10-19 |
| `win10-x64` | `c3ead3f` | 2023-10-28 |
| `win10-x64` | `c3ead3f` | 2024-03-04 |
| `linux-x64` | `c3ead3f` | 2024-01-26 |
:::
@ -167,7 +167,9 @@ sudo pacman -S cmake clang
</TabItem>
<TabItem value="win10-x64" label="Windows">
Install Visual Studio 2022 with the "Desktop Development with C++" workflow.
Install Visual Studio 2022 with the "Desktop Development with C++" workflow and
the "Git for Windows" individual component.
All commands in this demo should be run in a "Native Tools Command Prompt".
</TabItem>
@ -281,6 +283,37 @@ msbuild /m /p:Platform=x64 /p:Configuration=Debug /p:RuntimeLib=static_library B
cd ..
```
:::caution pass
During some test runs, the build failed with a message referencing `cfguard.h`:
```
44>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\include\cfguard.h(44,1): error C2220: the following warning is treated as an error
(compiling source file 'ThreadContextInfo.cpp')
44>C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.39.33519\include\cfguard.h(44,1): warning C4005: '_GUARD_CHECK_ICALL': macro redefinition
```
The source file `lib\Runtime\Base\ThreadContextInfo.cpp` must be patched. The
highlighted lines must be commented:
```cpp title="lib\Runtime\Base\ThreadContextInfo.cpp (comment highlighted lines)"
#if defined(_UCRT) && _CONTROL_FLOW_GUARD
// highlight-start
//# if _MSC_VER >= 1913
//# include <cfguard.h>
//# else
// highlight-end
extern "C" void __fastcall _guard_check_icall(_In_ uintptr_t _Target);
// highlight-next-line
//# endif
#endif
```
:::
After building, the generated DLL should be copied into the project folder:
```

@ -122,7 +122,7 @@ This demo was tested in the following deployments:
|:-------------|:-----------|
| `darwin-x64` | 2023-11-03 |
| `darwin-arm` | 2023-10-20 |
| `win10-x64` | 2023-10-28 |
| `win10-x64` | 2024-03-04 |
| `win11-arm` | 2023-12-01 |
| `linux-x64` | 2024-01-26 |
| `linux-arm` | 2023-12-01 |

@ -102,7 +102,7 @@ write_file("SheetJE.fods", $fods);
:::note Tested Deployments
This demo was tested on 2023-12-05 against JE 0.066
This demo was tested on 2024-02-13 against JE 0.066
:::

@ -109,7 +109,7 @@ Duktape is an embeddable JS engine written in C. It has been ported to a number
of exotic architectures and operating systems.
This demo has been moved [to a dedicated page](/docs/demos/engines/duktape).
The demo includes examples in C and Perl.
The demo includes examples in C, Perl, PHP, Python and Zig.
#### Goja

@ -369,4 +369,4 @@ the `w` text if available. When programmatically changing values, the `w` text
should be deleted before attempting to export. Utilities will regenerate the `w`
text from the number format (`cell.z`) and the raw value if possible.
[^1]: On 2023 November 04, [the "Review guidelines for customizing a number format" page](https://support.microsoft.com/en-us/office/review-guidelines-for-customizing-a-number-format-c0a1d1fa-d3f4-4018-96b7-9c9354dd99f5) in the Excel documentation covered custom number format minutiae.
[^1]: The ["Review guidelines for customizing a number format"](https://support.microsoft.com/en-us/office/review-guidelines-for-customizing-a-number-format-c0a1d1fa-d3f4-4018-96b7-9c9354dd99f5) page in the Excel documentation covered custom number format minutiae.

@ -154,8 +154,8 @@ Plain text format guessing follows the priority order:
| HTML | starts with `<` and HTML tags appear in the first 1024 characters * |
| XML | starts with `<` and the first tag is valid |
| RTF | starts with `{\rt` |
| DSV | starts with `/sep=.$/`, separator is the specified character |
| DSV | more unquoted `|` chars than `;` `\t` `,` in the first 1024 |
| DSV | starts with `sep=` followed by field delimiter and line separator |
| DSV | more unquoted `\|` chars than `;` `\t` or `,` in the first 1024 |
| DSV | more unquoted `;` chars than `\t` or `,` in the first 1024 |
| TSV | more unquoted `\t` chars than `,` chars in the first 1024 |
| CSV | one of the first 1024 characters is a comma `","` |

@ -43,7 +43,7 @@ These instructions were tested on the following platforms:
| Linux (Ubuntu 18 AArch64) | `linux-arm` | 2023-12-01 |
| MacOS 10.13.6 (x64) | `darwin-x64` | 2023-09-30 |
| MacOS 14.1.2 (ARM64) | `darwin-arm` | 2023-12-01 |
| Windows 10 (x64) + WSL Ubuntu | `win10-x64` | 2023-11-27 |
| Windows 10 (x64) + WSL Ubuntu | `win10-x64` | 2024-03-04 |
| Windows 11 (x64) + WSL Ubuntu | `win11-x64` | 2023-10-14 |
| Windows 11 (ARM) + WSL Ubuntu | `win11-arm` | 2023-09-18 |

@ -146,7 +146,7 @@ const config = {
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme,
additionalLanguages: [ "visual-basic", "swift", "java", "php", "csharp", "perl", "ruby", "cpp", "applescript", "liquid", "rust", "dart", "wolfram", "matlab", "stata" ],
additionalLanguages: [ "visual-basic", "swift", "java", "php", "csharp", "perl", "ruby", "cpp", "applescript", "liquid", "rust", "dart", "wolfram", "matlab", "stata", "zig" ],
},
liveCodeBlock: {
playgroundPosition: 'top'

67
docz/static/duk/main.zig Normal file

@ -0,0 +1,67 @@
const std = @import("std");
const duktape = @cImport({
@cInclude("duktape.h");
});
// SheetJS scripts embedded at comptime
const shim = @embedFile("shim.min.js");
const xlsx = @embedFile("xlsx.full.min.js");
pub fn main() !void {
// initialize duktape
const ctx = duktape.duk_create_heap(null, null, null, null, null);
defer _ = duktape.duk_destroy_heap(ctx);
// load SheetJS scripts
_ = duktape.duk_peval_string(ctx, shim);
_ = duktape.duk_peval_string(ctx, xlsx);
// display version number
_ = duktape.duk_peval_string(ctx, "XLSX.version");
const sum = duktape.duk_get_string(ctx, -1);
std.debug.print("SheetJS Version {s}\n", .{sum});
duktape.duk_pop(ctx);
// create allocator
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
var alloc = gpa.allocator();
// determine file to read
var args = try std.process.argsWithAllocator(alloc);
defer args.deinit();
_ = args.next();
const path = args.next();
if (path == null) {
std.debug.print("Must specify a filename!", .{});
return;
}
std.debug.print("Reading from {s}\n", .{path.?});
// read file
var file = try std.fs.cwd().readFileAlloc(alloc, path.?, std.math.maxInt(usize));
defer alloc.free(file);
std.debug.print("Size: {} bytes\n", .{file.len});
// load into duktape
_ = duktape.duk_push_buffer_raw(ctx, 0, duktape.DUK_BUF_FLAG_DYNAMIC | duktape.DUK_BUF_FLAG_EXTERNAL);
duktape.duk_config_buffer(ctx, -1, file.ptr, file.len);
_ = duktape.duk_put_global_string(ctx, "buf");
_ = duktape.duk_eval_raw(ctx, "workbook = XLSX.read(buf.slice(0, buf.length), {type:'buffer'});", 0, duktape.DUK_COMPILE_EVAL | duktape.DUK_COMPILE_NOSOURCE | duktape.DUK_COMPILE_STRLEN | duktape.DUK_COMPILE_NORESULT | duktape.DUK_COMPILE_NOFILENAME);
// display CSV of first worksheet
_ = duktape.duk_peval_string(ctx, "XLSX.utils.sheet_to_csv(workbook.Sheets[workbook.SheetNames[0]])");
const csv = duktape.duk_get_string(ctx, -1);
std.debug.print("{s}\n", .{csv});
duktape.duk_pop(ctx);
// convert to XLSX
_ = duktape.duk_eval_raw(ctx, "XLSX.write(workbook, {type:'array', bookType:'xlsx'})", 0, duktape.DUK_COMPILE_EVAL | duktape.DUK_COMPILE_NOSOURCE | duktape.DUK_COMPILE_STRLEN | duktape.DUK_COMPILE_NOFILENAME);
var sz: usize = 0;
var c_ptr: *anyopaque = duktape.duk_get_buffer_data(ctx, -1, &sz).?;
// generate zig slice from C pointer + length
var slc: []u8 = @as([*]u8, @ptrCast(c_ptr))[0..sz];
// write to file
_ = try std.fs.cwd().writeFile("sheetjs.zig.xlsx", slc);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB