forked from sheetjs/docs.sheetjs.com
		
	node-sea
This commit is contained in:
		
							parent
							
								
									1480a3e021
								
							
						
					
					
						commit
						e3ca16d997
					
				| @ -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)** | ||||
|  | ||||
							
								
								
									
										346
									
								
								docz/docs/03-demos/20-cli/09-nodesea.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										346
									
								
								docz/docs/03-demos/20-cli/09-nodesea.md
									
									
									
									
									
										Normal file
									
								
							| @ -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) | ||||
							
								
								
									
										151
									
								
								docz/docs/03-demos/20-cli/23-deno.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										151
									
								
								docz/docs/03-demos/20-cli/23-deno.md
									
									
									
									
									
										Normal file
									
								
							| @ -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). | ||||
							
								
								
									
										4
									
								
								docz/docs/03-demos/20-cli/_category_.json
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										4
									
								
								docz/docs/03-demos/20-cli/_category_.json
									
									
									
									
									
										Normal file
									
								
							| @ -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/' }, | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user