This commit is contained in:
SheetJS 2024-03-18 04:24:41 -04:00
parent 1480a3e021
commit e3ca16d997
32 changed files with 745 additions and 112 deletions

@ -41,10 +41,10 @@ This demo was tested in the following environments:
| Version | Date | Required Workarounds |
|:---------|:-----------|:------------------------------------|
| `2.7.0` | 2023-10-17 | Import `xlsx/dist/xlsx.full.min.js` |
| `3.12.0` | 2023-10-17 | Import `xlsx/dist/xlsx.full.min.js` |
| `4.47.0` | 2023-10-17 | Downgrade NodeJS (tested v16.20.2) |
| `5.89.0` | 2023-12-04 | |
| `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 | |
:::
@ -271,8 +271,13 @@ version above 4.0 can be pinned by locally installing webpack and the CLI tool.
:::info pass
Webpack 4 is incompatible with Node 18+. When this demo was last tested, NodeJS
was locally downgraded to 16.20.2
Webpack 4 is incompatible with Node 18+. It 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
:::

@ -28,7 +28,7 @@ This demo was last tested on 2024 March 11 against Drash 2.8.1 and Deno 1.41.2.
## Integration Details
The [SheetJS Deno module](/docs/getting-started/installation/nodejs) can be
The [SheetJS Deno module](/docs/getting-started/installation/deno) can be
imported from Drash server scripts.
### Reading Data

@ -129,7 +129,12 @@ site.use(sheets({
:::note Tested Deployments
This demo was last tested against Lume `v1.19.4` on 2023 December 04.
This demo was tested in the following environments:
| Lume | Date |
|:---------|:-----------|
| `1.19.4` | 2024-03-16 |
| `2.1.2` | 2024-03-16 |
This example uses the Nunjucks template format. Lume plugins support additional
template formats, including Markdown and JSX.
@ -145,17 +150,24 @@ template formats, including Markdown and JSX.
```bash
mkdir -p sheetjs-lume
cd sheetjs-lume
deno run -Ar https://deno.land/x/lume/init.ts
deno run -Ar https://deno.land/x/lume@v2.1.2/init.ts
```
When prompted, enter the following options:
- `Choose the configuration file format`: select `_config.ts`
- `Do you want to install some plugins now?`: select `Yes`
- `Select the plugins to install`: scroll down, select `sheets`, and submit
- `Select the plugins to install`: select `sheets` and `nunjucks`
- `Do you want to setup a CMS?`: select `Maybe later`
The project will be configured and modules will be installed.
:::note pass
The `nunjucks` plugin was included by default in Lume version 1.
:::
2) Download <https://sheetjs.com/pres.xlsx> and place in a `_data` subfolder:
```bash

@ -1,7 +1,7 @@
---
title: Electron
pagination_prev: demos/mobile/index
pagination_next: demos/data/index
pagination_next: demos/cli/index
sidebar_position: 1
sidebar_custom_props:
summary: Embedded NodeJS + Chromium

@ -1,7 +1,7 @@
---
title: NW.js
pagination_prev: demos/mobile/index
pagination_next: demos/data/index
pagination_next: demos/cli/index
sidebar_position: 2
sidebar_custom_props:
summary: Embedded Chromium + NodeJS

@ -3,7 +3,7 @@ title: Spreadsheet-Powered Wails Apps
sidebar_label: Wails
description: Build data-intensive desktop apps using Wails. Seamlessly integrate spreadsheets into your app using SheetJS. Modernize Excel-powered business processes with confidence.
pagination_prev: demos/mobile/index
pagination_next: demos/data/index
pagination_next: demos/cli/index
sidebar_position: 3
sidebar_custom_props:
summary: Webview + Go Backend

@ -3,7 +3,7 @@ title: Data Wrangling in Tauri Apps
sidebar_label: Tauri
description: Build data-intensive desktop apps using Tauri. Seamlessly integrate spreadsheets into your app using SheetJS. Modernize Excel-powered business processes with confidence.
pagination_prev: demos/mobile/index
pagination_next: demos/data/index
pagination_next: demos/cli/index
sidebar_position: 4
sidebar_custom_props:
summary: Webview + Rust Backend

@ -3,7 +3,7 @@ title: Data Munging in NeutralinoJS
sidebar_label: NeutralinoJS
description: Build data-intensive desktop apps using NeutralinoJS. Seamlessly integrate spreadsheets into your app using SheetJS. Quickly modernize Excel-powered business processes.
pagination_prev: demos/mobile/index
pagination_next: demos/data/index
pagination_next: demos/cli/index
sidebar_position: 5
sidebar_custom_props:
summary: Webview + Lightweight Extensions

