From 84b839627e133b2c2b14f354e9e12ea505319ce4 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Sun, 5 Jan 2025 21:51:20 -0500 Subject: [PATCH] demo refresh --- .spelling | 1 - docz/data/mobile.xls | 4 +- .../01-installation/07-bun.md | 8 +- .../02-examples/04-import.md | 5 +- docz/docs/03-demos/01-math/09-danfojs.md | 31 ++- docz/docs/03-demos/01-math/21-pandas.md | 8 +- docz/docs/03-demos/02-frontend/02-react.md | 2 +- docz/docs/03-demos/02-frontend/03-angular.md | 24 ++- docz/docs/03-demos/02-frontend/04-vue.md | 6 +- docz/docs/03-demos/02-frontend/10-openui5.md | 103 +++++++-- .../02-frontend/19-bundler/05-webpack.md | 15 +- .../02-frontend/19-bundler/12-systemjs.md | 12 +- .../02-frontend/19-bundler/14-rollup.md | 8 +- .../02-frontend/19-bundler/20-parcel.md | 4 +- .../03-demos/03-net/03-server/01-express.md | 16 +- .../03-demos/03-net/03-server/11-nestjs.md | 29 ++- .../03-demos/03-net/03-server/19-fastify.md | 9 +- docz/docs/03-demos/03-net/04-email/11-pst.md | 8 +- docz/docs/03-demos/03-net/04-email/index.md | 72 ++----- .../docs/03-demos/03-net/08-headless/index.md | 194 ++++++++--------- docz/docs/03-demos/04-grid/01-xs.md | 7 +- docz/docs/03-demos/04-grid/02-cdg.md | 7 +- docz/docs/03-demos/12-static/01-lume.md | 14 +- docz/docs/03-demos/12-static/02-gatsbyjs.md | 38 ++-- docz/docs/03-demos/12-static/06-webpack.md | 6 +- docz/docs/03-demos/12-static/07-eleventy.md | 14 +- .../docs/03-demos/17-mobile/01-reactnative.md | 50 +++-- .../03-demos/17-mobile/02-nativescript.md | 1 + docz/docs/03-demos/17-mobile/05-capacitor.md | 1 + docz/docs/03-demos/19-desktop/01-electron.md | 9 +- docz/docs/03-demos/19-desktop/02-nwjs.md | 3 +- docz/docs/03-demos/19-desktop/03-wails.md | 6 +- docz/docs/03-demos/19-desktop/04-tauri.md | 20 +- .../docs/03-demos/19-desktop/05-neutralino.md | 10 +- docz/docs/03-demos/20-cli/03-nexe.md | 2 +- docz/docs/03-demos/20-cli/05-pkg.md | 2 +- docz/docs/03-demos/20-cli/08-boxednode.md | 2 +- docz/docs/03-demos/20-cli/11-nodesea.md | 2 +- docz/docs/03-demos/20-cli/13-denosea.md | 2 +- docz/docs/03-demos/23-data/16-postgresql.md | 195 +++++++++--------- docz/docs/03-demos/23-data/25-mongodb.md | 75 ++++++- docz/docs/03-demos/27-local/03-storageapi.md | 53 ++++- docz/docs/03-demos/27-local/09-indexeddb.md | 13 +- docz/docs/03-demos/30-cloud/01-salesforce.md | 6 +- docz/docs/03-demos/30-cloud/21-gsheet.md | 9 +- .../03-demos/32-extensions/01-extendscript.md | 110 ++++++---- .../03-demos/32-extensions/02-chromium.md | 14 +- .../03-demos/32-extensions/03-excelapi.md | 47 ++++- docz/docs/03-demos/32-extensions/04-gsheet.md | 127 +++++++++--- docz/docs/03-demos/32-extensions/12-maple.md | 13 +- docz/docs/03-demos/37-bigdata/02-worker.md | 10 +- docz/docs/03-demos/42-engines/01-duktape.md | 43 ++-- docz/docs/03-demos/42-engines/02-v8.md | 6 +- docz/docs/03-demos/42-engines/06-goja.md | 2 +- docz/docs/03-demos/42-engines/09-hermes.md | 34 ++- docz/docs/03-demos/42-engines/15-rb.md | 2 +- docz/docs/03-demos/42-engines/21-boa.md | 2 +- .../03-demos/42-engines/23-jerryscript.md | 2 +- docz/docs/index.md | 2 +- docz/static/cli/xlsx-cli.js | 158 +++++++------- docz/static/electron/package.json | 12 +- docz/static/extendscript/parse.idjs | 1 + docz/static/extendscript/psauthor.png | Bin 0 -> 24062 bytes .../{files => extendscript}/psparse.png | Bin .../{files => extendscript}/pswrite.png | Bin docz/static/extendscript/write.idjs | 1 + docz/static/gsheet/aoa-udf.png | Bin 0 -> 15286 bytes docz/static/gsheet/apps-script.png | Bin 0 -> 65852 bytes docz/static/gsheet/clasp-perms.png | Bin 0 -> 85266 bytes docz/static/gsheet/clasp-signin.png | Bin 0 -> 128304 bytes docz/static/gsheet/xlsx-full-min-gs.png | Bin 0 -> 44406 bytes docz/static/hermes/Makefile | 4 +- docz/static/nativescript/and.png | Bin 62758 -> 58569 bytes docz/static/nativescript/step4.png | Bin 18311 -> 23145 bytes docz/static/nativescript/step5.png | Bin 28565 -> 34187 bytes docz/static/nativescript/step6.png | Bin 33850 -> 40890 bytes docz/static/tauri/linux.png | Bin 212358 -> 49078 bytes docz/static/tauri/macos.png | Bin 153454 -> 129290 bytes docz/static/wails/linux.png | Bin 170896 -> 44547 bytes docz/static/wails/macos.png | Bin 148740 -> 140388 bytes docz/static/xlapi/xlvers.png | Bin 3268 -> 19159 bytes docz/static/xspreadsheet/index.html | 2 +- tests/bundler-parcel.sh | 7 +- tests/data-postgres.sh | 33 +++ tests/static-eleventy.sh | 22 ++ 85 files changed, 1113 insertions(+), 647 deletions(-) create mode 100644 docz/static/extendscript/psauthor.png rename docz/static/{files => extendscript}/psparse.png (100%) rename docz/static/{files => extendscript}/pswrite.png (100%) create mode 100644 docz/static/gsheet/aoa-udf.png create mode 100644 docz/static/gsheet/apps-script.png create mode 100644 docz/static/gsheet/clasp-perms.png create mode 100644 docz/static/gsheet/clasp-signin.png create mode 100644 docz/static/gsheet/xlsx-full-min-gs.png create mode 100644 tests/data-postgres.sh create mode 100755 tests/static-eleventy.sh diff --git a/.spelling b/.spelling index 401cc04..8157d25 100644 --- a/.spelling +++ b/.spelling @@ -190,7 +190,6 @@ ExecJS ExpressJS ExtendScript FastifyJS -Fastmail FerretDB FileReader FileReaderSync diff --git a/docz/data/mobile.xls b/docz/data/mobile.xls index a2b2635..ef09aac 100644 --- a/docz/data/mobile.xls +++ b/docz/data/mobile.xls @@ -79,7 +79,7 @@ - + CapacitorJS @@ -90,7 +90,7 @@ - + Ionic diff --git a/docz/docs/02-getting-started/01-installation/07-bun.md b/docz/docs/02-getting-started/01-installation/07-bun.md index 467918d..8ace4aa 100644 --- a/docz/docs/02-getting-started/01-installation/07-bun.md +++ b/docz/docs/02-getting-started/01-installation/07-bun.md @@ -123,7 +123,7 @@ This demo was last tested in the following deployments: |:-------------|:---------|:-----------| | `darwin-x64` | `1.1.39` | 2024-12-17 | | `darwin-arm` | `1.1.10` | 2024-09-22 | -| `win11-x64` | `1.1.22` | 2024-08-11 | +| `win11-x64` | `1.1.42` | 2024-12-22 | | `win11-arm` | `1.1.40` | 2024-12-19 | | `linux-x64` | `1.1.40` | 2024-12-19 | | `linux-arm` | `1.1.40` | 2024-12-19 | @@ -146,11 +146,11 @@ The PowerShell file redirect will use the `UTF-16 LE` encoding. Bun does not support the encoding and will fail to install the package: ``` -bun add v1.1.22-canary.96 (df33f2b2) -1 | ��{} - +bun add v1.1.42 (50eec002) +1 | �� ^ error: Unexpected �� + at ���������������������������������������������:1:1 ``` The file must be resaved in UTF8 (without BOM) or ASCII. diff --git a/docz/docs/02-getting-started/02-examples/04-import.md b/docz/docs/02-getting-started/02-examples/04-import.md index 82b723e..41945de 100644 --- a/docz/docs/02-getting-started/02-examples/04-import.md +++ b/docz/docs/02-getting-started/02-examples/04-import.md @@ -489,8 +489,9 @@ function SheetJSAoAFilled() { ### Select Data Rows At this point, each data row will have the year in column `A` and dollar value -in column `C`. The year will be between 2007 and 2024 and the value will be -positive. The following function tests a data row: +in column `C`. The year (first value in the row) will be between 2007 and 2024. +The value (third value) will be positive. The following function tests a row +against the requirements: ```js const is_valid_row = r => diff --git a/docz/docs/03-demos/01-math/09-danfojs.md b/docz/docs/03-demos/01-math/09-danfojs.md index 27a4b9e..a3dbf2b 100644 --- a/docz/docs/03-demos/01-math/09-danfojs.md +++ b/docz/docs/03-demos/01-math/09-danfojs.md @@ -19,7 +19,12 @@ This demo covers details elided in the official DanfoJS documentation. :::note Tested Deployments -This example was last tested on 2024 April 25 against DanfoJS 1.1.2. +This demo was tested in the following deployments: + +| Platform | Version | Date | +|:------------|:--------|:-----------| +| Chrome 131 | `1.1.2` | 2025-01-01 | +| Safari 18.2 | `1.1.2` | 2025-01-01 | ::: @@ -207,15 +212,23 @@ The following example exports a sample dataframe to a XLSX spreadsheet. ```jsx live function DanfoToExcel() { - if(typeof dfd === "undefined") return (RELOAD THIS PAGE); /* sample dataframe */ - const df = new dfd.DataFrame([{Sheet:1,JS:2},{Sheet:3,JS:4}]); - return ( <>
{"Data:\n"+df.head()}
); + const [df, setDF] = React.useState({}); + React.useEffect(() => { + /* sample dataframe */ + setDF(new dfd.DataFrame([{Sheet:1,JS:2},{Sheet:3,JS:4}])); + }, []); + + if(!df.head) return ; + return !df.head ? ( RELOAD THIS PAGE) : ( <> + +
{"Data:\n"+df.head()}
+ ); } ``` diff --git a/docz/docs/03-demos/01-math/21-pandas.md b/docz/docs/03-demos/01-math/21-pandas.md index 8b15814..2d8151c 100644 --- a/docz/docs/03-demos/01-math/21-pandas.md +++ b/docz/docs/03-demos/01-math/21-pandas.md @@ -40,11 +40,11 @@ This demo was tested in the following deployments: | Architecture | JS Engine | Pandas | Python | Date | |:-------------|:----------------|:-------|:-------|:-----------| -| `darwin-x64` | Duktape `2.7.0` | 2.2.1 | 3.12.2 | 2024-03-15 | +| `darwin-x64` | Duktape `2.7.0` | 2.2.3 | 3.13.1 | 2024-12-31 | | `darwin-arm` | Duktape `2.7.0` | 2.2.2 | 3.12.3 | 2024-06-30 | | `win11-x64` | Duktape `2.7.0` | 2.2.3 | 3.11.8 | 2024-12-21 | | `win11-arm` | Duktape `2.7.0` | 2.2.2 | 3.11.5 | 2024-06-20 | -| `linux-x64` | Duktape `2.7.0` | 1.5.3 | 3.11.3 | 2024-03-21 | +| `linux-x64` | Duktape `2.7.0` | 1.5.3 | 3.11.7 | 2025-01-01 | | `linux-arm` | Duktape `2.7.0` | 1.5.3 | 3.11.2 | 2024-06-20 | ::: @@ -519,11 +519,11 @@ This demo was tested in the following deployments: | Architecture | JS Engine | Polars | Python | Date | |:-------------|:----------------|:--------|:-------|:-----------| -| `darwin-x64` | Duktape `2.7.0` | 0.20.15 | 3.12.2 | 2024-03-15 | +| `darwin-x64` | Duktape `2.7.0` | 1.18.0 | 3.13.1 | 2024-12-31 | | `darwin-arm` | Duktape `2.7.0` | 0.20.31 | 3.12.3 | 2024-06-30 | | `win11-x64` | Duktape `2.7.0` | 1.17.1 | 3.11.8 | 2024-12-21 | | `win11-arm` | Duktape `2.7.0` | 0.20.31 | 3.11.5 | 2024-06-20 | -| `linux-x64` | Duktape `2.7.0` | 0.20.16 | 3.11.3 | 2024-03-21 | +| `linux-x64` | Duktape `2.7.0` | 1.18.0 | 3.11.7 | 2025-01-01 | | `linux-arm` | Duktape `2.7.0` | 0.20.31 | 3.11.2 | 2024-06-20 | ::: diff --git a/docz/docs/03-demos/02-frontend/02-react.md b/docz/docs/03-demos/02-frontend/02-react.md index ff5ae0f..27d8fe1 100644 --- a/docz/docs/03-demos/02-frontend/02-react.md +++ b/docz/docs/03-demos/02-frontend/02-react.md @@ -753,7 +753,7 @@ This demo was tested in the following environments: | ReactJS | CRA | Date | |:---------|:--------|:-----------| -| `18.2.0` | `5.0.1` | 2024-03-13 | +| `18.2.0` | `5.0.1` | 2024-12-31 | ::: diff --git a/docz/docs/03-demos/02-frontend/03-angular.md b/docz/docs/03-demos/02-frontend/03-angular.md index ce1728b..e010b7e 100644 --- a/docz/docs/03-demos/02-frontend/03-angular.md +++ b/docz/docs/03-demos/02-frontend/03-angular.md @@ -425,8 +425,10 @@ This demo was tested in the following environments: | Angular | Date | |:----------|:-----------| -| `17.3.0` | 2024-03-13 | -| `16.2.12` | 2024-03-13 | +| `19.0.5` | 2025-01-03 | +| `18.2.13` | 2025-01-03 | +| `17.3.12` | 2025-01-03 | +| `16.2.12` | 2025-01-03 | ::: @@ -439,16 +441,16 @@ npx @angular/cli analytics disable -g 1) Create a new project: ```bash -npx @angular/cli@17.3.0 new --minimal --defaults --no-interactive sheetjs-angular +npx @angular/cli@19 new --minimal --defaults --no-interactive sheetjs-angular ``` :::note pass The `@angular/cli` version controls the project version of Angular. For example, -the following command uses Angular 16.2.12: +the following command uses Angular 16: ```bash -npx @angular/cli@16.2.12 new --minimal --defaults --no-interactive sheetjs-angular +npx @angular/cli@16 new --minimal --defaults --no-interactive sheetjs-angular ``` ::: @@ -619,8 +621,10 @@ This demo was tested in the following environments: | Angular | Date | |:----------|:-----------| -| `17.3.0` | 2024-03-13 | -| `16.2.12` | 2024-03-13 | +| `19.0.5` | 2025-01-03 | +| `18.2.13` | 2025-01-03 | +| `17.3.12` | 2025-01-03 | +| `16.2.12` | 2025-01-03 | ::: @@ -633,16 +637,16 @@ npx @angular/cli analytics disable -g 1) Create a new project: ```bash -npx @angular/cli@17.3.0 new --minimal --defaults --no-interactive sheetjs-angular +npx @angular/cli@19 new --minimal --defaults --no-interactive sheetjs-angular ``` :::note pass The `@angular/cli` version controls the project version of Angular. For example, -the following command uses Angular 16.2.12: +the following command uses Angular 16: ```bash -npx @angular/cli@16.2.12 new --minimal --defaults --no-interactive sheetjs-angular +npx @angular/cli@16 new --minimal --defaults --no-interactive sheetjs-angular ``` ::: diff --git a/docz/docs/03-demos/02-frontend/04-vue.md b/docz/docs/03-demos/02-frontend/04-vue.md index 4719a18..1d69e66 100644 --- a/docz/docs/03-demos/02-frontend/04-vue.md +++ b/docz/docs/03-demos/02-frontend/04-vue.md @@ -412,7 +412,7 @@ This demo was tested in the following environments: | VueJS | NuxtJS | Date | |:---------|:---------|:-----------| -| `3.4.21` | `3.11.1` | 2024-03-21 | +| `3.5.13` | `3.15.0` | 2025-01-02 | ::: @@ -520,7 +520,7 @@ This demo was tested in the following environments: | VueJS | ViteJS | Date | |:---------|:--------|:-----------| -| `3.4.21` | `5.2.2` | 2024-03-21 | +| `3.5.13` | `6.0.7` | 2025-01-02 | ::: @@ -573,7 +573,7 @@ This demo was tested in the following environments: | VueJS | NuxtJS | Date | |:---------|:---------|:-----------| -| `3.4.21` | `3.11.1` | 2024-03-21 | +| `3.5.13` | `3.15.0` | 2025-01-02 | ::: diff --git a/docz/docs/03-demos/02-frontend/10-openui5.md b/docz/docs/03-demos/02-frontend/10-openui5.md index c1a8355..a66f968 100644 --- a/docz/docs/03-demos/02-frontend/10-openui5.md +++ b/docz/docs/03-demos/02-frontend/10-openui5.md @@ -1,6 +1,6 @@ --- -title: Sheets in OpenUI5 Sites -sidebar_label: OpenUI5 +title: Sheets in UI5 Sites +sidebar_label: OpenUI5 / SAPUI5 description: Build enterprise-grade applications with OpenUI5. Seamlessly integrate spreadsheets into your app using SheetJS. Bring Excel-powered workflows and data to the modern web. pagination_prev: demos/index pagination_next: demos/grid/index @@ -12,7 +12,8 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; -[OpenUI5](https://openui5.org/) is a JavaScript framework for building enterprise-ready web applications. +[OpenUI5](https://openui5.org/) is a JavaScript framework for building +enterprise-ready web applications. It is compatible with the SAPUI5 framework. [SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing data from spreadsheets. @@ -21,19 +22,84 @@ This demo uses OpenUI5 and SheetJS to process and generate a spreadsheets. We'll explore how to load SheetJS in an OpenUI5 app and handle data binding with the Model-View-Controller pattern. +:::info pass + +[Docs Issue #20](https://git.sheetjs.com/sheetjs/docs.sheetjs.com/issues/20) +includes a complete example starting from the OpenUI5 "Worklist App Tutorial". + +::: + ## Installation -[The "Frameworks" section](/docs/getting-started/installation/frameworks) covers -installation with Yarn and other package managers. +SheetJS libraries conform to the UI5 ECMAScript limitations[^1]. SheetJS +libraries can be loaded in a UI5 site at different points in the app lifecycle. -The library should be loaded via script tag in your HTML: +**HTML** - - {``} +UI5 is typically loaded in a `SCRIPT` tag in `webapp/index.html`. Similarly, +[SheetJS Standalone scripts](/docs/getting-started/installation/standalone) +can be loaded in the same HTML page: + +{`\ + +`} -This will expose the `XLSX` global object which contains all the necessary methods. +This will expose the `XLSX` global object, which includes the functions listed +in the ["API Reference"](/docs/api/) section of the documentation. +:::caution pass + +The SheetJS Standalone script must be loaded before the UI5 bootstrap script: + +{`\ + + + UI5 Walkthrough + + + +`} + + +::: + +**UI5 Module** + +The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone) +comply with AMD `define` semantics. They support `sap.ui.define` out of the box. + +If the SheetJS Standalone script is saved to `webapp/xlsx.full.min.js`, the base +script `webapp/index.js` can load the library at `./xlsx.full.min`. + +```js title="webapp/index.js" +sap.ui.define([ + // highlight-next-line + "./xlsx.full.min", // relative path to script, without the file extension + /* ... other libraries ... */ +], function( + // highlight-next-line + _XLSX // !! NOTE: this is not XLSX! A different variable name must be used + /* ... variables for the other libraries ... */, +) { + // highlight-next-line + alert(XLSX.version); // use XLSX in the callback +}); +``` + +:::info pass + +In some deployments, the function argument was `undefined`. + +The standalone scripts add `window.XLSX`, so it is recommended to use `_XLSX` +in the function arguments and access the library with `XLSX` in the callback. + +::: ## Internal State @@ -70,7 +136,7 @@ object for each row, using the values in the first rows as keys: -The OpenUI5 `JSONModel`[^1] is a client-side model implementation that stores data as JSON. +The OpenUI5 `JSONModel`[^2] is a client-side model implementation that stores data as JSON. Here's a basic example of initializing a model, with a more complete implementation shown later: @@ -132,7 +198,7 @@ _loadExcelFile: async function () { #### Rendering Data -In OpenUI5, the `Model-View-Controller`[^2] pattern is used to organize code and separate concerns. +In OpenUI5, the `Model-View-Controller`[^3] pattern is used to organize code and separate concerns. The view defines the UI structure, the controller handles the logic, and the model manages the data. ```xml title="Example XML for displayin array of objects" @@ -360,14 +426,14 @@ will generate a workbook that can be opened in a spreadsheet editor. The main disadvantage of the Array of Objects approach is the specific nature of the columns. For more general use, passing around an Array of Arrays works. -However, this does not handle merge cells[^3] well! +However, this does not handle merge cells[^4] well! The [`sheet_to_html`](/docs/api/utilities/html#html-table-output) function generates HTML that is aware of merges and other worksheet -features. Using OpenUI5's `core:HTML`[^4] control, we can render this HTML directly. During export, we extract the table element from the +features. Using OpenUI5's `core:HTML`[^5] control, we can render this HTML directly. During export, we extract the table element from the rendered HTML and use [`table_to_book`](/docs/api/utilities/html#html-table-input) to create a workbook that maintains all the worksheet features. -In this example, the component directly renders the HTML table in the model through OpenUI5's `core:HTML`[^4] control. For export, we extract +In this example, the component directly renders the HTML table in the model through OpenUI5's `core:HTML`[^5] control. For export, we extract the inner table from the rendered HTML using `getElementsByTagName("table")[1]`, then pass it to [`table_to_book`](/docs/api/utilities/html#html-table-input) to create a workbook that preserves all features. @@ -513,7 +579,8 @@ will generate a workbook that can be opened in a spreadsheet editor. -[^1]: See [`JSONModel`](https://sdk.openui5.org/1.38.62/docs/api/symbols/sap.ui.model.json.JSONModel.html) in the OpenUI5 documentation. -[^2]: See OpenUI5's [MVC Documentation](https://sdk.openui5.org/topic/91f233476f4d1014b6dd926db0e91070) for detailed explanation of the pattern implementation. -[^3]: See ["Merged Cells" in "SheetJS Data Model"](/docs/csf/features/merges) for more details. -[^4]: See [`core:HTML`](https://sdk.openui5.org/1.38.62/docs/api/symbols/sap.ui.core.HTML.html) in the OpenUI5 documentation. \ No newline at end of file +[^1]: See ["ECMAScript Support"](https://sdk.openui5.org/topic/0cb44d7a147640a0890cefa5fd7c7f8e.html#loio0cb44d7a147640a0890cefa5fd7c7f8e/section_UI5Mod) for more details about OpenUI5 compatibility. +[^2]: See [`JSONModel`](https://sdk.openui5.org/1.38.62/docs/api/symbols/sap.ui.model.json.JSONModel.html) in the OpenUI5 documentation. +[^3]: See OpenUI5's [MVC Documentation](https://sdk.openui5.org/topic/91f233476f4d1014b6dd926db0e91070) for detailed explanation of the pattern implementation. +[^4]: See ["Merged Cells" in "SheetJS Data Model"](/docs/csf/features/merges) for more details. +[^5]: See [`core:HTML`](https://sdk.openui5.org/1.38.62/docs/api/symbols/sap.ui.core.HTML.html) in the OpenUI5 documentation. \ No newline at end of file diff --git a/docz/docs/03-demos/02-frontend/19-bundler/05-webpack.md b/docz/docs/03-demos/02-frontend/19-bundler/05-webpack.md index 296ae37..0d3bc34 100644 --- a/docz/docs/03-demos/02-frontend/19-bundler/05-webpack.md +++ b/docz/docs/03-demos/02-frontend/19-bundler/05-webpack.md @@ -41,10 +41,10 @@ This demo was tested in the following environments: | Version | Date | Required Workarounds | |:---------|:-----------|:------------------------------------| -| `2.7.0` | 2024-03-16 | Import `xlsx/dist/xlsx.full.min.js` | -| `3.12.0` | 2024-03-16 | Import `xlsx/dist/xlsx.full.min.js` | -| `4.47.0` | 2024-03-16 | Downgrade NodeJS (tested v16.20.2) | -| `5.90.3` | 2024-03-16 | | +| `5.97.1` | 2025-01-03 | | +| `4.47.0` | 2025-01-03 | | +| `3.12.0` | 2025-01-03 | Import `xlsx/dist/xlsx.full.min.js` | +| `2.7.0` | 2025-01-03 | Import `xlsx/dist/xlsx.full.min.js` | ::: @@ -269,15 +269,16 @@ version above 4.0 can be pinned by locally installing webpack and the CLI tool. **Webpack 4.x** -:::info pass +:::note pass -Webpack 4 is incompatible with Node 18+. It will elicit the following error: +Some Webpack 4 versions are incompatible with Node 18+. They will elicit the +following error: ``` Error: error:0308010C:digital envelope routines::unsupported ``` -When this demo was last tested, NodeJS was locally downgraded to 16.20.2 +In some demo tests, NodeJS was locally downgraded to 16.20.2 ::: diff --git a/docz/docs/03-demos/02-frontend/19-bundler/12-systemjs.md b/docz/docs/03-demos/02-frontend/19-bundler/12-systemjs.md index a0af2be..6276df2 100644 --- a/docz/docs/03-demos/02-frontend/19-bundler/12-systemjs.md +++ b/docz/docs/03-demos/02-frontend/19-bundler/12-systemjs.md @@ -46,11 +46,11 @@ This demo was tested in the following environments: | Version | Platform | Date | |:----------|:---------|:-----------| -| `0.19.47` | NodeJS | 2024-03-31 | -| `0.20.16` | Browser | 2024-03-31 | -| `0.20.19` | NodeJS | 2024-03-31 | -| `0.21.6` | NodeJS | 2024-03-31 | -| `6.14.3` | NodeJS | 2024-03-31 | +| `0.19.47` | NodeJS | 2025-01-03 | +| `0.20.16` | Browser | 2025-01-03 | +| `0.20.19` | NodeJS | 2025-03-03 | +| `0.21.6` | NodeJS | 2025-03-03 | +| `6.15.1` | NodeJS | 2025-01-03 | ::: @@ -203,7 +203,7 @@ npm init -y 1) Install the dependencies: {`\ -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz systemjs@6.14.3`} +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz systemjs@6.15.1`} 2) Download [`SheetJSystem.js`](pathname:///systemjs/SheetJSystem.js) and move diff --git a/docz/docs/03-demos/02-frontend/19-bundler/14-rollup.md b/docz/docs/03-demos/02-frontend/19-bundler/14-rollup.md index efb5175..b48b2b4 100644 --- a/docz/docs/03-demos/02-frontend/19-bundler/14-rollup.md +++ b/docz/docs/03-demos/02-frontend/19-bundler/14-rollup.md @@ -34,10 +34,10 @@ This demo was tested in the following environments: | Version | Date | |:---------|:-----------| -| `4.13.0` | 2024-03-25 | -| `3.29.4` | 2024-03-25 | -| `2.79.1` | 2024-03-25 | -| `1.32.1` | 2024-03-25 | +| `4.29.1` | 2025-01-03 | +| `3.29.5` | 2025-01-03 | +| `2.79.1` | 2025-01-03 | +| `1.32.1` | 2025-01-03 | ::: diff --git a/docz/docs/03-demos/02-frontend/19-bundler/20-parcel.md b/docz/docs/03-demos/02-frontend/19-bundler/20-parcel.md index f764f89..8effcce 100644 --- a/docz/docs/03-demos/02-frontend/19-bundler/20-parcel.md +++ b/docz/docs/03-demos/02-frontend/19-bundler/20-parcel.md @@ -34,8 +34,8 @@ This demo was tested in the following environments: | Version | Date | |:---------|:-----------| -| `2.12.0` | 2024-06-08 | -| `1.12.4` | 2024-06-08 | +| `2.13.3` | 2024-12-31 | +| `1.12.3` | 2024-12-31 | ::: diff --git a/docz/docs/03-demos/03-net/03-server/01-express.md b/docz/docs/03-demos/03-net/03-server/01-express.md index 589cbf4..cd22735 100644 --- a/docz/docs/03-demos/03-net/03-server/01-express.md +++ b/docz/docs/03-demos/03-net/03-server/01-express.md @@ -22,8 +22,12 @@ The ["Complete Example"](#complete-example) section includes a complete server. :::note Tested Deployments -This demo was tested on 2024 March 11 using `express-formidable@1.2.0` and -ExpressJS `4.18.3` +This demo was tested in the following deployments: + +| Version | Date | +|:---------|:-----------| +| `4.21.2` | 2025-01-03 | +| `5.0.1` | 2025-01-03 | ::: @@ -136,21 +140,23 @@ app.get('/download', function(req, res) { res.status(200).end(buf); // highlight-end }); -app.listen(+process.env.PORT||3000); +app.listen(+process.env.PORT||3000, function() { console.log("Ready to go"); }); ``` 2) Install dependencies: {`\ -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz express@4.18.3 express-formidable@1.2.0`} +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz express@4.21.2 express-formidable@1.2.0`} -3) Start server (note: it will not print anything to console when running) +3) Start server ```bash node SheetJSExpressCSV.js ``` +Once the server starts, the process will print `Ready to go`. + 4) Test POST requests using https://docs.sheetjs.com/pres.numbers . The commands should be run in a new terminal window: diff --git a/docz/docs/03-demos/03-net/03-server/11-nestjs.md b/docz/docs/03-demos/03-net/03-server/11-nestjs.md index f48dd03..e4d84c5 100644 --- a/docz/docs/03-demos/03-net/03-server/11-nestjs.md +++ b/docz/docs/03-demos/03-net/03-server/11-nestjs.md @@ -22,7 +22,13 @@ The ["Complete Example"](#complete-example) section includes a complete server. :::note Tested Deployments -This demo was tested on 2024 March 11 using NestJS `10.3.3`. +This demo was tested in the following deployments: + +| NestJS | Date | +|:----------|:-------------| +| `10.4.15` | `2024-12-22` | +| `9.4.3` | `2024-12-22` | +| `8.4.7` | `2024-12-22` | ::: @@ -124,10 +130,23 @@ npx @nestjs/cli@latest new -p npm sheetjs-nest cd sheetjs-nest ``` -2) Install the `@types/multer` package as a development dependency: +:::info pass + +The NestJS CLI generates a project using the latest version of NestJS. To force +an older version, install older versions of dependencies in the `@nestjs` scope. + +For example, the following command rolls back to NestJS major version 8: ```bash -npm i --save-dev @types/multer +npm install --save @nestjs/cli@8.x @nestjs/common@8.x @nestjs/core@8.x @nestjs/platform-express@8.x @nestjs/schematics@8.x @nestjs/testing@8.x --force +``` + +::: + +2) Install the `@types/multer` package as a dependency: + +```bash +npm i --save @types/multer ``` 3) Install the SheetJS library: @@ -187,7 +206,7 @@ npx @nestjs/cli start :::note pass -In the most recent test, the process failed with a message referencing `Multer`: +In some tests, the process failed with a message referencing `Multer`: ``` src/sheetjs/sheetjs.controller.ts:9:54 - error TS2694: Namespace 'global.Express' has no exported member 'Multer'. @@ -203,7 +222,7 @@ This error indicates that `@types/multer` is not available. The recommended fix is to install `@types/multer` again: ```bash -npm i --save-dev @types/multer +npm i --save @types/multer npx @nestjs/cli start ``` diff --git a/docz/docs/03-demos/03-net/03-server/19-fastify.md b/docz/docs/03-demos/03-net/03-server/19-fastify.md index 652aae4..c1bed7f 100644 --- a/docz/docs/03-demos/03-net/03-server/19-fastify.md +++ b/docz/docs/03-demos/03-net/03-server/19-fastify.md @@ -21,7 +21,12 @@ The ["Complete Example"](#complete-example) section includes a complete server. :::note Tested Deployments -This demo was verified on 2024 March 11 using `fastify@4.26.2` +This demo was tested in the following deployments: + +| Version | Date | +|:---------|:-----------| +| `4.29.0` | 2025-01-02 | +| `5.2.0` | 2025-01-02 | ::: @@ -157,7 +162,7 @@ fastify.listen({port: process.env.PORT || 3000}, (err, addr) => { if(err) throw 1) Install dependencies: {`\ -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz fastify@4.26.2 @fastify/multipart@8.1.0`} +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz fastify@4.29.0 @fastify/multipart@8`} 2) Start server diff --git a/docz/docs/03-demos/03-net/04-email/11-pst.md b/docz/docs/03-demos/03-net/04-email/11-pst.md index cc217c1..6dc5eea 100644 --- a/docz/docs/03-demos/03-net/04-email/11-pst.md +++ b/docz/docs/03-demos/03-net/04-email/11-pst.md @@ -34,7 +34,13 @@ the file can be downloaded or previewed in the browser. :::note Tested Deployments -This demo was last tested on 2024 March 11 against `pst-extractor` 1.9.0 +This demo was tested in the following deployments: + +| Platform | Version | Date | +|:------------|:---------|:-----------| +| Chrome 131 | `1.9.0` | 2024-12-22 | +| NodeJS 20 | `1.10.0` | 2024-12-22 | +| BunJS 1.1 | `1.10.0` | 2024-12-22 | ::: diff --git a/docz/docs/03-demos/03-net/04-email/index.md b/docz/docs/03-demos/03-net/04-email/index.md index 7052282..174409f 100644 --- a/docz/docs/03-demos/03-net/04-email/index.md +++ b/docz/docs/03-demos/03-net/04-email/index.md @@ -32,53 +32,25 @@ before integrating with important inboxes or accounts. :::danger pass It is strongly advised to use a test email address before using an important -address. One small mistake could erase decades of messages or result in a block +address. One small mistake could erase decades of messages or result in a block or ban from Google services. ::: ### 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. +Many email providers (including 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 -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. - -:::caution pass - -A valid phone number (for SMS verification) was required. - -::: - -0) Create a new Fastmail email account and verify with a mobile number. - - -_Create App Password_ - -1) Open the settings screen (click on the icon in the top-left corner of the -screen and select "Settings"). - -2) Select "Privacy & Security" in the left pane, then click "Integrations" near -the top of the main page. Click "New app password". - -3) Select any name in the top drop-down (the default "iPhone" can be used). In -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.** +It is strongly recommended to first test with a separate account. #### Gmail -This demo will start with a free Gmail account. At the time the demo was last -tested, no payment details were required. +This demo will start with a free Gmail account. When the demo was last tested, +no payment details were required. :::caution pass @@ -98,7 +70,8 @@ _Create App Password_ 4) Click "2-Step Verification" -5) Click the right arrow (`>`) next to "App passwords". +5) Click the right arrow (`>`) next to "App passwords". If that option is not +available, open https://myaccount.google.com/apppasswords 6) Type a name ("SheetJS Test") and click "Create". @@ -152,8 +125,7 @@ This demo was tested in the following deployments: | Email Provider | Date | Library | Version | |:---------------|:-----------|:-------------|:---------| -| `gmail.com` | 2024-03-11 | `nodemailer` | `6.9.12` | -| `fastmail.com` | 2024-03-11 | `nodemailer` | `6.9.12` | +| `gmail.com` | 2025-01-05 | `nodemailer` | `6.9.16` | ::: @@ -175,7 +147,7 @@ const nodemailer = require('nodemailer'); const transporter = nodemailer.createTransport({ // highlight-next-line - service: 'fastmail', + service: 'gmail', auth: { // highlight-start user: '**', @@ -210,7 +182,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] +- `service: 'gmail',` 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 @@ -300,8 +272,7 @@ This demo was tested in the following deployments: | Email Provider | Date | Library | Version | |:---------------|:-----------|:-----------|:----------| -| `gmail.com` | 2024-03-11 | `imapflow` | `1.0.156` | -| `fastmail.com` | 2024-03-11 | `imapflow` | `1.0.156` | +| `gmail.com` | 2025-01-05 | `imapflow` | `1.0.172` | ::: @@ -312,7 +283,7 @@ This demo was tested in the following deployments: {`\ mkdir sheetjs-recv cd sheetjs-recv -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz imapflow@1.0.156`} +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz imapflow@1.0.172`} 2) Save the following script to `SheetJSIMAP.js`: @@ -323,7 +294,7 @@ const { ImapFlow } = require('imapflow'); const client = new ImapFlow({ // highlight-next-line - host: 'imap.fastmail.com', + host: 'imap.gmail.com', port: 993, secure: true, logger: false, auth: { // highlight-start @@ -371,18 +342,19 @@ 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: +- `host: 'imap.gmail.com',` the value should be the host name: | Service | `host` value | |:---------------|:--------------------| | `gmail.com` | `imap.gmail.com` | -| `fastmail.com` | `imap.fastmail.com` | -4) Download https://docs.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 test account should have an email in the inbox that has an attachment. +4) Download https://docs.sheetjs.com/pres.numbers . -5) Run the script: +5) Send an email to the test account and attach `pres.numbers` from step 4. + +6) Wait until the test account receives the email. + +7) Run the script: ```bash node SheetJSIMAP.js diff --git a/docz/docs/03-demos/03-net/08-headless/index.md b/docz/docs/03-demos/03-net/08-headless/index.md index 5e0b0a9..62583c6 100644 --- a/docz/docs/03-demos/03-net/08-headless/index.md +++ b/docz/docs/03-demos/03-net/08-headless/index.md @@ -25,6 +25,17 @@ not generally support passing objects between the browser context and the automation script, so the file data must be generated in the browser context and sent back to the automation script for saving in the file system. +This demo exports data from https://sheetjs.com/demos/table. + +:::note pass + +It is also possible to parse files from the browser context, but parsing from +the automation context is more efficient and strongly recommended. + +::: + +#### Key Steps + ```mermaid sequenceDiagram autonumber off @@ -50,39 +61,23 @@ sequenceDiagram end ``` -
- Key Steps (click to hide) - 1) Launch the headless browser and load the target site. 2) Add the standalone SheetJS build to the page in a `SCRIPT` tag. 3) Add a script to the page (in the browser context) that will: -- Make a workbook object from the first table using `XLSX.utils.table_to_book` -- Generate the bytes for an XLSB file using `XLSX.write` +- Make a SheetJS workbook object[^1] from the first table using the SheetJS + `table_to_book`[^2] method. +- Generate the bytes for an XLSB file using the SheetJS `write`[^3] method. - Send the bytes back to the automation script 4) When the automation context receives data, save to a file -
- -This demo exports data from https://sheetjs.com/demos/table. - -:::note pass - -It is also possible to parse files from the browser context, but parsing from -the automation context is more efficient and strongly recommended. - -::: - ## Puppeteer -[Puppeteer](https://pptr.dev/) enables headless Chromium automation for NodeJS. -Releases ship with an installer script that installs a headless browser. - - - +[Puppeteer](https://pptr.dev/) enables headless Chromium automation for NodeJS +and BunJS. Releases ship with a script that installs a headless browser. Binary strings are the favored data type. They can be safely passed from the browser context to the automation script. NodeJS provides an API to write @@ -131,116 +126,61 @@ const puppeteer = require('puppeteer'); :::note Tested Deployments -This demo was last tested on 2024 June 24 against Puppeteer 22.12.0. +This demo was tested in the following deployments: + +| Puppeteer | Date | +|:----------|:-----------| +| `23.11.1` | 2024-12-31 | +| `22.15.0` | 2024-12-31 | +| `21.11.0` | 2024-12-31 | +| `20.9.0` | 2024-12-31 | +| `15.5.0` | 2024-12-31 | +| `10.4.0` | 2024-12-31 | ::: 1) Install SheetJS and Puppeteer: + + + {`\ -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz puppeteer@22.12.0`} +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz puppeteer@23.11.1`} + + + +{`\ +bun install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz puppeteer@23.11.1`} + + + + + 2) Save the `SheetJSPuppeteer.js` code snippet to `SheetJSPuppeteer.js`. 3) Run the script: + + + ```bash node SheetJSPuppeteer.js ``` -When the script finishes, the file `SheetJSPuppeteer.xlsb` will be created. -This file can be opened with Excel. - - - -:::caution pass - -Deno Puppeteer is a fork. It is not officially supported by the Puppeteer team. - -::: - -Base64 strings are the favored data type. They can be safely passed from the -browser context to the automation script. Deno can decode the Base64 strings -and write the decoded `Uint8Array` data to file with `Deno.writeFileSync` - -The key steps are commented below: - -{`\ -import puppeteer from "https://deno.land/x/puppeteer@16.2.0/mod.ts"; -import { decode } from "https://deno.land/std/encoding/base64.ts" -\n\ -/* (1) Load the target page */ -const browser = await puppeteer.launch(); -const page = await browser.newPage(); -page.on("console", msg => console.log("PAGE LOG:", msg.text())); -await page.setViewport({width: 1920, height: 1080}); -await page.goto('https://sheetjs.com/demos/table'); -\n\ -/* (2) Load the standalone SheetJS build from the CDN */ -await page.addScriptTag({ url: 'https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js' }); -\n\ -/* (3) Run the snippet in browser and return data */ -const b64 = await page.evaluate(() => { - /* NOTE: this function will be evaluated in the browser context. - \`page\`, \`fs\` and \`puppeteer\` are not available. - \`XLSX\` will be available thanks to step 2 */ -\n\ - /* find first table */ - var table = document.body.getElementsByTagName('table')[0]; -\n\ - /* call table_to_book on first table */ - var wb = XLSX.utils.table_to_book(table); -\n\ - /* generate XLSB and return binary string */ - return XLSX.write(wb, {type: "base64", bookType: "xlsb"}); -}); -/* (4) write data to file */ -Deno.writeFileSync("SheetJSPuppeteer.xlsb", decode(b64)); -\n\ -await browser.close();`} - - -**Demo** - -:::note Tested Deployments - -This demo was last tested on 2024 June 24 against `deno-puppeteer` 16.2.0. - -::: - -1) Install `deno-puppeteer`: + ```bash -env PUPPETEER_PRODUCT=chrome deno run -A --unstable https://deno.land/x/puppeteer@16.2.0/install.ts +bun SheetJSPuppeteer.js ``` -:::note pass - -In PowerShell, the environment variable should be set separately: - -```powershell -[Environment]::SetEnvironmentVariable('PUPPETEER_PRODUCT', 'chrome') -deno run -A --unstable https://deno.land/x/puppeteer@16.2.0/install.ts -``` - -::: - -2) Save the `SheetJSPuppeteer.ts` code snippet to `SheetJSPuppeteer.ts`. - -3) Run the script: - -```bash -deno run -A --unstable SheetJSPuppeteer.ts -``` - -When the script finishes, the file `SheetJSPuppeteer.xlsb` will be created. -This file can be opened with Excel. - +When the script finishes, the file `SheetJSPuppeteer.xlsb` will be created. +This file can be opened with a spreadsheet editor that supports XLSB workbooks. ## Playwright @@ -294,26 +234,56 @@ const { webkit } = require('playwright'); // import desired browser :::note Tested Deployments -This demo was last tested on 2024 June 24 against Playwright 1.45.0. +This demo was tested in the following deployments: + +| Playwright | Date | +|:-----------|:-----------| +| `1.49.1` | 2024-12-31 | ::: 1) Install SheetJS and Playwright: + + + {`\ -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz playwright@1.45.0`} +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz playwright@1.49.1`} + + + +{`\ +bun install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz playwright@1.49.1`} + + + + + 2) Save the `SheetJSPlaywright.js` code snippet to `SheetJSPlaywright.js`. 3) Run the script + + + ```bash node SheetJSPlaywright.js ``` + + + +```bash +bun SheetJSPlaywright.js +``` + + + + When the script finishes, the file `SheetJSPlaywright.xlsb` will be created. -This file can be opened with Excel. +This file can be opened with a spreadsheet editor that supports XLSB workbooks. :::caution pass @@ -456,3 +426,7 @@ env OPENSSL_CONF=/dev/null QT_QPA_PLATFORM=phantom ./phantomjs-2.1.1-linux-x86_6 ::: + +[^1]: See ["Workbook Object"](/docs/csf/book) for more details about the SheetJS workbook object. +[^2]: See [`table_to_book` in "HTML" Utilities](/docs/api/utilities/html#create-new-sheet) +[^3]: See [`write` in "Writing Files"](/docs/api/write-options) \ No newline at end of file diff --git a/docz/docs/03-demos/04-grid/01-xs.md b/docz/docs/03-demos/04-grid/01-xs.md index 26b968c..b0129e3 100644 --- a/docz/docs/03-demos/04-grid/01-xs.md +++ b/docz/docs/03-demos/04-grid/01-xs.md @@ -16,7 +16,12 @@ With a familiar UI, `x-spreadsheet` is an excellent choice for a modern editor. :::note Tested Deployments -This demo was last verified on 2024 April 25. +This demo was tested in the following environments: + +| Browser | Date | +|:------------|:-----------| +| Chrome 131 | 2024-12-31 | +| Safari 18.2 | 2024-12-31 | ::: diff --git a/docz/docs/03-demos/04-grid/02-cdg.md b/docz/docs/03-demos/04-grid/02-cdg.md index 9aff7a0..5a004e3 100644 --- a/docz/docs/03-demos/04-grid/02-cdg.md +++ b/docz/docs/03-demos/04-grid/02-cdg.md @@ -15,7 +15,12 @@ with a straightforward API. :::note Tested Deployments -This demo was last verified on 2024 April 25. +This demo was tested in the following environments: + +| Browser | Date | +|:------------|:-----------| +| Chrome 131 | 2024-12-31 | +| Safari 18.2 | 2024-12-31 | ::: diff --git a/docz/docs/03-demos/12-static/01-lume.md b/docz/docs/03-demos/12-static/01-lume.md index 4804ba2..6a57b64 100644 --- a/docz/docs/03-demos/12-static/01-lume.md +++ b/docz/docs/03-demos/12-static/01-lume.md @@ -133,8 +133,8 @@ This demo was tested in the following environments: | Lume | Date | |:---------|:-----------| -| `1.19.4` | 2024-03-16 | -| `2.1.2` | 2024-03-16 | +| `1.19.4` | 2025-01-02 | +| `2.4.3` | 2025-01-02 | This example uses the Nunjucks template format. Lume plugins support additional template formats, including Markdown and JSX. @@ -150,15 +150,17 @@ template formats, including Markdown and JSX. ```bash mkdir -p sheetjs-lume cd sheetjs-lume -deno run -Ar https://deno.land/x/lume@v2.1.2/init.ts +deno run -Ar https://deno.land/x/lume@v2.4.3/init.ts ``` -When prompted, enter the following options: +When prompted, enter the following options. The initialization script has +changed over time, so not all questions will be asked. +- `What kind of setup do you want?`: select `Basic + plugins` - `Choose the configuration file format`: select `_config.ts` - `Do you want to install some plugins now?`: select `Yes` - `Select the plugins to install`: select `sheets` and `nunjucks` -- `Do you want to setup a CMS?`: select `Maybe later` +- `Do you want to setup a CMS?`: select `No` or `Maybe later` The project will be configured and modules will be installed. @@ -226,7 +228,7 @@ deno task lume This will create a static site in the `_site` folder -7) Test the generated site by starting a web server: +8) Test the generated site by starting a web server: ```bash npx http-server _site diff --git a/docz/docs/03-demos/12-static/02-gatsbyjs.md b/docz/docs/03-demos/12-static/02-gatsbyjs.md index aedfed5..451776c 100644 --- a/docz/docs/03-demos/12-static/02-gatsbyjs.md +++ b/docz/docs/03-demos/12-static/02-gatsbyjs.md @@ -180,7 +180,7 @@ This demo was tested in the following environments: | GatsbyJS | Date | |:---------|:-----------| | `5.13.4` | 2024-05-04 | -| `4.25.8` | 2024-03-27 | +| `4.25.8` | 2025-01-02 | ::: @@ -221,8 +221,8 @@ npx gatsby new sheetjs-gatsby For older Gatsby versions, the project must be built from the starter project. -For GatsbyJS 4, the starter commit is `6bc4466090845f20650117b3d27e68e6e46dc8d5` -and the steps are shown below: +The starter commit for GatsbyJS 4 is `6bc4466090845f20650117b3d27e68e6e46dc8d5`. +This version of the starter can be fetched with `git`: ```bash git clone https://github.com/gatsbyjs/gatsby-starter-default sheetjs-gatsby @@ -234,7 +234,7 @@ cd .. ::: -2) Follow the on-screen instructions for starting the local development server: +2) Start the local development server: ```bash cd sheetjs-gatsby @@ -257,7 +257,7 @@ Open a web browser to the displayed URL (typically `http://localhost:8000/`) `}
-4) Install the library and plugins: +4) Install the SheetJS library and GatsbyJS plugins: {`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @@ -329,14 +329,18 @@ If the `plugins` array exists, the two plugins should be added at the beginning: ::: -Stop and restart the development server process (`npm run develop`). +7) Stop and restart the development server process: + +```bash +npm run develop +``` ### GraphiQL test -7) Open the GraphiQL editor. The output of the previous step displayed the URL -(typically `http://localhost:8000/___graphql` ) +8) Open the GraphiQL editor in a web browser. The output of the previous step +displayed the URL (typically `http://localhost:8000/___graphql` ). -There is an editor in the left pane. Paste the following query into the editor: +9) Paste the following query into the code editor: ```graphql title="GraphQL Query (paste into editor)" { @@ -358,7 +362,7 @@ Press the Execute Query button (`▶`) and data should show up in the right pane
Sample Output (click to show) -In GatsbyJS version `5.13.4`, the raw output was: +In GatsbyJS versions `5.13.4` and `4.25.8`, the raw output was: ```json title="GraphQL query result from GatsbyJS 5.13.4" { @@ -406,7 +410,7 @@ In GatsbyJS version `5.13.4`, the raw output was: ### React page -8) Create a new file `src/pages/pres.js` that uses the query and displays the result: +10) Create a new page `src/pages/pres.js` that displays the raw query result: ```jsx title="src/pages/pres.js (create new file)" import { graphql } from "gatsby" @@ -429,8 +433,8 @@ const PageComponent = ({data}) => { export default PageComponent; ``` -After saving the file, access `http://localhost:8000/pres` in the browser. The -displayed JSON is the data that the component receives: +11) After saving the file, access `http://localhost:8000/pres` in the browser. +The displayed JSON is the data that the component receives: ```js title="Expected contents of /pres" { @@ -445,7 +449,7 @@ displayed JSON is the data that the component receives: // .... ``` -9) Change `PageComponent` to display a table based on the data: +12) Change `PageComponent` to display a table based on the data: ```jsx title="src/pages/pres.js (replace PageComponent)" import { graphql } from "gatsby" @@ -484,7 +488,7 @@ Going back to the browser, `http://localhost:8000/pres` will show a table: ### Live refresh -10) Open the file `src/data/pres.xlsx` in Excel or another spreadsheet editor. +13) Open the file `src/data/pres.xlsx` in Excel or another spreadsheet editor. Add a new row at the end of the file, setting cell `A7` to "SheetJS Dev" and cell `B7` to `47`. The sheet should look like the following screenshot: @@ -496,7 +500,7 @@ Save the file and observe that the table has refreshed with the new data: ### Static site -11) Stop the development server and build the site: +14) Stop the development server and build the site: ```bash npm run build @@ -527,7 +531,7 @@ Pages The generated page will be placed in `public/pres/index.html`. -12) Open `public/pres/index.html` with a text editor and search for "SheetJS". +15) Open `public/pres/index.html` with a text editor and search for "SheetJS". There will be a HTML row: ```html title="public/pres/index.html (Expected contents)" diff --git a/docz/docs/03-demos/12-static/06-webpack.md b/docz/docs/03-demos/12-static/06-webpack.md index badd5c0..51caabf 100644 --- a/docz/docs/03-demos/12-static/06-webpack.md +++ b/docz/docs/03-demos/12-static/06-webpack.md @@ -184,7 +184,11 @@ document.body.appendChild(elt); :::note Tested Deployments -This demo was last tested on 2024 April 06 against Webpack 5.91.0 +This demo was tested in the following deployments: + +| Version | Date | +|:---------|:-----------| +| `5.91.0` | 2024-04-06 | ::: diff --git a/docz/docs/03-demos/12-static/07-eleventy.md b/docz/docs/03-demos/12-static/07-eleventy.md index 6f68a8c..b9b2d6c 100644 --- a/docz/docs/03-demos/12-static/07-eleventy.md +++ b/docz/docs/03-demos/12-static/07-eleventy.md @@ -114,10 +114,10 @@ accessed using the variable `pres` in a template: This demo was tested in the following environments: -| Eleventy | Date | -|:----------------|:-----------| -| `2.0.1` | 2024-03-15 | -| `3.0.0-alpha.5` | 2024-03-15 | +| Eleventy | Date | +|:---------|:-----------| +| `2.0.1` | 2024-12-23 | +| `3.0.0` | 2024-12-23 | ::: @@ -134,17 +134,17 @@ npm init -y 2) Install Eleventy and SheetJS libraries: - + {`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @11ty/eleventy@2.0.1`} - + {`\ -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @11ty/eleventy@3.0.0-alpha.5`} +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @11ty/eleventy@3.0.0`} diff --git a/docz/docs/03-demos/17-mobile/01-reactnative.md b/docz/docs/03-demos/17-mobile/01-reactnative.md index 7c3f480..b6db0e4 100644 --- a/docz/docs/03-demos/17-mobile/01-reactnative.md +++ b/docz/docs/03-demos/17-mobile/01-reactnative.md @@ -226,19 +226,19 @@ This demo was tested in the following environments: | OS | Device | RN | Date | |:-----------|:------------------|:---------|:-----------| -| iOS 15.1 | iPhone 12 Pro Max | `0.73.6` | 2024-03-13 | -| Android 29 | NVIDIA Shield | `0.73.6` | 2024-03-13 | +| iOS 15.6 | iPhone 13 Pro Max | `0.76.5` | 2025-01-05 | +| Android 34 | NVIDIA Shield | `0.76.5` | 2025-01-05 | **Simulators** | OS | Device | RN | Dev Platform | Date | |:-----------|:--------------------|:---------|:-------------|:-----------| -| Android 34 | Pixel 3a | `0.73.6` | `darwin-x64` | 2024-03-13 | -| iOS 17.4 | iPhone 15 Pro Max | `0.73.6` | `darwin-x64` | 2024-03-13 | -| Android 34 | Pixel 3a | `0.74.2` | `darwin-arm` | 2024-06-20 | -| iOS 17.5 | iPhone SE (3rd gen) | `0.74.2` | `darwin-arm` | 2024-06-20 | +| Android 34 | Pixel 3a | `0.76.5` | `darwin-x64` | 2024-12-31 | +| iOS 18.2 | iPhone 16 Pro | `0.76.5` | `darwin-x64` | 2024-12-31 | +| Android 34 | Pixel 3a | `0.76.5` | `darwin-arm` | 2025-01-05 | +| iOS 18.2 | iPhone 16 Pro | `0.76.5` | `darwin-arm` | 2025-01-05 | | Android 35 | Pixel 9 | `0.76.5` | `win11-x64` | 2024-12-22 | -| Android 34 | Pixel 3a | `0.73.7` | `linux-x64` | 2024-04-29 | +| Android 35 | Pixel 9 | `0.76.5` | `linux-x64` | 2025-01-02 | ::: @@ -280,6 +280,8 @@ export JAVA_HOME=/usr/lib/jvm/java-17-openjdk npx -y @react-native-community/cli@15 init SheetJSRNFetch --version="0.76.5" ``` +On macOS, if prompted to install `CocoaPods`, press Y + :::info pass Older versions of this demo used the `react-native` package. The `init` command @@ -481,6 +483,12 @@ If the device asks to allow USB debugging, tap "Allow". npx react-native run-android ``` +:::note pass + +Depending on the device, it may take up to 10 seconds for app to update. + +::: + **iOS Device Testing** 13) Connect an iOS device using a USB cable. @@ -494,7 +502,7 @@ If the device asks to trust the computer, tap "Trust" and enter the passcode.
Enabling Code Signing (click to show) -These instructions were verified against Xcode 15.3. +These instructions were verified against Xcode 16.2. A) Open the included iOS workspace in Xcode: @@ -526,6 +534,14 @@ brew install ios-deploy npx react-native run-ios ``` +:::info pass + +> "SheetJSRNFetch" would like to find and connect to devices on your local network. + +Local network access is not required for the demo. Select "Don't Allow". + +::: + :::caution pass In some tests, the app failed to run on the device due to "Untrusted Developer": @@ -534,7 +550,7 @@ In some tests, the app failed to run on the device due to "Untrusted Developer": Your device management settings do not allow apps from developer ... on this iPhone. You can allow using these apps in Settings. ``` -These instructions were verified against iOS 15.1. +These instructions were verified against iOS 15.6. A) Open the Settings app and select "General" > "VPN & Device Management". @@ -1027,17 +1043,19 @@ This demo was tested in the following environments: | OS | Device | RN | Date | |:-----------|:------------------|:---------|:-----------| -| iOS 15.5 | iPhone 13 Pro Max | `0.73.6` | 2024-03-31 | -| Android 29 | NVIDIA Shield | `0.73.6` | 2024-03-31 | +| iOS 15.6 | iPhone 13 Pro Max | `0.76.5` | 2025-01-05 | +| Android 34 | NVIDIA Shield | `0.76.5` | 2025-01-05 | **Simulators** | OS | Device | RN | Dev Platform | Date | |:-----------|:------------------|:---------|:-------------|:-----------| -| Android 34 | Pixel 3a | `0.73.6` | `darwin-x64` | 2024-03-31 | -| iOS 17.4 | iPhone 15 Pro Max | `0.73.6` | `darwin-x64` | 2024-03-31 | -| Android 35 | Pixel 9 | `0.76.5` | `win11-x64` | 2024-03-31 | -| Android 34 | Pixel 3a | `0.73.6` | `linux-x64` | 2024-03-31 | +| Android 34 | Pixel 3a | `0.76.5` | `darwin-x64` | 2024-12-31 | +| iOS 18.2 | iPhone 16 Pro | `0.76.5` | `darwin-x64` | 2024-12-31 | +| Android 34 | Pixel 3a | `0.76.5` | `darwin-arm` | 2025-01-05 | +| iOS 18.2 | iPhone 16 Pro | `0.76.5` | `darwin-arm` | 2025-01-05 | +| Android 35 | Pixel 9 | `0.76.5` | `win11-x64` | 2024-12-22 | +| Android 35 | Pixel 9 | `0.76.5` | `linux-x64` | 2025-01-02 | ::: @@ -1060,7 +1078,7 @@ This example tries to separate the library-specific functions. npx -y @react-native-community/cli@15 init SheetJSRN --version="0.76.5" ``` -On macOS, if prompted to install `CocoaPods`, press `y`. +On macOS, if prompted to install `CocoaPods`, press Y 2) Install shared dependencies: diff --git a/docz/docs/03-demos/17-mobile/02-nativescript.md b/docz/docs/03-demos/17-mobile/02-nativescript.md index ef9d7f6..e13971f 100644 --- a/docz/docs/03-demos/17-mobile/02-nativescript.md +++ b/docz/docs/03-demos/17-mobile/02-nativescript.md @@ -66,6 +66,7 @@ This demo was tested in the following environments: | Android 34 | Pixel 3a | `8.7.2` | `darwin-arm` | 2024-06-09 | | iOS 17.5 | iPhone SE (3rd gen) | `8.7.2` | `darwin-arm` | 2024-06-09 | | Android 35 | Pixel 9 | `8.8.3` | `win11-x64` | 2024-12-21 | +| Android 35 | Pixel 9 | `8.8.3` | `linux-x64` | 2025-01-02 | ::: diff --git a/docz/docs/03-demos/17-mobile/05-capacitor.md b/docz/docs/03-demos/17-mobile/05-capacitor.md index 0b8262b..2727bd6 100644 --- a/docz/docs/03-demos/17-mobile/05-capacitor.md +++ b/docz/docs/03-demos/17-mobile/05-capacitor.md @@ -56,6 +56,7 @@ This demo was tested in the following environments: | Android 34 | Pixel 3a | `6.0.0` / `6.0.0` | `darwin-arm` | 2024-06-02 | | iOS 17.5 | iPhone 15 Pro Max | `6.0.0` / `6.0.0` | `darwin-arm` | 2024-06-02 | | Android 35 | Pixel 9 | `6.2.0` / `6.0.2` | `win11-x64` | 2024-12-21 | +| Android 35 | Pixel 9 | `6.2.0` / `6.0.2` | `linux-x64` | 2025-01-02 | ::: diff --git a/docz/docs/03-demos/19-desktop/01-electron.md b/docz/docs/03-demos/19-desktop/01-electron.md index 67c0df8..af41a76 100644 --- a/docz/docs/03-demos/19-desktop/01-electron.md +++ b/docz/docs/03-demos/19-desktop/01-electron.md @@ -188,11 +188,11 @@ This demo was tested in the following environments: | OS and Version | Architecture | Electron | Date | |:---------------|:-------------|:---------|:-----------| -| macOS 14.4 | `darwin-x64` | `29.1.4` | 2024-03-15 | +| macOS 15.2 | `darwin-x64` | `33.2.1` | 2024-12-31 | | macOS 14.5 | `darwin-arm` | `30.0.8` | 2024-05-28 | | Windows 11 | `win11-x64` | `31.2.0` | 2024-08-18 | | Windows 11 | `win11-arm` | `30.0.8` | 2024-05-28 | -| Linux (HoloOS) | `linux-x64` | `29.1.4` | 2024-03-21 | +| Linux (HoloOS) | `linux-x64` | `33.2.1` | 2025-01-02 | | Linux (Debian) | `linux-arm` | `30.0.8` | 2024-05-28 | ::: @@ -321,8 +321,8 @@ and select `pres.numbers`. ## Electron Breaking Changes -The first version of this demo used Electron 1.7.5. The current demo includes -the required changes for Electron 30.0.8. +The first version of this demo used Electron `1.7.5`. The current demo includes +the required changes for Electron `33.2.1`. There are no Electron-specific workarounds in the library, but Electron broke backwards compatibility multiple times. A summary of changes is noted below. @@ -336,6 +336,7 @@ methods have been renamed: |:-----------------|:---------------------| | `showOpenDialog` | `showOpenDialogSync` | | `showSaveDialog` | `showSaveDialogSync` | + **This change was not properly documented!** Electron 9 and later require the preference `nodeIntegration: true` in order to diff --git a/docz/docs/03-demos/19-desktop/02-nwjs.md b/docz/docs/03-demos/19-desktop/02-nwjs.md index 0189fd0..1d2a4f4 100644 --- a/docz/docs/03-demos/19-desktop/02-nwjs.md +++ b/docz/docs/03-demos/19-desktop/02-nwjs.md @@ -113,7 +113,7 @@ This demo was tested in the following environments: | OS and Version | Architecture | NW.js | Date | Notes | |:---------------|:-------------|:---------|:-----------|:---------------------| -| macOS 14.3.1 | `darwin-x64` | `0.85.0` | 2024-03-12 | | +| macOS 15.2 | `darwin-x64` | `0.94.0` | 2024-12-31 | | | macOS 14.5 | `darwin-arm` | `0.88.0` | 2024-05-28 | | | Windows 11 | `win11-x64` | `0.94.0` | 2024-12-19 | | | Windows 11 | `win11-arm` | `0.88.0` | 2024-05-28 | | @@ -198,6 +198,7 @@ testing, version `4.11.6` correctly generated the standalone application. | Architecture | Command | |:-------------|:--------------------------------------------------------------| +| `darwin-x64` | `open ../out/sheetjs-nwjs.app` | | `linux-x64` | `../out/sheetjs-nwjs` | | `win11-x64` | `..\out\sheetjs-nwjs.exe` | diff --git a/docz/docs/03-demos/19-desktop/03-wails.md b/docz/docs/03-demos/19-desktop/03-wails.md index a8a8e9f..18d1091 100644 --- a/docz/docs/03-demos/19-desktop/03-wails.md +++ b/docz/docs/03-demos/19-desktop/03-wails.md @@ -297,11 +297,11 @@ This demo was tested in the following environments: | OS and Version | Architecture | Wails | Date | |:---------------|:-------------|:---------|:-----------| -| macOS 14.4 | `darwin-x64` | `v2.8.0` | 2024-03-15 | +| macOS 15.2 | `darwin-x64` | `v2.9.2` | 2024-12-31 | | macOS 14.5 | `darwin-arm` | `v2.8.2` | 2024-05-28 | | Windows 11 | `win11-x64` | `v2.9.2` | 2024-12-21 | | Windows 11 | `win11-arm` | `v2.8.2` | 2024-05-28 | -| Linux (HoloOS) | `linux-x64` | `v2.8.0` | 2024-03-21 | +| Linux (HoloOS) | `linux-x64` | `v2.9.2` | 2025-01-02 | | Linux (Debian) | `linux-arm` | `v2.8.2` | 2024-05-28 | ::: @@ -358,7 +358,7 @@ None of the optional packages are required for building and running this demo. On the Steam Deck (HoloOS), some dependencies must be reinstalled: ```bash -sudo pacman -Syu base-devel gtk3 glib2 pango harfbuzz cairo gdk-pixbuf2 atk libsoup +sudo pacman -Syu base-devel gtk3 glib2 pango harfbuzz cairo gdk-pixbuf2 atk libsoup webkit2gtk ``` ::: diff --git a/docz/docs/03-demos/19-desktop/04-tauri.md b/docz/docs/03-demos/19-desktop/04-tauri.md index ae4df5e..9e85f16 100644 --- a/docz/docs/03-demos/19-desktop/04-tauri.md +++ b/docz/docs/03-demos/19-desktop/04-tauri.md @@ -14,6 +14,7 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; +export const c = {style: {color:"cyan"}}; export const y = {style: {color:"gold"}}; export const g = {style: {color:"green"}}; export const B = {style: {fontWeight:"bold"}}; @@ -352,11 +353,11 @@ This demo was tested in the following environments: | OS and Version | Architecture | Tauri | Date | |:---------------|:-------------|:----------|:-----------| -| macOS 14.4 | `darwin-x64` | `v1.5.11` | 2024-04-20 | +| macOS 15.2 | `darwin-x64` | `v1.6.0` | 2024-12-31 | | macOS 14.5 | `darwin-arm` | `v1.5.14` | 2024-05-26 | | Windows 11 | `win11-x64` | `v1.6.0` | 2024-12-21 | | Windows 11 | `win11-arm` | `v1.5.14` | 2024-05-28 | -| Linux (HoloOS) | `linux-x64` | `v1.5.11` | 2024-03-21 | +| Linux (HoloOS) | `linux-x64` | `v1.6.0` | 2025-01-02 | | Linux (Debian) | `linux-arm` | `v1.5.14` | 2024-05-28 | ::: @@ -383,15 +384,16 @@ If required dependencies are installed, the output will show a checkmark next to
 [✔] Environment
-{`    `}- OS: Mac OS 14.4.1 X64
+{`    `}- OS: Mac OS 15.2.0 x86_64 (X64)
 {`    `} Xcode Command Line Tools: installed
-{`    `} rustc: 1.77.2 (25ef9e3d8 2024-04-09)
-{`    `} cargo: 1.77.2 (e52e36006 2024-03-26)
-{`    `} rustup: 1.27.0 (bbb9276d2 2024-03-08)
+{`    `} rustc: 1.83.0 (90b35a623 2024-11-26)
+{`    `} cargo: 1.83.0 (5ffbef321 2024-10-29)
+{`    `} rustup: 1.27.1 (54dd3d00f 2024-04-24)
 {`    `} Rust toolchain: stable-x86_64-apple-darwin (default)
-{`    `}- node: 20.12.1
-{`    `}- npm: 10.5.0
-{`    `}- bun: 1.1.4
+{`    `}- node: 20.18.0
+{`    `}- npm: 10.8.2
+{`    `}- bun: 1.1.42
+{`    `}- deno: deno 2.1.4
 
:::caution pass diff --git a/docz/docs/03-demos/19-desktop/05-neutralino.md b/docz/docs/03-demos/19-desktop/05-neutralino.md index 99b0d7b..881ee56 100644 --- a/docz/docs/03-demos/19-desktop/05-neutralino.md +++ b/docz/docs/03-demos/19-desktop/05-neutralino.md @@ -192,11 +192,11 @@ This demo was tested in the following environments: | OS and Version | Architecture | Server | Client | Date | |:---------------|:-------------|:---------|:---------|:-----------| -| macOS 14.4 | `darwin-x64` | `5.0.0` | `5.0.1` | 2024-03-15 | +| macOS 15.2 | `darwin-x64` | `5.5.0` | `5.5.0` | 2024-12-31 | | macOS 14.5 | `darwin-arm` | `5.1.0` | `5.1.0` | 2024-05-25 | | Windows 11 | `win11-x64` | `5.5.0` | `5.5.0` | 2024-12-20 | | Windows 11 | `win11-arm` | `5.1.0` | `5.1.1` | 2024-05-28 | -| Linux (HoloOS) | `linux-x64` | `5.0.0` | `5.0.1` | 2024-03-21 | +| Linux (HoloOS) | `linux-x64` | `5.5.0` | `5.5.0` | 2025-01-02 | | Linux (Debian) | `linux-arm` | `5.1.0` | `5.1.1` | 2024-05-28 | NeutralinoJS on Windows on ARM generates X64 binaries that run using the X64 @@ -211,7 +211,7 @@ the window. Writing files will parse the table into a spreadsheet. Installation Notes (click to show) NeutralinoJS uses `portable-file-dialogs`[^12] to show open and save dialogs. On -Linux, Zenity or KDialog are require. +Linux, a dialog box helper (Zenity or KDialog) must be installed. The last Debian test was run on a system using LXDE. KDialog is supported but must be explicitly installed: @@ -413,10 +413,12 @@ Platform-specific programs will be created in the `dist` folder: | Platform | Path to binary | |:-------------|:---------------------------------------------| +| `darwin-x64` | `./dist/sheetjs-neu/sheetjs-neu-mac_x64` | | `darwin-arm` | `./dist/sheetjs-neu/sheetjs-neu-mac_arm64` | | `win11-x64` | `.\dist\sheetjs-neu\sheetjs-neu-win_x64.exe` | | `win11-arm` | `.\dist\sheetjs-neu\sheetjs-neu-win_x64.exe` | -| `linux-arm` | `.\dist\sheetjs-neu\sheetjs-neu-linux_arm64` | +| `linux-x64` | `./dist/sheetjs-neu/sheetjs-neu-linux_x64` | +| `linux-arm` | `./dist/sheetjs-neu/sheetjs-neu-linux_arm64` | Run the generated app and confirm that Presidential data is displayed. diff --git a/docz/docs/03-demos/20-cli/03-nexe.md b/docz/docs/03-demos/20-cli/03-nexe.md index 0e312c8..dba98e2 100644 --- a/docz/docs/03-demos/20-cli/03-nexe.md +++ b/docz/docs/03-demos/20-cli/03-nexe.md @@ -41,7 +41,7 @@ This demo was tested in the following deployments: | `darwin-arm` | `4.0.0-rc.6` | `18.20.3` | Compiled | 2024-05-25 | | `win11-x64` | `4.0.0-rc.6` | `14.15.3` | Pre-built | 2024-12-19 | | `win11-arm` | `4.0.0-rc.6` | `20.10.0` | Compiled | 2024-05-28 | -| `linux-x64` | `4.0.0-rc.4` | `14.15.3` | Pre-built | 2024-03-21 | +| `linux-x64` | `4.0.0-rc.6` | `14.15.3` | Pre-built | 2024-12-31 | | `linux-arm` | `4.0.0-rc.6` | `18.20.3` | Compiled | 2024-05-26 | ::: diff --git a/docz/docs/03-demos/20-cli/05-pkg.md b/docz/docs/03-demos/20-cli/05-pkg.md index 133bd85..3c4c544 100644 --- a/docz/docs/03-demos/20-cli/05-pkg.md +++ b/docz/docs/03-demos/20-cli/05-pkg.md @@ -41,7 +41,7 @@ This demo was tested in the following deployments: | `darwin-arm` | `5.8.1` | `18.5.0` | 2024-05-25 | | `win11-x64` | `5.8.1` | `18.5.0` | 2024-12-19 | | `win11-arm` | `5.8.1` | `18.5.0` | 2024-10-25 | -| `linux-x64` | `5.8.1` | `18.5.0` | 2024-03-21 | +| `linux-x64` | `5.8.1` | `18.5.0` | 2024-12-31 | | `linux-arm` | `5.8.1` | `18.5.0` | 2024-05-26 | ::: diff --git a/docz/docs/03-demos/20-cli/08-boxednode.md b/docz/docs/03-demos/20-cli/08-boxednode.md index 7311cb1..bd5f1ba 100644 --- a/docz/docs/03-demos/20-cli/08-boxednode.md +++ b/docz/docs/03-demos/20-cli/08-boxednode.md @@ -33,7 +33,7 @@ This demo was tested in the following deployments: | `darwin-x64` | `2.4.0` | `22.2.0` | 2024-05-28 | | `darwin-arm` | `2.4.3` | `22.2.0` | 2024-05-25 | | `win11-x64` | `2.4.4` | `16.20.2` | 2024-12-19 | -| `linux-x64` | `2.4.0` | `21.7.1` | 2024-03-21 | +| `linux-x64` | `2.4.4` | `23.5.0` | 2024-12-31 | | `linux-arm` | `2.4.3` | `20.13.1` | 2024-05-26 | ::: diff --git a/docz/docs/03-demos/20-cli/11-nodesea.md b/docz/docs/03-demos/20-cli/11-nodesea.md index 4c439ce..ff3b378 100644 --- a/docz/docs/03-demos/20-cli/11-nodesea.md +++ b/docz/docs/03-demos/20-cli/11-nodesea.md @@ -162,7 +162,7 @@ This demo was tested in the following deployments: | `darwin-arm` | `22.2.0` | 2024-05-29 | | `win11-x64` | `20.13.1` | 2024-05-22 | | `win11-arm` | `20.14.0` | 2024-06-11 | -| `linux-x64` | `20.11.1` | 2024-03-18 | +| `linux-x64` | `22.12.0` | 2025-01-02 | | `linux-arm` | `20.14.0` | 2024-06-10 | ::: diff --git a/docz/docs/03-demos/20-cli/13-denosea.md b/docz/docs/03-demos/20-cli/13-denosea.md index 5a2d7aa..3a308d9 100644 --- a/docz/docs/03-demos/20-cli/13-denosea.md +++ b/docz/docs/03-demos/20-cli/13-denosea.md @@ -103,7 +103,7 @@ This demo was last tested in the following deployments: | `darwin-arm` | `1.43.6` | 2024-05-23 | | `win11-x64` | `1.43.6` | 2024-05-25 | | `win11-arm` | `2.0.3` | 2024-10-25 | -| `linux-x64` | `1.41.3` | 2024-03-18 | +| `linux-x64` | `2.1.4` | 2025-01-02 | | `linux-arm` | `1.43.6` | 2024-05-25 | ::: diff --git a/docz/docs/03-demos/23-data/16-postgresql.md b/docz/docs/03-demos/23-data/16-postgresql.md index a93daa0..dd742c3 100644 --- a/docz/docs/03-demos/23-data/16-postgresql.md +++ b/docz/docs/03-demos/23-data/16-postgresql.md @@ -36,9 +36,12 @@ This demo was tested in the following environments: | Postgres | Connector Library | Date | |:---------|:------------------|:-----------| -| `16.6.1` | `pg` (`8.13.1`) | 2024-12-03 | -| `15.6` | `pg` (`8.11.4`) | 2024-03-31 | -| `14.11` | `pg` (`8.11.4`) | 2024-03-31 | +| `17.2` | `pg` (`8.13.1`) | 2025-01-03 | +| `16.6` | `pg` (`8.13.1`) | 2025-01-03 | +| `15.10` | `pg` (`8.13.1`) | 2025-01-03 | +| `14.15` | `pg` (`8.13.1`) | 2025-01-03 | +| `13.18` | `pg` (`8.13.1`) | 2025-01-03 | +| `12.22` | `pg` (`8.13.1`) | 2025-01-03 | ::: @@ -144,125 +147,125 @@ The `sheet_to_pg_table` function: ```js /* create table and load data given a worksheet and a PostgreSQL client */ async function sheet_to_pg_table(client, worksheet, tableName) { - if (!worksheet['!ref']) return; + if (!worksheet['!ref']) return; - const range = XLSX.utils.decode_range(worksheet['!ref']); + const range = XLSX.utils.decode_range(worksheet['!ref']); - /* Extract headers from first row, clean names for PostgreSQL */ - const headers = []; + /* Extract headers from first row, clean names for PostgreSQL */ + const headers = []; + for (let col = range.s.c; col <= range.e.c; col++) { + const cellAddress = XLSX.utils.encode_cell({ r: range.s.r, c: col }); + const cell = worksheet[cellAddress]; + const headerValue = cell ? String(cell.v).replace(/[^a-zA-Z0-9_]/g, '_') : `column_${col + 1}`; + headers.push(headerValue.toLowerCase()); + } + + /* Group cell values by column for type deduction */ + const columnValues = headers.map(() => []); + for (let row = range.s.r + 1; row <= range.e.r; row++) { for (let col = range.s.c; col <= range.e.c; col++) { - const cellAddress = XLSX.utils.encode_cell({ r: range.s.r, c: col }); - const cell = worksheet[cellAddress]; - const headerValue = cell ? String(cell.v).replace(/[^a-zA-Z0-9_]/g, '_') : `column_${col + 1}`; - headers.push(headerValue.toLowerCase()); + const cellAddress = XLSX.utils.encode_cell({ r: row, c: col }); + const cell = worksheet[cellAddress]; + columnValues[col].push(cell); } + } - /* Group cell values by column for type deduction */ - const columnValues = headers.map(() => []); - for (let row = range.s.r + 1; row <= range.e.r; row++) { - for (let col = range.s.c; col <= range.e.c; col++) { - const cellAddress = XLSX.utils.encode_cell({ r: row, c: col }); - const cell = worksheet[cellAddress]; - columnValues[col].push(cell); - } - } + /* Deduce PostgreSQL type for each column */ + const types = {}; + headers.forEach((header, idx) => { + types[header] = deduceType(columnValues[idx]); + }); - /* Deduce PostgreSQL type for each column */ - const types = {}; - headers.forEach((header, idx) => { - types[header] = deduceType(columnValues[idx]); + /* Delete table if it exists in the DB */ + await client.query(format('DROP TABLE IF EXISTS %I', tableName)); + + /* Create table */ + const createTableSQL = format( + 'CREATE TABLE %I (%s)', + tableName, + headers.map(header => format('%I %s', header, types[header])).join(', ') + ); + await client.query(createTableSQL); + + /* Insert data row by row */ + for (let row = range.s.r + 1; row <= range.e.r; row++) { + const values = headers.map((header, col) => { + const cellAddress = XLSX.utils.encode_cell({ r: row, c: col }); + const cell = worksheet[cellAddress]; + return parseValue(cell, types[header]); }); - /* Delete table if it exists in the DB */ - await client.query(format('DROP TABLE IF EXISTS %I', tableName)); - - /* Create table */ - const createTableSQL = format( - 'CREATE TABLE %I (%s)', - tableName, - headers.map(header => format('%I %s', header, types[header])).join(', ') + const insertSQL = format( + 'INSERT INTO %I (%s) VALUES (%s)', + tableName, + headers.map(h => format('%I', h)).join(', '), + values.map(() => '%L').join(', ') ); - await client.query(createTableSQL); - - /* Insert data row by row */ - for (let row = range.s.r + 1; row <= range.e.r; row++) { - const values = headers.map((header, col) => { - const cellAddress = XLSX.utils.encode_cell({ r: row, c: col }); - const cell = worksheet[cellAddress]; - return parseValue(cell, types[header]); - }); - - const insertSQL = format( - 'INSERT INTO %I (%s) VALUES (%s)', - tableName, - headers.map(h => format('%I', h)).join(', '), - values.map(() => '%L').join(', ') - ); - await client.query(format(insertSQL, ...values)); - } + await client.query(format(insertSQL, ...values)); + } } function deduceType(cells) { - if (!cells || cells.length === 0) return 'text'; + if (!cells || cells.length === 0) return 'text'; - const nonEmptyCells = cells.filter(cell => cell && cell.v != null); - if (nonEmptyCells.length === 0) return 'text'; + const nonEmptyCells = cells.filter(cell => cell && cell.v != null); + if (nonEmptyCells.length === 0) return 'text'; - // Check for dates by looking at both cell type and formatted value - const isDateCell = cell => cell?.t === 'd' || (cell?.t === 'n' && cell.w && /\d{4}-\d{2}-\d{2}|\d{1,2}\/\d{1,2}\/\d{4}|\d{2}-[A-Za-z]{3}-\d{4}|[A-Za-z]{3}-\d{2}|\d{1,2}-[A-Za-z]{3}/.test(cell.w)); + // Check for dates by looking at both cell type and formatted value + const isDateCell = cell => cell?.t === 'd' || (cell?.t === 'n' && cell.w && /\d{4}-\d{2}-\d{2}|\d{1,2}\/\d{1,2}\/\d{4}|\d{2}-[A-Za-z]{3}-\d{4}|[A-Za-z]{3}-\d{2}|\d{1,2}-[A-Za-z]{3}/.test(cell.w)); - if (nonEmptyCells.some(isDateCell)) { return 'date'; } + if (nonEmptyCells.some(isDateCell)) { return 'date'; } - const allBooleans = nonEmptyCells.every(cell => cell.t === 'b'); - if (allBooleans) { return 'boolean'; } + const allBooleans = nonEmptyCells.every(cell => cell.t === 'b'); + if (allBooleans) { return 'boolean'; } - const allNumbers = nonEmptyCells.every(cell => cell.t === 'n' || (cell.t === 's' && !isNaN(cell.v.replace(/[,$\s%()]/g, '')))); + const allNumbers = nonEmptyCells.every(cell => cell.t === 'n' || (cell.t === 's' && !isNaN(cell.v.replace(/[,$\s%()]/g, '')))); - if (allNumbers) { - const numbers = nonEmptyCells.map(cell => { - if (cell.t === 'n') return cell.v; - return parseFloat(cell.v.replace(/[,$\s%()]/g, '')); - }); + if (allNumbers) { + const numbers = nonEmptyCells.map(cell => { + if (cell.t === 'n') return cell.v; + return parseFloat(cell.v.replace(/[,$\s%()]/g, '')); + }); - const needsPrecision = numbers.some(num => { - const str = num.toString(); - return str.includes('e') || - (str.includes('.') && str.split('.')[1].length > 6) || - Math.abs(num) > 1e15; - }); + const needsPrecision = numbers.some(num => { + const str = num.toString(); + return str.includes('e') + || (str.includes('.') && str.split('.')[1].length > 6) + || Math.abs(num) > 1e15; + }); - return needsPrecision ? 'numeric' : 'double precision'; - } - return 'text'; + return needsPrecision ? 'numeric' : 'double precision'; + } + return 'text'; } function parseValue(cell, type) { - if (!cell || cell.v == null) return null; + if (!cell || cell.v == null) return null; - switch (type) { - case 'date': - if (cell.t === 'd') { return cell.v.toISOString().split('T')[0]; } - if (cell.t === 'n') { - const date = new Date((cell.v - 25569) * 86400 * 1000); - return date.toISOString().split('T')[0]; - } - return null; + switch (type) { + case 'date': + if (cell.t === 'd') { return cell.v.toISOString().split('T')[0]; } + if (cell.t === 'n') { + const date = new Date((cell.v - 25569) * 86400 * 1000); + return date.toISOString().split('T')[0]; + } + return null; - case 'numeric': - case 'double precision': - if (cell.t === 'n') return cell.v; - if (cell.t === 's') { - const cleaned = cell.v.replace(/[,$\s%()]/g, ''); - if (!isNaN(cleaned)) return parseFloat(cleaned); - } - return null; + case 'numeric': + case 'double precision': + if (cell.t === 'n') return cell.v; + if (cell.t === 's') { + const cleaned = cell.v.replace(/[,$\s%()]/g, ''); + if (!isNaN(cleaned)) return parseFloat(cleaned); + } + return null; - case 'boolean': - return cell.t === 'b' ? cell.v : null; + case 'boolean': + return cell.t === 'b' ? cell.v : null; - default: - return String(cell.v); - } + default: + return String(cell.v); + } } ``` @@ -271,7 +274,7 @@ function parseValue(cell, type) { ## Complete Example -0) Install and start the PostgreSQL server. +0) Install and start the PostgreSQL serve r.
Installation Notes (click to show) diff --git a/docz/docs/03-demos/23-data/25-mongodb.md b/docz/docs/03-demos/23-data/25-mongodb.md index 872811a..017e810 100644 --- a/docz/docs/03-demos/23-data/25-mongodb.md +++ b/docz/docs/03-demos/23-data/25-mongodb.md @@ -1,6 +1,6 @@ --- -title: Sheets with MongoDB -sidebar_label: MongoDB / FerretDB +title: Sheets with FerretDB and MongoDB +sidebar_label: FerretDB / MongoDB pagination_prev: demos/cli/index pagination_next: demos/local/index sidebar_custom_props: @@ -11,7 +11,8 @@ import current from '/version.js'; import CodeBlock from '@theme/CodeBlock'; [MongoDB](https://mongodb.github.io/node-mongodb-native/) is a document-oriented -database engine. +database engine. [FerretDB](https://www.ferretdb.com/) is a truly open source +implementation of the MongoDB wire protocol [SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing data from spreadsheets. @@ -24,11 +25,11 @@ to add data from spreadsheets into a collection. This demo was tested in the following environments: -| Server | Connector Library | Date | -|:--------------------|:--------------------|:-----------| -| FerretDB `1.21.0` | `mongodb` (`5.9.2`) | 2024-03-30 | -| MongoDB CE `6.0.15` | `mongodb` (`6.5.0`) | 2024-05-01 | -| MongoDB CE `7.0.8` | `mongodb` (`6.5.0`) | 2024-05-01 | +| Server | Connector Library | Date | +|:--------------------|:---------------------|:-----------| +| FerretDB `1.24.0` | `mongodb` (`6.12.0`) | 2025-01-03 | +| MongoDB CE `6.0.15` | `mongodb` (`6.5.0`) | 2024-05-01 | +| MongoDB CE `7.0.8` | `mongodb` (`6.5.0`) | 2024-05-01 | ::: @@ -123,13 +124,69 @@ If Homebrew is configured to use `/opt/homebrew`, the command is:
+
+ FerretDB Setup (click to show) + +The official documentation recommends Docker, but it is strongly recommended to +use [`colima`](https://github.com/abiosoft/colima) on MacOS: + +```bash +brew install colima docker docker-compose +``` + +To properly install `docker-compose`, the `colima` process must be run once: + +```bash +/opt/homebrew/opt/colima/bin/colima start -f +``` + +After stopping the process, delete any containers: + +```bash +/opt/homebrew/opt/colima/bin/colima delete +``` + + `config.json` must be edited: + +- Homebrew docker plugins folder must be added to `cliPluginsExtraDirs`. +- All `credsStore` settings must be removed. + +When the demo was last tested, the following `config.json` was used: + +```json title="~/.docker/config.json" +{ + "auths": {}, + "currentContext": "colima", +/* highlight-start */ + "cliPluginsExtraDirs": [ + "/opt/homebrew/lib/docker/cli-plugins" + ] + /* highlight-end */ +} +``` + +After making the changes, start `colima` again and keep the window open: + +```bash +/opt/homebrew/opt/colima/bin/colima start -f +``` + +Start the FerretDB server in a new terminal window: + +```bash +cd /tmp +docker run -d --rm --name ferretdb -p 27017:27017 -e FERRETDB_HANDLER=sqlite ghcr.io/ferretdb/all-in-one +``` + +
+ 2) Create base project and install the dependencies: {`\ mkdir sheetjs-mongo cd sheetjs-mongo npm init -y -npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz mongodb@6.5.0`} +npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz mongodb@6.12.0`} 3) Save the following to `SheetJSMongoCRUD.mjs` (the key step is highlighted): diff --git a/docz/docs/03-demos/27-local/03-storageapi.md b/docz/docs/03-demos/27-local/03-storageapi.md index a9a28f4..db6795d 100644 --- a/docz/docs/03-demos/27-local/03-storageapi.md +++ b/docz/docs/03-demos/27-local/03-storageapi.md @@ -20,8 +20,8 @@ Each browser demo was tested in the following environments: | Browser | Date | |:------------|:-----------| -| Chrome 122 | 2024-03-25 | -| Safari 17.3 | 2024-03-12 | +| Chrome 131 | 2024-12-23 | +| Safari 18.2 | 2024-12-31 | ::: @@ -48,8 +48,8 @@ strings using `JSON.stringify` and store using the row index as a key: #### Importing Data -Starting from a worksheet, `XLSX.utils.sheet_to_json` generates an array of row -objects. `localStorage.setItem` will store data in Local Storage: +Starting from a worksheet, the SheetJS `sheet_to_json` method[^1] generates an +array of row objects. `localStorage.setItem` will store data in Local Storage: ```js function sheet_to_localStorage(worksheet) { @@ -65,9 +65,35 @@ function sheet_to_localStorage(worksheet) { `localStorage.length` returns the total number of entries. A simple `for` loop can cover the keys (integers from `0` to `localStorage.length - 1` inclusive) -`localStorage.getItem` will load the stringified data from the Local Storage. A -new array of objects can be constructed by using `JSON.parse` and pushing to an -array. `XLSX.utils.json_to_sheet` can create a new worksheet from that array: +`localStorage.getItem` will load the stringified data from the Local Storage. + +The following function collects data from `localStorage` to an array of strings: + +```js +function localStorage_to_array_of_strings() { + const strings = []; + for(let i = 0; i < localStorage.length; ++i) { + aoo.push(localStorage.getItem(i)); + } + return strings; +} +``` + +Since each entry is a string created using `JSON.stringify`, an object can be +constructed using `JSON.parse`: + +```js +function localStorage_to_array_of_objects() { + const objects = []; + for(let i = 0; i < localStorage.length; ++i) { + aoo.push(JSON.parse(localStorage.getItem(i))); + } + return objects; +} +``` + +The SheetJS `json_to_sheet`[^2] method will create a new worksheet from the +array of objects: ```js function localStorage_to_sheet() { @@ -173,7 +199,8 @@ objects approach has an ordering. That does not apply to the general case. ::: In modern browsers, `Object.entries` will generate an array of key/value pairs. -`XLSX.utils.aoa_to_sheet` will interpret that array as a worksheet with 2 cols: +The SheetJS `aoa_to_sheet`[^3] method will interpret that array as a worksheet +with 2 columns (key and value): ```js function localStorage_to_ws() { @@ -185,8 +212,8 @@ function localStorage_to_ws() { #### Importing Storage In the other direction, the worksheet is assumed to store keys in column A and -values in column B. `XLSX.utils.sheet_to_json` with the `header: 1` option -will generate key/value pairs that can be assigned to a storage: +values in column B. The SheetJS `sheet_to_json`[^1] method, with the option +`header: 1`, will generate key/value pairs that can be assigned to a storage: ```js function ws_to_localStorage(ws) { @@ -239,4 +266,8 @@ function SheetJSRandomStorage() { } ``` -
\ No newline at end of file +
+ +[^1]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output) +[^2]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input) +[^3]: See [`aoa_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-arrays-input) diff --git a/docz/docs/03-demos/27-local/09-indexeddb.md b/docz/docs/03-demos/27-local/09-indexeddb.md index fafba57..1ce1d2a 100644 --- a/docz/docs/03-demos/27-local/09-indexeddb.md +++ b/docz/docs/03-demos/27-local/09-indexeddb.md @@ -8,7 +8,7 @@ sidebar_custom_props: - + :::danger pass @@ -43,8 +43,8 @@ This demo was last tested in the following environments: | Browser | Date | `localForage` | |:------------|:-----------|:--------------| -| Chrome 122 | 2024-03-21 | 1.10.0 | -| Safari 17.4 | 2024-03-23 | 1.10.0 | +| Chrome 131 | 2024-12-31 | `1.10.0` | +| Safari 18.2 | 2024-12-31 | `1.10.0` | ::: @@ -113,9 +113,10 @@ function SheetJSLocalForage() { This demo was last tested in the following environments: -| Browser | Date | DexieJS | -|:------------|:-----------|:--------| -| Chrome 122 | 2024-03-21 | 3.2.4 | +| Browser | Date | DexieJS | +|:------------|:-----------|:---------| +| Chrome 131 | 2024-12-31 | `4.0.10` | +| Safari 18.2 | 2024-12-31 | `4.0.10` | ::: diff --git a/docz/docs/03-demos/30-cloud/01-salesforce.md b/docz/docs/03-demos/30-cloud/01-salesforce.md index 23b8345..d45d437 100644 --- a/docz/docs/03-demos/30-cloud/01-salesforce.md +++ b/docz/docs/03-demos/30-cloud/01-salesforce.md @@ -29,7 +29,11 @@ may require some adjustments. The official documentation should be consulted. :::note Tested Deployments -This demo was last tested on 2024 October 06 using Lightning API version `61.0`. +This demo was tested in the following deployments: + +| Lightning API | Date | +|:--------------|:-----------| +| `61.0` | 2024-10-06 | ::: diff --git a/docz/docs/03-demos/30-cloud/21-gsheet.md b/docz/docs/03-demos/30-cloud/21-gsheet.md index 2810b8a..54ed00c 100644 --- a/docz/docs/03-demos/30-cloud/21-gsheet.md +++ b/docz/docs/03-demos/30-cloud/21-gsheet.md @@ -10,11 +10,12 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CodeBlock from '@theme/CodeBlock'; -:::note pass +:::info pass -This demo focuses on external data processing. For Google Apps Script custom -functions, [the "Google Sheets" extension demo](/docs/demos/extensions/gsheet) -covers Apps Script integration. +This demo focuses on external data processing. + +[The "Google Sheets" extension demo](/docs/demos/extensions/gsheet) covers Apps +Script integration and user-defined functions. ::: diff --git a/docz/docs/03-demos/32-extensions/01-extendscript.md b/docz/docs/03-demos/32-extensions/01-extendscript.md index 7f41c78..dff484d 100644 --- a/docz/docs/03-demos/32-extensions/01-extendscript.md +++ b/docz/docs/03-demos/32-extensions/01-extendscript.md @@ -45,10 +45,10 @@ This demo was verified in the following deployments: | App | Platform | Date | |:----------|:-------------|:-----------| -| Photoshop | ExtendScript | 2024-03-12 | -| InDesign | ExtendScript | 2024-08-12 | -| InDesign | CEP | 2024-03-12 | -| InDesign | UXP | 2024-03-11 | +| Photoshop | ExtendScript | 2025-01-03 | +| InDesign | ExtendScript | 2025-01-03 | +| InDesign | CEP | 2025-01-03 | +| InDesign | UXP | 2025-01-03 | ::: @@ -112,15 +112,20 @@ author (`activeDocument.info.author`) will be changed accordingly.
  • parse.jsx
  • -2) Restart Photoshop and open a file (or create a new one) +2) Restart Photoshop. -3) File > Scripts > parse and select the test workbook +3) Create a new file using the default settings. -4) An alert will confirm that the file was read and the author will be changed: +4) In the menu bar, select File > Scripts > parse and select the test workbook -!["Changing Author" popup](pathname:///files/psparse.png) +An alert will confirm that the file was read and the author will be changed: -5) Check the Author field of the document in File > File Info... +!["Changing Author" popup](pathname:///extendscript/psparse.png) + +5) In the menu bar, select File > File Info… and select "Basic" in the popup. +The text box next to "Author:" will show `Sh33tJ5`. + +!["Author" property in Photoshop](pathname:///extendscript/psauthor.png) @@ -133,17 +138,17 @@ the Layers window is "Title") will be set to the name of the first worksheet. - The data from the first sheet will be added to the "Table Frame" TextFrame. -0) Download the [test workbook](https://docs.sheetjs.com/pres.xlsx) and -[InDesign template](pathname:///extendscript/Template.idml) +0) Download the [`pres.xlsx` test workbook](https://docs.sheetjs.com/pres.xlsx) +and [`Template.idml` InDesign template](pathname:///extendscript/Template.idml) -1) Download the following scripts and move to the scripts directory[^4]: +1) Download the following scripts and move to the scripts directory[^3]: -2) Open the template +2) Open `Template.idml` in InDesign. 3) Activate the Scripts panel. Expand the "User" folder and double-click `esidparse` in the list. @@ -187,25 +192,31 @@ selected, the library will create a new workbook with one worksheet. Cell `A1` will be "Author" and cell `B1` will be the active Photoshop document Author. The PS author is available as `activeDocument.info.author`. -1) Download the following scripts and move to the scripts directory[^6]: +1) Download the following scripts and move to the scripts directory[^3]: -2) Restart Photoshop and open a file (or create a new one) +2) Restart Photoshop. -3) File > File Info ... and confirm there is an Author. If not, set to `SheetJS` +3) Create a new file using the default settings. -4) File > Scripts > write and use the popup to select the Documents folder. - Enter `SheetJSPSTest.xlsx` and press "Save" +4) In the menu bar, select File > File Info… and add an Author if it is blank. -5) An alert will confirm that the file was created: +5) In the menu bar, select File > Scripts > write. -!["Created File" popup](pathname:///files/pswrite.png) +Select the Documents folder, enter the file name `SheetJSPSTest.xlsx` and +press "Save". -6) Open the generated `SheetJSPSTest.xlsx` file and compare to Photoshop author +6) Click "OK" in the "Created File" alert: + +!["Created File" popup](pathname:///extendscript/pswrite.png) + +7) Open the generated `SheetJSPSTest.xlsx` file. + +Cell `A1` will be "Author" and cell `B1` will match the Photoshop file author. @@ -214,16 +225,16 @@ In this example, the script will show a dialog to select an output file. Once selected, the library will scan all text frames for table objects. Each table object will be scanned and a new worksheet will be created. -0) Download the [InDesign document](pathname:///extendscript/Filled.idml) +0) Download the [`Filled.idml` document](pathname:///extendscript/Filled.idml) -1) Download the following scripts and move to the scripts directory[^7]: +1) Download the following scripts and move to the scripts directory[^3]: -2) Open the document. +2) Open `Filled.idml` in InDesign. 3) Activate the Scripts panel. Expand the "User" folder and double-click `esidwrite` in the list. Use the popup to select the Documents folder. Enter @@ -253,6 +264,8 @@ manifest must include the following flags to enable `cep.fs`: ``` +#### Unsigned Extensions + :::caution pass With newer versions of Creative Cloud apps, a special player debug mode must be @@ -318,9 +331,16 @@ If prompted, give administrator privileges. 4) Show the extension (in the menu bar, select Window > Extensions > SheetJS) +:::caution pass + +If the extension panel is blank, unsigned extensions must be enabled. See the +["Unsigned Extensions" note](#unsigned-extensions) for more details. + +::: + 5) In the extension panel, click "Import from file" and select `pres.xlsx` -After "success" popup, the first worksheet should be written to the file. +After "success" popup, the first worksheet should be written to the document. @@ -358,7 +378,7 @@ cep.fs.writeFile(fn.data, b64, cep.encoding.Base64); 0) Download [`com.sheetjs.data.zip`](pathname:///extendscript/com.sheetjs.data.zip) and extract to a `com.sheetjs.data` subdirectory. -1) Move the entire `com.sheetjs.data` folder to the CEP extensions folder[^13]: +1) Move the entire `com.sheetjs.data` folder to the CEP extensions folder[^10]: If prompted, give administrator privileges. @@ -366,9 +386,17 @@ If prompted, give administrator privileges. 3) Show the extension (in the menu bar, select Window > Extensions > SheetJS) +:::caution pass + +If the extension panel is blank, unsigned extensions must be enabled. See the +["Unsigned Extensions" note](#unsigned-extensions) for more details. + +::: + 4) In the extension panel, click "Export to XLSX" and "Save" in the dialog. -5) A popup will display the path to the generated file. Open the new file. +5) A popup will display the path to the generated file (`SheetJSIDCEP.xlsx` in +the Documents folder). Open the new file. @@ -398,7 +426,7 @@ const storage = UXP.storage, ufs = storage.localFileSystem; The `getFileForOpening` method resolves to a `File` object. Reading the file with the `binary` format returns an `ArrayBuffer` object that can be parsed -with the SheetJS `read` method[^14]: +with the SheetJS `read` method[^8]: ```js /* show file picker (single file, no folders) */ @@ -415,7 +443,7 @@ const wb = XLSX.read(ab); -0) Open the "Scripts Panel" folder[^15]. +0) Open the "Scripts Panel" folder[^3]. 1) Download the following scripts: @@ -450,7 +478,7 @@ If the InDesign version does not support UXP, a tooltip shows a message: ### Writing Files -The SheetJS `write` method[^16], with the option `type: "buffer"`[^17], returns +The SheetJS `write` method[^11], with the option `type: "buffer"`[^12], returns file data stored in a `Uint8Array`. The `getFileForSaving` method resolves to a `File` object. The `write` method @@ -474,7 +502,7 @@ await file.write(buf, { data: storage.formats.binary }); -0) Open the "Scripts Panel" folder[^18]. +0) Open the "Scripts Panel" folder[^3]. 1) Download the following scripts: @@ -501,7 +529,9 @@ Move them to the Scripts Panel folder. ### Scripts Panel The scripts panel folder is used for ExtendScript and UXP scripts. The location -can be revealed from the relevant applications. For InDesign: +can be revealed from the relevant applications. + +**InDesign** 1) Activate Scripts panel (Windows > Utilities > Scripts) @@ -518,6 +548,13 @@ Some versions of InDesign will open the parent "Scripts" folder. If there is a ::: +**Photoshop** + +The scripts folder is located in `\Presets\Scripts` within the app folder. + +For example, on Windows, the Photoshop 2025 scripts folder is typically +`c:\Program Files\Adobe\Adobe Photoshop 2025\Presets\Scripts` + ### CEP Extensions CEP extension scripts are typically stored in a system-wide folder: @@ -532,18 +569,9 @@ Administrator privileges are usually required for writing to the folder. [^1]: Historically, Adobe applications were separate entities. Eventually they were bundled in a package called "Creative Suite". It was rebranded to "Creative Cloud" later. As ExtendScript was introduced during the Creative Suite era, this page will use the phrase "Creative Suite". [^2]: See [`readFile` in "Reading Files"](/docs/api/parse-options) [^3]: See ["Scripts Panel"](#scripts-panel) -[^4]: See ["Scripts Panel"](#scripts-panel) [^5]: See [`writeFile` in "Writing Files"](/docs/api/write-options) -[^6]: See ["Scripts Panel"](#scripts-panel) -[^7]: See ["Scripts Panel"](#scripts-panel) [^8]: See [`read` in "Reading Files"](/docs/api/parse-options) [^9]: See [the "base64" type in "Reading Files"](/docs/api/parse-options#input-type) [^10]: See ["CEP Extensions"](#cep-extensions) [^11]: See [`write` in "Writing Files"](/docs/api/write-options) [^12]: See ["Supported Output Formats" type in "Writing Files"](/docs/api/write-options#supported-output-formats) -[^13]: See ["CEP Extensions"](#cep-extensions) -[^14]: See [`read` in "Reading Files"](/docs/api/parse-options) -[^15]: See ["Scripts Panel"](#scripts-panel) -[^16]: See [`write` in "Writing Files"](/docs/api/write-options) -[^17]: See ["Supported Output Formats" type in "Writing Files"](/docs/api/write-options#supported-output-formats) -[^18]: See ["Scripts Panel"](#scripts-panel) \ No newline at end of file diff --git a/docz/docs/03-demos/32-extensions/02-chromium.md b/docz/docs/03-demos/32-extensions/02-chromium.md index 8a8df01..f2abaa8 100644 --- a/docz/docs/03-demos/32-extensions/02-chromium.md +++ b/docz/docs/03-demos/32-extensions/02-chromium.md @@ -21,7 +21,11 @@ tables with a content script and a background script. :::note Tested Deployments -This demo was last tested on 2024 March 30 against Chrome 122. +This demo was tested in the following deployments: + +| Platform | Date | +|:------------|:-----------| +| Chrome 131 | 2025-01-02 | ::: @@ -383,6 +387,14 @@ chrome.bookmarks.getTree(function(res) { ### Table Exporter +:::caution pass + +**Due to security restrictions, V2 table export does not work in Chrome 131!** + +The Manifest V3 table exporter does work in Chrome 131. + +::: +
    Testing (click to hide) diff --git a/docz/docs/03-demos/32-extensions/03-excelapi.md b/docz/docs/03-demos/32-extensions/03-excelapi.md index 1f6376f..d7a8001 100644 --- a/docz/docs/03-demos/32-extensions/03-excelapi.md +++ b/docz/docs/03-demos/32-extensions/03-excelapi.md @@ -35,7 +35,12 @@ data into the worksheet. :::note Tested Deployments -This demo was last tested on 2024 August 11 against Excel 365 (version 2407). +This demo was tested in the following deployments: + +| OS and Version | Architecture | Excel | Date | +|:---------------|:-------------|:-----------|:-----------| +| macOS 14.5 | `darwin-arm` | 16.81 | 2024-12-22 | +| Windows 11 | `win11-x64` | 365 (2407) | 2024-08-11 | ::: @@ -125,7 +130,7 @@ export async function extern(url) { ## Complete Demo -0) Clear the functions cache. For the tested version of Excel: +0) Clear the functions cache. For the tested version of Excel for Windows: - Open File Explorer - Select the address bar and enter `%LOCALAPPDATA%\Microsoft\Office\16.0\Wef` @@ -143,7 +148,7 @@ after testing is finished. 1) Install [NodeJS LTS](https://nodejs.org/en/download/). -2) After installing NodeJS, launch a new PowerShell window. +2) Launch a new PowerShell (Windows) or Terminal (MacOS) window. 3) Disable telemetry: @@ -220,9 +225,10 @@ element with name `bt:String`. Change the `DefaultValue` attribute to `SHEETJS`: 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: +9) In the terminal window, start the development process again: ```bash +npm run stop npm start ``` @@ -251,9 +257,10 @@ export function version() { 12) Close the terminal window and the Excel window. Do not save the Excel file. -13) In the PowerShell window, start the development process again: +13) In a new terminal window, start the development process again: ```bash +npm run stop npm start ``` @@ -264,6 +271,33 @@ npm start This indicates that the SheetJS library has been loaded. +:::info pass + +In some MacOS tests, the add-in installed `CONTOSO.VERSION`. To force a refresh +of the manifest: + +1) Stop the development process: + +```bash +npm run stop +``` + +2) Close the Excel app by right-clicking Excel in the Dock and selecting "Quit". + +3) Restart the development process: + +```bash +npm start +``` + +4) Activate the Task Pane for the addin (click "Show Task Pane" in the ribbon). + +5) Hover near the top-right corner of the addin and click the `i` icon. + +6) Click "Clear Web Cache" and wait a few moments. + +::: + ### Fetching Files from the Internet 15) Add the following code snippet to `src\functions\functions.js` and save: @@ -296,9 +330,10 @@ export async function extern(url) { 16) Close the terminal window and the Excel window (do not save the Excel file). -17) In the PowerShell window, start the development process again: +17) In a new terminal window, start the development process again: ```bash +npm run stop npm start ``` diff --git a/docz/docs/03-demos/32-extensions/04-gsheet.md b/docz/docs/03-demos/32-extensions/04-gsheet.md index 98b3f54..0cdb08f 100644 --- a/docz/docs/03-demos/32-extensions/04-gsheet.md +++ b/docz/docs/03-demos/32-extensions/04-gsheet.md @@ -10,17 +10,20 @@ sidebar_custom_props: import current from '/version.js'; import CodeBlock from '@theme/CodeBlock'; -:::note pass +:::info pass -This demo focuses on Google Apps Script custom functions. For external data -processing, [the "Google Sheets" cloud data demo](/docs/demos/cloud/gsheet) -covers the API for NodeJS scripts +This demo focuses on Google Apps Script custom functions. + +[The "Google Sheets" cloud data demo](/docs/demos/cloud/gsheet) covers NodeJS +APIs for external data processing. ::: -The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone) -can be uploaded into an Apps Script project. Once uploaded, the `XLSX` variable -is available to other scripts in the project. +[Google Sheets](https://google.com/sheets/about/) is a collaborative spreadsheet +service with powerful JavaScript automation and user-defined functions. + +[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing +data from spreadsheets. Google Sheets currently does not provide support for working with Apple Numbers files and some legacy file formats. SheetJS fills the gap. @@ -32,12 +35,20 @@ remote file, parses the contents, and writes data to the sheet: :::note Tested Deployments -This demo was last tested on 2024 March 11. +This demo was tested in the following deployments: + +| Clasp | Date | +|:--------|:-----------| +| `2.4.2` | 2024-12-31 | ::: ## Integration Details +The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone) +can be uploaded into an Apps Script project. Once uploaded, the `XLSX` variable +is available to other scripts in the project. + ### Adding the script The `clasp` command line tool can be used to upload the standalone script: @@ -66,24 +77,55 @@ const response = UrlFetchApp.fetch("https://docs.sheetjs.com/pres.numbers"); const content = response.getContent(); ``` -The `"array"` type for `XLSX.read` expects an array of *unsigned* bytes. -Fortunately, the content can be corrected with bitwise operations: +The SheetJS `read` method[^1] can read arrays of *unsigned* bytes. Fortunately, +the values in the array can be corrected with bitwise operations: ```js for(var i = 0; i < content.length; ++i) content[i] &= 0xFF; +``` + +After converting each signed byte to unsigned byte, the array can be parsed with +the `read` method: + +```js const wb = XLSX.read(content, { type: "array" }); ``` ### Returning data -`XLSX.utils.sheet_to_json` with the option `header: 1` returns arrays of arrays -that play nice with Google Sheets: +The SheetJS `sheet_to_json` method[^2] with the option `header: 1` returns +arrays of arrays of data[^3]: ```js const first_worksheet = wb.Sheets[wb.SheetNames[0]]; const aoa = XLSX.utils.sheet_to_json(first_worksheet, {header: 1}); ``` +Google Sheets will spread arrays of arrays across rows and columns. The `AOA` +function below returns an array that contains two arrays. The screenshot shows +the result of setting cell `A1` to the formula `=AOA()`: + + + + +
    Custom FunctionGoogle Sheets
    + +```js +function AOA(url) { + return [ + ["Sheet", "JS"], + [ 72, 62] + ]; +} +``` + + + +![Google Sheets result for AOA function](pathname:///gsheet/aoa-udf.png) + +
    + + ## Complete Demo This demo creates a function `SHEETJS(url)` that fetches the specified URL, @@ -99,14 +141,33 @@ extracts data from the first worksheet, and writes the data npx @google/clasp login ``` -A browser window should direct to an account selection page. Select the account -from the previous step. In the next page, there will be a title like +A browser window should direct to an account selection page. -> clasp – The Apps Script CLI wants to access your Google Account +2) Select the account from step 0. -At the bottom of the screen, click "Allow". +The next page will include the following title: -The terminal window should now state +> Sign in to clasp – The Apps Script CLI + +![clasp sign-in](pathname:///gsheet/clasp-signin.png) + +3) At the bottom of the screen, click "Continue". + +4) In the next screen, check every box that mentions "Google Apps Script". When +the demo was last tested, the following were required: + +- Create and update Google Apps Script deployments. +- Create and update Google Apps Script projects. + +![clasp permissions](pathname:///gsheet/clasp-perms.png) + +5) Scroll to the bottom of the screen and click "Continue". + +The browser will show the following message: + +> Logged in! You may close this page. + +The terminal window will show the following message: ``` Authorization successful. @@ -114,22 +175,26 @@ Authorization successful. ### Creating a Sheet -2) Sign into Google Sheets with the same account and create a new blank sheet +6) Sign into Google Sheets with the same account. -3) Open up the apps script window (Extensions > Apps Script) +7) Create a new Blank spreadsheet. -4) Click the gear icon (Project Settings) and copy the Script ID +8) Open the apps script window (Extensions > Apps Script) + +![extensions - apps script](pathname:///gsheet/apps-script.png) + +9) Click the gear icon (Project Settings) and copy the Script ID ### Cloning the Apps Script -5) In the terminal window, create a new folder for your project: +10) In the terminal window, create a new folder for your project: ```bash mkdir SheetJSGAS cd SheetJSGAS ``` -6) Clone the Apps Script project. The official command is: +11) Clone the Apps Script project. The official command is: ```bash npx @google/clasp clone PASTE_YOUR_ID_HERE @@ -141,7 +206,7 @@ and paste in the terminal. Press Enter after pasting the ID. ### Adding the SheetJS Library -7) Download the SheetJS Standalone script and move to the project directory: +12) Download the SheetJS Standalone script and move to the project directory: