forked from sheetjs/docs.sheetjs.com
		
	refresh
This commit is contained in:
		
							parent
							
								
									17d9d3d7cf
								
							
						
					
					
						commit
						2450d115db
					
				| @ -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. | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| 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: | ||||
| 
 | ||||
|  | ||||
| @ -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: | ||||
| 
 | ||||
|  | ||||
| 
 | ||||
| :::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' | ||||
|  | ||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										67
									
								
								docz/static/duk/main.zig
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										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 | 
		Loading…
	
		Reference in New Issue
	
	Block a user