@ -3,7 +3,7 @@ title: Sheets on the Desktop with React Native
sidebar_label: React Native
description: Build data-intensive desktop apps with React Native. Seamlessly integrate spreadsheets into your app using SheetJS. Securely process and generate Excel files at the desk.
pagination_prev: demos/mobile/index
pagination_next: demos/data/index
pagination_next: demos/cli/index
sidebar_position: 6
sidebar_custom_props:
summary: Native Components with React

@ -1,4 +1,4 @@
{
"label": "Desktop and CLI Tools",
"label": "Desktop Apps",
"position": 19
}

@ -1,7 +1,7 @@
---
title: Desktop and CLI Tools
title: Desktop Applications
pagination_prev: demos/mobile/index
pagination_next: demos/data/index
pagination_next: demos/cli/index
---
import DocCardList from '@theme/DocCardList';
@ -40,16 +40,4 @@ Frameworks like React Native generate applications that use native UI elements.
## Command-Line Tools
Command-line tools bundle a JavaScript engine and a system runtime. The runtime
provides low-level access to computer resources.
Demos for common command-line tools are included in separate pages:
<ul>{useCurrentSidebarCategory().items.filter(item => item.customProps?.cli).map((item, index) => {
const listyle = (item.customProps?.icon) ? {
listStyleImage: `url("${item.customProps.icon}")`
} : {};
return (<li style={listyle} {...(item.customProps?.class ? {className: item.customProps.class}: {})}>
<a href={item.href}>{item.label}</a>{item.customProps?.summary && (" - " + item.customProps.summary)}
</li>);
})}</ul>
**[The exposition has been moved to a separate page.](/docs/demos/cli)**

@ -0,0 +1,346 @@
---
title: NodeJS SEA
pagination_prev: demos/desktop/index
pagination_next: demos/data/index
sidebar_custom_props:
summary: Single Executable Applications
---
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
NodeJS "Single Executable Applications"[^1] are standalone CLI tools that embed
bundled scripts in a special standalone copy of the NodeJS binary.
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
This demo uses NodeJS SEA and SheetJS to create a standalone CLI tool for
parsing spreadsheets and generating CSV rows.
:::info pass
It is strongly recommended to install NodeJS on systems using SheetJS libraries
in command-line tools. This workaround should only be considered if a standalone
binary is considered desirable.
:::
:::caution NodeJS SEA support is considered experimental.
Great open source software grows with user tests and reports. Any issues should
be reported to the NodeJS single-executable project for further diagnosis.
:::
## Integration Details
The [SheetJS NodeJS module](/docs/getting-started/installation/nodejs) can be
required from NodeJS SEA base scripts.
:::info pass
**NodeJS SEA does not support ECMAScript Modules!**
A CommonJS script is conveniently included in the SheetJS NodeJS module package.
:::
At a high level, single-executable applications are constructed in four steps:
1) Pre-process an existing NodeJS script, creating a SEA bundle.
2) Copy the NodeJS binary and remove any signatures.
3) Inject the SEA bundle into the unsigned NodeJS binary.
4) Re-sign the binary.
:::note pass
macOS and Windows enforce digital signatures. Both operating systems will warn
users if a signed program is modified.
Existing signatures should be removed *before* injecting the SEA bundle. After
injecting the SEA bundle, the binary should be resigned.
:::
### Script Requirements
Scripts that exclusively use SheetJS libraries and NodeJS built-in modules can
be bundled using NodeJS SEA. Due to limitations in the SEA bundler, a special
`require` function must be created manually:
```js
const { createRequire } = require('node:module');
require = createRequire(__filename);
const { readFile, utils } = require("xlsx");
```
For example, the following script accepts one command line argument, parses the
specified file using the SheetJS `readFile` method[^2], generates CSV text from
the first worksheet using `sheet_to_csv`[^3], and prints to terminal:
```js title="sheet2csv.js"
// For NodeJS SEA, the CommonJS `require` must be used
const { createRequire } = require('node:module');
require = createRequire(__filename);
const { readFile, utils } = require("xlsx");
// argv[2] is the first argument to the script
const filename = process.argv[2];
// read file
const wb = readFile(filename);
// generate CSV of first sheet
const ws = wb.Sheets[wb.SheetNames[0]];
const csv = utils.sheet_to_csv(ws);
// print to terminal
console.log(csv);
```
### SEA Bundles
SEA Bundles are blobs that represent the script and supporting libraries.
#### Configuration
SEA configuration is specified using a special JSON file. Assuming no special
assets are bundled with the script, there are two relevant fields:
- `main` is a relative path to the entry script.
- `output` is a relative path to the output file (typically ending in `.blob`)
For example, the following configuration specifies `sheet2csv.js` as the entry
script and `sheet2csv.blob` as the output blob:
```js title="sheet2csv.json"
{
"main": "sheet2csv.js",
"output": "sheet2csv.blob"
}
```
#### Construction
The main `node` program, with the command-line flag `--experimental-sea-config`,
will generate a SEA bundle:
```bash
node --experimental-sea-config sheet2csv.json
```
The bundle will be written to the file specified in the `output` field of the
SEA configuration file.
#### Injection
A special `postject` utility is used to add the SEA bundle to the NodeJS binary.
The specific command depends on the operating system.
On macOS, assuming the copy of the NodeJS binary is named `sheet2csv` and the
SEA bundle is named `sheet2csv.blob`, the following command injects the bundle:
```bash
npx -y postject --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 --macho-segment-name NODE_SEA sheet2csv NODE_SEA_BLOB sheet2csv.blob
```
## Complete Example
:::note Tested Deployments
This demo was tested in the following deployments:
| Architecture | NodeJS | Date |
|:-------------|:----------|:-----------|
| `darwin-x64` | `20.11.1` | 2024-03-17 |
| `linux-x64` | `20.11.1` | 2024-03-18 |
:::
0) Ensure NodeJS version 20 or later is installed.
:::note pass
To display the current version, run the following command:
```bash
node --version
```
The major version number starts after the `v` and ends before the first `.`
If the version number is 19 or earlier, upgrade NodeJS before proceeding.
:::
### Project Setup
1) Create a new project folder:
```bash
mkdir sheetjs-sea
cd sheetjs-sea
npm init -y
```
2) Save the [contents of the `sheet2csv.js` code block](#script-requirements)
to `sheet2csv.js` in the project folder.
3) Install the SheetJS dependency:
<Tabs groupId="pm">
<TabItem value="npm" label="npm">
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
<TabItem value="pnpm" label="pnpm">
<CodeBlock language="bash">{`\
pnpm install https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
<TabItem value="yarn" label="Yarn" default>
<CodeBlock language="bash">{`\
yarn add https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
</TabItem>
</Tabs>
### Script Test
:::caution pass
Before building the standalone app, the base script should be tested using the
local NodeJS platform.
:::
4) Download the test file <https://sheetjs.com/pres.numbers>:
```bash
curl -LO https://sheetjs.com/pres.numbers
```
5) Run the script and pass `pres.numbers` as the first argument:
```bash
node sheet2csv.js pres.numbers
```
The script should display CSV contents from the first sheet:
```
Name,Index
Bill Clinton,42
GeorgeW Bush,43
Barack Obama,44
Donald Trump,45
Joseph Biden,46
```
### SEA Bundle
6) Save the [contents of the `sheet2csv.json` code block](#configuration) to
`sheet2csv.json` in the project folder.
7) Generate the SEA bundle:
```bash
node --experimental-sea-config sheet2csv.json
```
### SEA Injection
8) Create a local copy of the NodeJS binary. On macOS and Linux:
```bash
cp `which node` sheet2csv
```
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="MacOS">
9) Remove the code signature.
```bash
codesign --remove-signature ./sheet2csv
```
</TabItem>
<TabItem value="linux-x64" label="Linux">
9) Observe that many Linux distributions do not enforce code signatures.
</TabItem>
</Tabs>
10) Inject the SEA bundle.
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="MacOS">
```bash
npx -y postject --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 --macho-segment-name NODE_SEA sheet2csv NODE_SEA_BLOB sheet2csv.blob
```
11) Resign the binary. The following command performs macOS ad-hoc signing:
```bash
codesign -s - ./sheet2csv
```
</TabItem>
<TabItem value="linux-x64" label="Linux">
```bash
npx -y postject --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 sheet2csv NODE_SEA_BLOB sheet2csv.blob
```
11) Observe that many Linux distributions do not enforce code signatures.
</TabItem>
</Tabs>
### Standalone Test
12) Run the command and pass `pres.numbers` as the first argument:
```bash
./sheet2csv pres.numbers
```
The program should display the same CSV contents as the script (from step 5)
<Tabs groupId="triple">
<TabItem value="darwin-x64" label="MacOS">
13) Validate the binary signature. On macOS:
```bash
codesign -dv ./sheet2csv
```
Inspecting the output, the following line confirms ad-hoc signing was used:
```
Signature=adhoc
```
</TabItem>
<TabItem value="linux-x64" label="Linux">
13) Observe that many Linux distributions do not enforce code signatures.
</TabItem>
</Tabs>
[^1]: See ["Single Executable Applications"](https://nodejs.org/api/single-executable-applications.html) in the NodeJS documentation.
[^2]: See [`readFile` in "Reading Files"](/docs/api/parse-options)
[^3]: See [`sheet_to_csv` in "CSV and Text"](/docs/api/utilities/csv#delimiter-separated-output)

@ -0,0 +1,151 @@
---
title: Deno Compiler
pagination_prev: demos/desktop/index
pagination_next: demos/data/index
sidebar_custom_props:
summary: Deno Standalone Binaries
---
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
[Deno](https://docs.deno.com/runtime/manual/tools/compiler) is a JavaScript
runtime with support for compiling scripts into self-contained executables.
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
This demo uses the Deno compiler and SheetJS to create a standalone CLI tool for
parsing spreadsheets and generating CSV rows.
:::info pass
It is strongly recommended to install Deno on systems using SheetJS libraries in
command-line tools. This workaround should only be considered if a standalone
binary is considered desirable.
:::
:::caution Deno support is considered experimental.
Great open source software grows with user tests and reports. Any issues should
be reported to the Deno project for further diagnosis.
:::
## Integration Details
The [SheetJS Deno module](/docs/getting-started/installation/deno) can be
imported from Deno scripts.
`deno compile` generates a standalone executable that includes the entire JS
runtime as well as user JS code.
### Script Requirements
Scripts that exclusively use SheetJS libraries and Deno built-in modules can be
bundled using `deno compile`. The ESM script should be imported directly:
<CodeBlock language="ts">{`\
// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts"
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs';`}
</CodeBlock>
For example, the following script accepts one command line argument, parses the
specified file using the SheetJS `readFile` method[^1], generates CSV text from
the first worksheet using `sheet_to_csv`[^2], and prints to terminal:
<CodeBlock language="ts" title="sheet2csv.ts">{`\
// @deno-types="https://cdn.sheetjs.com/xlsx-${current}/package/types/index.d.ts"
import * as XLSX from 'https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs';
import * as cptable from 'https://cdn.sheetjs.com/xlsx-${current}/package/dist/cpexcel.full.mjs';
XLSX.set_cptable(cptable);
\n\
/* Deno.args[0] is the first argument to the script */
const filename = Deno.args[0];
\n\
/* read file */
const wb = XLSX.readFile(filename);
\n\
/* generate CSV of first sheet */
const ws = wb.Sheets[wb.SheetNames[0]];
const csv = utils.sheet_to_csv(ws);
\n\
/* print to terminal */
console.log(csv);`}
</CodeBlock>
### Deno Permissions
The same permissions that apply to normal Deno scripts apply to the compiler:
- The `--allow-read` option must be specified to allow the program to read files
from the filesystem with the SheetJS `readFile` [^3] method.
- The `--allow-write` option must be specified to allow the program to write
files to the filesystem with the SheetJS `writeFile` [^4] method.
- The `--allow-net` option must be specified to allow the program to download
and upload spreadsheets.
More flags can be found in the official permissions list[^5]
## Complete Example
:::note Tested Deployments
This demo was last tested in the following deployments:
| Architecture | Deno | Date |
|:-------------|:---------|:-----------|
| `darwin-x64` | `1.41.3` | 2024-03-15 |
| `darwin-arm` | `1.37.2` | 2023-10-18 |
| `win10-x64` | `1.37.1` | 2023-10-09 |
| `win11-x64` | `1.37.2` | 2023-10-14 |
| `win11-arm` | `1.38.4` | 2023-12-01 |
| `linux-x64` | `1.41.3` | 2024-03-18 |
| `linux-arm` | `1.38.4` | 2023-12-01 |
:::
0) Install Deno.[^6]
1) Download the test file <https://sheetjs.com/pres.numbers>:
```bash
curl -LO https://sheetjs.com/pres.numbers
```
2) Test the script with `deno run`:
```bash
deno run -r --allow-read https://docs.sheetjs.com/cli/sheet2csv.ts pres.numbers
```
The script should display CSV contents from the first sheet:
```
Name,Index
Bill Clinton,42
GeorgeW Bush,43
Barack Obama,44
Donald Trump,45
Joseph Biden,46
```
3) Compile and run `sheet2csv`:
```bash
deno compile -r --allow-read https://docs.sheetjs.com/cli/sheet2csv.ts
./sheet2csv pres.numbers
```
The program should display the same CSV contents as the script (from step 2)
[^1]: See [`readFile` in "Reading Files"](/docs/api/parse-options)
[^2]: See [`sheet_to_csv` in "CSV and Text"](/docs/api/utilities/csv#delimiter-separated-output)
[^3]: See [`readFile` in "Reading Files"](/docs/api/parse-options)
[^4]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
[^5]: See ["Permissions list"](https://docs.deno.com/runtime/manual/basics/permissions#permissions-list) in the official Deno documentation
[^6]: [The official instructions](https://docs.deno.com/runtime/manual/getting_started/installation) cover most platforms. Deno does not provide official Linux ARM64 builds, but [there are unofficial community builds](https://github.com/LukeChannings/deno-arm64).

@ -0,0 +1,4 @@
{
"label": "Command-Line Tools",
"position": 20
}

@ -1,21 +1,47 @@
---
title: Command-Line Tools
pagination_prev: demos/mobile/index
pagination_prev: demos/desktop/index
pagination_next: demos/data/index
sidebar_custom_props:
cli: true
---
import current from '/version.js';
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import CodeBlock from '@theme/CodeBlock';
import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
With the availability of JS engines and the success of server-side platforms,
it is feasible to build command-line tools for various workflows.
it is possible to build standalone command-line tools from JavaScript code.
This demo covers a number of strategies for building standalone processors. The
goal is to generate CSV output from an arbitrary spreadsheet file.
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
This demo covers a number of strategies for building standalone spreadsheet
processors. The ultimate goal is to use SheetJS libraries to generate CSV output
from arbitrary spreadsheet files. The generated command-line tool will accept an
argument, parse the specified workbook, and print CSV rows to the terminal.
>**Sample terminal session**
```bash
$ xlsx-cli.exe pres.numbers
Name,Index
Bill Clinton,42
GeorgeW Bush,43
Barack Obama,44
Donald Trump,45
Joseph Biden,46
```
Demos for common standalone CLI tools are included in separate pages:
<ul>{useCurrentSidebarCategory().items.map((item, index) => {
const listyle = (item.customProps?.icon) ? {
listStyleImage: `url("${item.customProps.icon}")`
} : {};
return (<li style={listyle} {...(item.customProps?.class ? {className: item.customProps.class}: {})}>
<a href={item.href}>{item.label}</a>{item.customProps?.summary && (" - " + item.customProps.summary)}
</li>);
})}</ul>
:::tip pass
@ -25,6 +51,18 @@ translating files between supported spreadsheet file formats.
:::
:::caution pass
For most common deployment scenarios, it is possible to install a server-side
platform such as [NodeJS](/docs/getting-started/installation/nodejs).
**It is strongly recommended to use a dedicated platform when possible.**
The standalone programs generated in this demo are useful when a dedicated
server-side scripting platform cannot be installed on the target computer.
:::
## NodeJS
There are a few popular tools for compiling NodeJS scripts to CLI programs.
@ -309,7 +347,7 @@ This demo was last tested in the following deployments:
| `darwin-arm` | `11.8.172.13` | `0.79.2` | 2023-10-18 |
| `win10-x64` | `11.8.172.13` | `0.79.2` | 2023-10-09 |
| `win11-x64` | `11.8.172.13` | `0.79.2` | 2023-10-14 |
| `linux-x64` | `12.0.267.8` | `0.83.1` | 2024-01-26 |
| `linux-x64` | `12.3.219.9` | `0.88.0` | 2024-03-18 |
| `linux-arm` | `12.0.267.8` | `0.82.0` | 2023-12-01 |
:::
@ -400,54 +438,9 @@ mv target/release/sheet2csv.exe .
</TabItem>
</Tabs>
## Deno
#### Deno
`deno compile` generates a standalone executable that includes the entire JS
runtime as well as user JS code.
When compiling, the `--allow-read` option must be specified to allow the script
to read files from the filesystem with `Deno.readFileSync`.
<https://docs.sheetjs.com/cli/sheet2csv.ts> can be compiled and run from Deno.
:::note Tested Deployments
This demo was last tested in the following deployments:
| Architecture | Version | Date |
|:-------------|:---------|:-----------|
| `darwin-x64` | `1.41.3` | 2024-03-15 |
| `darwin-arm` | `1.37.2` | 2023-10-18 |
| `win10-x64` | `1.37.1` | 2023-10-09 |
| `win11-x64` | `1.37.2` | 2023-10-14 |
| `win11-arm` | `1.38.4` | 2023-12-01 |
| `linux-x64` | `1.39.4` | 2024-01-22 |
| `linux-arm` | `1.38.4` | 2023-12-01 |
:::
0) Install Deno.[^2]
1) Download the test file <https://sheetjs.com/pres.numbers>:
```bash
curl -LO https://sheetjs.com/pres.numbers
```
2) Test the script with `deno run`:
```bash
deno run -r --allow-read https://docs.sheetjs.com/cli/sheet2csv.ts pres.numbers
```
If this worked, the program will print a CSV of the first worksheet.
3) Compile and run `sheet2csv`:
```bash
deno compile -r --allow-read https://docs.sheetjs.com/cli/sheet2csv.ts
./sheet2csv pres.numbers
```
**[The exposition has been moved to a separate page.](/docs/demos/cli/deno)**
## Dedicated Engines
@ -459,5 +452,4 @@ The following demos for JS engines produce standalone programs:
- [Goja](/docs/demos/engines/goja)
- [JavaScriptCore](/docs/demos/engines/jsc)
[^1]: Downloads can be found [at the main NASM project website](https://www.nasm.us/)
[^2]: [The official instructions](https://docs.deno.com/runtime/manual/getting_started/installation) cover most platforms. Deno does not provide official Linux ARM64 builds, but [there are unofficial community builds](https://github.com/LukeChannings/deno-arm64).
[^1]: Downloads can be found [at the main NASM project website](https://www.nasm.us/)

@ -1,6 +1,6 @@
---
title: SQL Connectors
pagination_prev: demos/desktop/index
pagination_prev: demos/cli/index
pagination_next: demos/local/index
sidebar_custom_props:
sql: true

@ -1,7 +1,7 @@
---
title: Sheets with SQLite
sidebar_label: SQLite
pagination_prev: demos/desktop/index
pagination_prev: demos/cli/index
pagination_next: demos/local/index
sidebar_custom_props:
sql: true

@ -1,6 +1,6 @@
---
title: Knex SQL Builder
pagination_prev: demos/desktop/index
pagination_prev: demos/cli/index
pagination_next: demos/local/index
sidebar_custom_props:
sql: true

@ -1,7 +1,7 @@
---
title: Sheets with PostgreSQL
sidebar_label: PostgreSQL
pagination_prev: demos/desktop/index
pagination_prev: demos/cli/index
pagination_next: demos/local/index
sidebar_custom_props:
sql: true

@ -1,7 +1,7 @@
---
title: Sheets with MariaDB and MySQL
sidebar_label: MariaDB / MySQL
pagination_prev: demos/desktop/index
pagination_prev: demos/cli/index
pagination_next: demos/local/index
sidebar_custom_props:
sql: true

@ -1,7 +1,7 @@
---
title: Sheets with AlaSQL
sidebar_label: AlaSQL
pagination_prev: demos/desktop/index
pagination_prev: demos/cli/index
pagination_next: demos/local/index
sidebar_custom_props:
sql: true

@ -1,7 +1,7 @@
---
title: Sheets with MongoDB
sidebar_label: MongoDB
pagination_prev: demos/desktop/index
pagination_prev: demos/cli/index
pagination_next: demos/local/index
sidebar_custom_props:
type: document

@ -2,7 +2,7 @@
title: Redis Databases Wrapped in Sheets
sidebar_label: Redis
description: Store complex datasets in Redis. Seamlessly save data to spreadsheets and read data from sheets using SheetJS. Enable Excel spreadsheet experts to update content.
pagination_prev: demos/desktop/index
pagination_prev: demos/cli/index
pagination_next: demos/local/index
sidebar_custom_props:
type: nosql

@ -1,7 +1,7 @@
---
title: Sheets in PouchDB
sidebar_label: PouchDB
pagination_prev: demos/desktop/index
pagination_prev: demos/cli/index
pagination_next: demos/local/index
sidebar_custom_props:
type: nosql

@ -1,6 +1,6 @@
---
title: Databases and Stores
pagination_prev: demos/desktop/index
pagination_prev: demos/cli/index
pagination_next: demos/local/index
---

@ -28,7 +28,8 @@ Some snippets are also available in the "Common Use Cases" section:
Other demos cover APIs for local file access on special platforms:
- ["iOS and Android Apps"](/docs/demos/mobile/) covers mobile app frameworks
- ["Desktop and CLI Tools"](/docs/demos/desktop/) covers desktop apps and CLIs
- ["Desktop Apps"](/docs/demos/desktop/) covers desktop apps
- ["Command-Line Tools"](/docs/demos/cli) covers standalone command-line tools
:::

@ -33,7 +33,7 @@ This demo was last tested by SheetJS users on 2023 October 18.
## Integration Details
The [SheetJS Deno module](/docs/getting-started/installation/nodejs) can be
The [SheetJS Deno module](/docs/getting-started/installation/deno) can be
imported from Deno Deploy server scripts.
### Supported Frameworks

@ -197,7 +197,7 @@ SheetJSImportFileEE["pres.numbers"]
### Command-Line Tools
The ["Command-Line Tools" demo](/docs/demos/desktop/cli) creates `xlsx-cli`, a
The ["Command-Line Tools" demo](/docs/demos/cli) creates `xlsx-cli`, a
command-line tool that reads a spreadsheet file and generates CSV rows from the
first worksheet.
@ -354,5 +354,5 @@ data = SheetJSImportURL["https://sheetjs.com/pres.numbers"]
[^11]: See [`ImportString`](https://reference.wolfram.com/language/ref/ImportString.html) in the Mathematica documentation.
[^12]: A [`Dataset`](https://reference.wolfram.com/language/ref/Dataset.html) will be created when using the [`"Dataset"` element in `ImportString`](https://reference.wolfram.com/language/ref/format/CSV.html)
[^13]: See [`HeaderLines`](https://reference.wolfram.com/language/ref/HeaderLines.html) in the Mathematica documentation.
[^14]: See ["Command-line Tools"](/docs/demos/desktop/cli) for more details.
[^14]: See ["Command-line Tools"](/docs/demos/cli) for more details.
[^15]: Mathematica 11 introduced new methods including [`URLRead`](https://reference.wolfram.com/language/ref/URLRead.html).

@ -55,7 +55,7 @@ loaded in NodeJS scripts and bundled in standalone command-line tools.
### Command-Line Tools
The ["Command-Line Tools" demo](/docs/demos/desktop/cli) creates `xlsx-cli`, a
The ["Command-Line Tools" demo](/docs/demos/cli) creates `xlsx-cli`, a
command-line tool that reads a spreadsheet file and generates output. The
examples in the "NodeJS" section are able to generate XLSX spreadsheets using
the `--xlsx` command line flag:
@ -265,5 +265,5 @@ matlab -batch SheetJSMATLAB
[^4]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
[^5]: See [`system`](https://www.mathworks.com/help/matlab/ref/system.html) in the MATLAB documentation.
[^6]: See ["MATLAB Operators and Special Characters](https://www.mathworks.com/help/matlab/matlab_prog/matlab-operators-and-special-characters.html) in the MATLAB documentation.
[^7]: See ["Command-line Tools"](/docs/demos/desktop/cli) for more details.
[^7]: See ["Command-line Tools"](/docs/demos/cli) for more details.

@ -106,7 +106,7 @@ in the [issue tracker](https://git.sheetjs.com/sheetjs/docs.sheetjs.com/issues)
### Platforms and Integrations
- [`Command-Line Tools`](/docs/demos/desktop/cli)
- [`Command-Line Tools`](/docs/demos/cli)
- [`NodeJS Server-Side Processing`](/docs/demos/net/server#nodejs)
- [`Deno Server-Side Processing`](/docs/demos/net/server#deno)
- [`Headless Automation`](/docs/demos/net/headless)

@ -1,8 +1,10 @@
---
title: Dates and Times
sidebar_position: 1
---
# Dates and Times
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
<details>
<summary><b>File Format Support</b> (click to show)</summary>
@ -70,7 +72,10 @@ recommended to [upgrade](/docs/getting-started/installation/).
:::
The following example exports the current time to XLSX spreadsheet. The time
shown on this page will be the time displayed in Excel
shown on this page will be the time displayed in Excel.
<Tabs groupId="live">
<TabItem value="react" label="React (Live Demo)">
```jsx live
function SheetJSNow() {
@ -87,8 +92,7 @@ function SheetJSNow() {
ws["!cols"] = [{wch: 20}];
/* generate workbook and export */
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
const wb = XLSX.utils.book_new(ws, "Sheet1");
XLSX.writeFile(wb, "SheetJSNow.xlsx");
}, []);
return ( <>
@ -97,10 +101,71 @@ function SheetJSNow() {
<button onClick={()=>setDate(new Date())}>Refresh</button>
</p>
<button onClick={xport}>Export XLSX</button>
</> )
</> );
}
```
</TabItem>
<TabItem value="js" label="JavaScript (Explanation)">
:::note pass
1) Create a new Date object and set milliseconds to 0 (to avoid date rounding):
```js
/* starting date */
const date = new Date();
/* to avoid confusion, set milliseconds to 0 */
date.setMilliseconds(0);
```
2) Construct an array of arrays to store the date. It will be placed in cell A1:
```js
/* generate array of arrays */
const aoa = [[date]];
```
3) [Create a worksheet](/docs/api/utilities/array#array-of-arrays-input):
```js
/* generate workbook */
const ws = XLSX.utils.aoa_to_sheet(aoa, {dense: true});
```
4) Adjust the date format using a [custom number format](/docs/csf/features/nf):
```js
/* set cell A1 number format */
ws["!data"][0][0].z = "yyyy-mm-dd hh:mm:ss"
```
5) Adjust the [column width](/docs/csf/features/colprops)
```js
/* adjust column width */
ws["!cols"] = [{wch: 20}];
```
6) [Create a workbook](/docs/api/utilities/wb):
```js
/* create workbook object */
const wb = XLSX.utils.book_new(ws, "Sheet1");
```
7) [Write XLSX file](/docs/api/write-options):
```js
/* generate XLSX workbook and attempt to download */
XLSX.writeFile(wb, "SheetJSNow.xlsx");
```
:::
</TabItem>
</Tabs>
## How Spreadsheets Understand Time
Excel stores dates as numbers. When displaying dates, the format code should
@ -500,3 +565,71 @@ function SSFIsDate() {
```
</details>
## How JSON and APIs Understand Time
JSON does not have a native representation for JavaScript Date objects.
Starting from a Date object, the `JSON.stringify` method will encode the object
as a ISO 8601 date string. Applying `JSON.parse` to the result will return the
string rather than a proper Date object.
```mermaid
flowchart LR
ws(("new Date#40;#41;"\nObject))
jstr[["'#quot;2001-01-01T00:00:00.000Z#quot;'"\nEncoded String]]
js[["#quot;2001-01-01T00:00:00.000Z#quot;"\nJavaScript String]]
ws --> |JSON\nstringify| jstr
jstr --> |JSON.parse\n\n| js
js --> |\nJSON.stringify| jstr
```
SheetJS utility functions will not try to interpret those strings as dates.
Instead, the strings will be translated to text.
In the following example, the "ISO Text" data will be converted to a string cell
while the "Date Obj" data will be converted to a spreadsheet date.
```jsx live
function SheetJSONDates() { return ( <button onClick={() => {
const aoa = [
["ISO Text", "2001-01-01T00:00:00.000Z"], // B1 will be text
["Date Obj", new Date("2001-01-01T00:00:00.000Z")] // B2 will be a date
];
const ws = XLSX.utils.aoa_to_sheet(aoa);
const wb = XLSX.utils.book_new(ws, "Data");
XLSX.writeFile(wb, "SheetJSONDates.xlsx");
}}>Click to Export Sample Data</button> ); }
```
:::caution pass
Many API wrapper libraries return dates as strings instead of Date objects.
If the SheetJS operations generate string cells, review the documentation for
the wrapper library to ensure the other library is properly handling dates.
:::
### Fixing Arrays of Objects
Many APIs will return data as JSON objects. When particular fields are known to
contain date strings, they can be manually fixed.
For example, the [Export Tutorial](/docs/getting-started/examples/export) makes
a final array of objects with birthdays stored as strings:
```js
const rows = [
{ name: "George Washington", birthday: "1732-02-22" },
{ name: "John Adams", birthday: "1735-10-19" },
// ... one row per President
];
```
If this dataset is exported, the `birthday` column will contain raw text values.
A single `Array#map` operation can create a fixed dataset:
```js
const new_rows = rows.map(({birthday, ...rest}) => ({birthday: new Date(birthday), ...rest}))
```

@ -269,9 +269,10 @@ const config = {
{ from: '/docs/demos/data/storageapi', to: '/docs/demos/local/storageapi/' },
{ from: '/docs/demos/data/websql', to: '/docs/demos/local/websql/' },
/* desktop */
{ from: '/docs/demos/cli', to: '/docs/demos/desktop/cli/' },
{ from: '/docs/getting-started/demos/cli', to: '/docs/demos/desktop/cli/' },
{ from: '/docs/getting-started/demos/desktop', to: '/docs/demos/desktop/' },
/* cli */
{ from: '/docs/getting-started/demos/cli', to: '/docs/demos/cli/' },
{ from: '/docs/demos/desktop/cli', to: '/docs/demos/cli/' },
/* bigdata */
{ from: '/docs/demos/worker', to: '/docs/demos/bigdata/worker/' },
{ from: '/docs/demos/stream', to: '/docs/demos/bigdata/stream/' },