forked from sheetjs/docs.sheetjs.com
react-native mobile refresh
This commit is contained in:
parent
9230a968c3
commit
ad27e3a947
@ -46,11 +46,11 @@ This demo was tested in the following environments:
|
||||
|
||||
| Version | Platform | Date |
|
||||
|:----------|:---------|:-----------|
|
||||
| `0.19.47` | NodeJS | 2023-10-18 |
|
||||
| `0.20.16` | Browser | 2023-12-04 |
|
||||
| `0.20.19` | NodeJS | 2023-10-18 |
|
||||
| `0.21.6` | NodeJS | 2023-10-18 |
|
||||
| `6.14.2` | NodeJS | 2023-12-04 |
|
||||
| `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 |
|
||||
|
||||
:::
|
||||
|
||||
@ -203,7 +203,7 @@ npm init -y
|
||||
1) Install the dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz systemjs@6.14.2`}
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz systemjs@6.14.3`}
|
||||
</CodeBlock>
|
||||
|
||||
2) Download [`SheetJSystem.js`](pathname:///systemjs/SheetJSystem.js) and move
|
||||
@ -215,7 +215,7 @@ curl -LO https://docs.sheetjs.com/systemjs/SheetJSystem.js
|
||||
|
||||
:::info pass
|
||||
|
||||
The script is handles both old-style and new-style SystemJS loaders.
|
||||
The script handles old-style and new-style SystemJS loaders.
|
||||
|
||||
:::
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
title: Sheets in PST Mailboxes
|
||||
sidebar_label: PST Mailboxes
|
||||
pagination_prev: demos/net/server/index
|
||||
pagination_next: demos/net/headless
|
||||
pagination_next: demos/net/headless/index
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
title: Electronic Mail
|
||||
pagination_prev: demos/net/server/index
|
||||
pagination_next: demos/net/headless
|
||||
pagination_next: demos/net/headless/index
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
|
4
docz/docs/03-demos/03-net/08-headless/_category_.json
Normal file
4
docz/docs/03-demos/03-net/08-headless/_category_.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Browser Automation",
|
||||
"position": 8
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
---
|
||||
title: Browser Automation
|
||||
pagination_prev: demos/net/email/index
|
||||
pagination_next: demos/net/dom
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
@ -406,7 +407,7 @@ This demo was tested in the following environments:
|
||||
|:-------------|:----------|:-----------|
|
||||
| `darwin-x64` | `2.1.1` | 2024-03-15 |
|
||||
| `win10-x64` | `2.1.1` | 2024-03-24 |
|
||||
|
||||
| `linux-x64` | `2.1.1` | 2024-03-29 |
|
||||
:::
|
||||
|
||||
1) [Download and extract PhantomJS](https://phantomjs.org/download.html)
|
||||
@ -425,4 +426,30 @@ will be placed in `phantomjs-2.1.1-macosx/bin/` and the command will be:
|
||||
When the script finishes, the file `SheetJSPhantomJS.xlsb` will be created.
|
||||
This file can be opened with Excel.
|
||||
|
||||
:::caution pass
|
||||
|
||||
When this demo was last tested on Linux, there were multiple errors.
|
||||
|
||||
```
|
||||
This application failed to start because it could not find or load the Qt platform plugin "xcb".
|
||||
```
|
||||
|
||||
The environment variable `QT_QPA_PLATFORM=phantom` resolves the issue. There is
|
||||
a different error after assignment:
|
||||
|
||||
```
|
||||
140412268664640:error:25066067:DSO support routines:DLFCN_LOAD:could not load the shared library:dso_dlfcn.c:185:filename(libproviders.so): libproviders.so: cannot open shared object file: No such file or directory
|
||||
140412268664640:error:25070067:DSO support routines:DSO_load:could not load the shared library:dso_lib.c:244:
|
||||
140412268664640:error:0E07506E:configuration file routines:MODULE_LOAD_DSO:error loading dso:conf_mod.c:285:module=providers, path=providers
|
||||
140412268664640:error:0E076071:configuration file routines:MODULE_RUN:unknown module name:conf_mod.c:222:module=providers
|
||||
```
|
||||
|
||||
This error is resolved by ignoring SSL errors. The complete command is:
|
||||
|
||||
```bash
|
||||
env OPENSSL_CONF=/dev/null QT_QPA_PLATFORM=phantom ./phantomjs-2.1.1-linux-x86_64/bin/phantomjs --ignore-ssl-errors=true test.js
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
</details>
|
@ -1,5 +1,6 @@
|
||||
---
|
||||
title: Synthetic DOM
|
||||
pagination_prev: demos/net/headless/index
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
|
@ -141,7 +141,7 @@ Consider the following worksheet:
|
||||
Assuming the file name is `pres.xlsx` and the data is stored in "Sheet1", the
|
||||
following nodes will be created:
|
||||
|
||||
```js
|
||||
```js title="GraphQL Nodes"
|
||||
[
|
||||
{ Name: "Bill Clinton", Index: 42, type: "PresXlsxSheet1" },
|
||||
{ Name: "GeorgeW Bush", Index: 43, type: "PresXlsxSheet1" },
|
||||
@ -155,7 +155,7 @@ The type is a proper casing of the file name concatenated with the sheet name.
|
||||
|
||||
The following query pulls the `Name` and `Index` fields from each row:
|
||||
|
||||
```graphql
|
||||
```graphql title="GraphQL Query to pull Name and Index fields from each row"
|
||||
{
|
||||
allPresXlsxSheet1 { # "all" followed by type
|
||||
edges {
|
||||
@ -172,8 +172,12 @@ The following query pulls the `Name` and `Index` fields from each row:
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was tested on 2023 December 04 against `create-gatsby@3.12.3`. The
|
||||
generated project used `gatsby@5.12.11` and `react@18.2.0`.
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| GatsbyJS | Date |
|
||||
|:---------|:-----------|
|
||||
| `5.12.1` | 2023-12-04 |
|
||||
| `4.25.8` | 2024-03-27 |
|
||||
|
||||
:::
|
||||
|
||||
@ -188,9 +192,26 @@ npx gatsby telemetry --disable
|
||||
1) Create a template site:
|
||||
|
||||
```bash
|
||||
npm init gatsby -- -y sheetjs-gatsby
|
||||
npx gatsby new sheetjs-gatsby
|
||||
```
|
||||
|
||||
:::info pass
|
||||
|
||||
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:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/gatsbyjs/gatsby-starter-default sheetjs-gatsby
|
||||
cd sheetjs-gatsby
|
||||
git checkout 6bc4466090845f20650117b3d27e68e6e46dc8d5
|
||||
npm install
|
||||
cd ..
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
2) Follow the on-screen instructions for starting the local development server:
|
||||
|
||||
```bash
|
||||
@ -222,6 +243,18 @@ npm i --save gatsby-transformer-excel gatsby-source-filesystem
|
||||
`}
|
||||
</CodeBlock>
|
||||
|
||||
:::info pass
|
||||
|
||||
For older versions of Gatsby, older versions of the dependencies must be used.
|
||||
|
||||
For GatsbyJS 4, the plugin version numbers align with the Gatsby version:
|
||||
|
||||
```bash
|
||||
npm i --save gatsby-transformer-excel@4 gatsby-source-filesystem@4
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
5) Make a `src/data` directory, download <https://sheetjs.com/pres.xlsx>, and
|
||||
move the downloaded file into the new folder:
|
||||
|
||||
@ -253,6 +286,27 @@ module.exports = {
|
||||
}
|
||||
```
|
||||
|
||||
:::note pass
|
||||
|
||||
If the `plugins` array exists, the two plugins should be added at the beginning:
|
||||
|
||||
```js title="gatsby-config.js (add highlighted lines)"
|
||||
plugins: [
|
||||
// highlight-start
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
name: `data`,
|
||||
path: `${__dirname}/src/data/`,
|
||||
},
|
||||
},
|
||||
`gatsby-transformer-excel`,
|
||||
// highlight-end
|
||||
// ...
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Stop and restart the development server process (`npm run develop`).
|
||||
|
||||
### GraphiQL test
|
||||
@ -322,7 +376,7 @@ displayed JSON is the data that the component receives:
|
||||
|
||||
9) Change `PageComponent` to display a table based on the data:
|
||||
|
||||
```jsx title="src/pages/pres.js"
|
||||
```jsx title="src/pages/pres.js (replace PageComponent)"
|
||||
import { graphql } from "gatsby"
|
||||
import * as React from "react"
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -159,6 +159,7 @@ This demo was tested in the following deployments:
|
||||
| Architecture | NodeJS | Date |
|
||||
|:-------------|:----------|:-----------|
|
||||
| `darwin-x64` | `20.11.1` | 2024-03-17 |
|
||||
| `win10-x64` | `20.12.0` | 2024-03-26 |
|
||||
| `linux-x64` | `20.11.1` | 2024-03-18 |
|
||||
|
||||
:::
|
||||
@ -224,7 +225,7 @@ local NodeJS platform.
|
||||
4) Download the test file <https://sheetjs.com/pres.numbers>:
|
||||
|
||||
```bash
|
||||
curl -LO https://sheetjs.com/pres.numbers
|
||||
curl -o pres.numbers https://sheetjs.com/pres.numbers
|
||||
```
|
||||
|
||||
5) Run the script and pass `pres.numbers` as the first argument:
|
||||
@ -257,24 +258,54 @@ node --experimental-sea-config sheet2csv.json
|
||||
|
||||
### SEA Injection
|
||||
|
||||
8) Create a local copy of the NodeJS binary. On macOS and Linux:
|
||||
8) Create a local copy of the NodeJS binary:
|
||||
|
||||
<Tabs groupId="triple">
|
||||
<TabItem value="darwin-x64" label="MacOS">
|
||||
|
||||
```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="win10-x64" label="Windows">
|
||||
|
||||
In PowerShell, the `Get-Command` command displays the location to `node.exe`:
|
||||
|
||||
```powershell
|
||||
PS C:\sheetjs-sea> get-command node
|
||||
|
||||
CommandType Name Version Source
|
||||
----------- ---- ------- ------
|
||||
Application node.exe 20.12.0.0 C:\Program Files\nodejs\node.exe
|
||||
|
||||
```
|
||||
|
||||
Copy the program (listed in the "Source" column) to `sheet2csv.exe`:
|
||||
|
||||
```powershell
|
||||
PS C:\sheetjs-sea> copy "C:\Program Files\nodejs\node.exe" sheet2csv.exe
|
||||
```
|
||||
|
||||
9) Remove the code signature.
|
||||
|
||||
```powershell
|
||||
signtool remove /s .\sheet2csv.exe
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="linux-x64" label="Linux">
|
||||
|
||||
```bash
|
||||
cp `which node` sheet2csv
|
||||
```
|
||||
|
||||
9) Observe that many Linux distributions do not enforce code signatures.
|
||||
|
||||
</TabItem>
|
||||
@ -293,6 +324,29 @@ npx -y postject --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 -
|
||||
|
||||
```bash
|
||||
codesign -s - ./sheet2csv
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win10-x64" label="Windows">
|
||||
|
||||
```bash
|
||||
npx -y postject --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 sheet2csv.exe NODE_SEA_BLOB sheet2csv.blob
|
||||
```
|
||||
|
||||
11) Resign the binary.
|
||||
|
||||
The following sequence generates a self-signed certificate:
|
||||
|
||||
```powershell
|
||||
$cert = New-SelfSignedCertificate -Type CodeSigning -DnsName www.onlyspans.net -CertStoreLocation Cert:\CurrentUser\My
|
||||
$pass = ConvertTo-SecureString -String "hunter2" -Force -AsPlainText
|
||||
Export-PfxCertificate -Cert "cert:\CurrentUser\My\$($cert.Thumbprint)" -FilePath "mycert.pfx" -Password $pass
|
||||
```
|
||||
|
||||
After creating a cert, sign the binary:
|
||||
|
||||
```powershell
|
||||
signtool sign /v /f mycert.pfx /p hunter2 /fd SHA256 sheet2csv.exe
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
@ -321,7 +375,7 @@ 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:
|
||||
13) Validate the binary signature:
|
||||
|
||||
```bash
|
||||
codesign -dv ./sheet2csv
|
||||
@ -333,6 +387,24 @@ Inspecting the output, the following line confirms ad-hoc signing was used:
|
||||
Signature=adhoc
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="win10-x64" label="Windows">
|
||||
|
||||
13) Validate the binary signature:
|
||||
|
||||
```powershell
|
||||
signtool verify sheet2csv.exe
|
||||
```
|
||||
|
||||
If the certificate is self-signed, there may be an error:
|
||||
|
||||
```
|
||||
SignTool Error: A certificate chain processed, but terminated in a root
|
||||
certificate which is not trusted by the trust provider.
|
||||
```
|
||||
|
||||
This error is expected.
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="linux-x64" label="Linux">
|
||||
|
||||
|
@ -36,8 +36,9 @@ This demo was tested in the following environments:
|
||||
|
||||
| Postgres | Connector Library | Date |
|
||||
|:---------|:------------------|:-----------|
|
||||
| `16.0.1` | `pg` (`8.11.3`) | 2023-10-30 |
|
||||
| `15.5` | `pg` (`8.11.3`) | 2023-12-04 |
|
||||
| `16.2.1` | `pg` (`8.11.4`) | 2024-03-31 |
|
||||
| `15.6` | `pg` (`8.11.4`) | 2024-03-31 |
|
||||
| `14.11` | `pg` (`8.11.4`) | 2024-03-31 |
|
||||
|
||||
:::
|
||||
|
||||
@ -275,7 +276,7 @@ npm init -y
|
||||
4) Install the `pg` connector module:
|
||||
|
||||
```bash
|
||||
npm i --save pg@8.11.3
|
||||
npm i --save pg@8.11.4
|
||||
```
|
||||
|
||||
5) Save the following example codeblock to `PGTest.js`:
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
title: Sheets with MongoDB
|
||||
sidebar_label: MongoDB
|
||||
sidebar_label: MongoDB / FerretDB
|
||||
pagination_prev: demos/cli/index
|
||||
pagination_next: demos/local/index
|
||||
sidebar_custom_props:
|
||||
@ -24,10 +24,11 @@ to add data from spreadsheets into a collection.
|
||||
|
||||
This demo was tested in the following environments:
|
||||
|
||||
| MongoDB CE | Connector Library | Date |
|
||||
|:-----------|:--------------------|:-----------|
|
||||
| `6.0.10` | `mongodb` (`5.7.0`) | 2023-12-04 |
|
||||
| `7.0.2` | `mongodb` (`5.7.0`) | 2023-12-04 |
|
||||
| Server | Connector Library | Date |
|
||||
|:--------------------|:--------------------|:-----------|
|
||||
| FerretDB `1.21.0` | `mongodb` (`5.9.2`) | 2024-03-30 |
|
||||
| MongoDB CE `6.0.10` | `mongodb` (`5.7.0`) | 2023-12-04 |
|
||||
| MongoDB CE `7.0.2` | `mongodb` (`5.7.0`) | 2023-12-04 |
|
||||
|
||||
:::
|
||||
|
||||
@ -81,7 +82,14 @@ This workbook is typically exported to the filesystem with `writeFile`[^8].
|
||||
|
||||
## Complete Example
|
||||
|
||||
0) Install MongoDB 7.0 Community Edition[^9]. The macOS steps required `brew`:
|
||||
0) Install a MongoDB-compatible server. Options include MongoDB CE[^9] and
|
||||
FerretDB[^10]
|
||||
|
||||
1) Start a server on `localhost` (follow official instructions).
|
||||
|
||||
<details><summary><b>MongoDB CE Setup</b> (click to show)</summary>
|
||||
|
||||
For MongoDB 7.0 Community Edition, the macOS steps required `brew`:
|
||||
|
||||
```bash
|
||||
brew tap mongodb/brew
|
||||
@ -89,8 +97,6 @@ brew update
|
||||
brew install mongodb-community
|
||||
```
|
||||
|
||||
1) Start a MongoDB server on `localhost` (follow official instructions).
|
||||
|
||||
:::note pass
|
||||
|
||||
If `brew` was used to install MongoDB, the following command starts a server:
|
||||
@ -107,6 +113,8 @@ If Homebrew is configured to use `/opt/homebrew`, the command is:
|
||||
|
||||
:::
|
||||
|
||||
</details>
|
||||
|
||||
2) Create base project and install the dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
@ -179,4 +187,5 @@ There should be no errors in the terminal. The script will generate the file
|
||||
[^6]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
|
||||
[^7]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`.
|
||||
[^8]: See [`writeFile` in "Writing Files"](/docs/api/write-options)
|
||||
[^9]: See ["Install MongoDB Community Edition"](https://www.mongodb.com/docs/manual/administration/install-community/#std-label-install-mdb-community-edition) in the MongoDB documentation.
|
||||
[^9]: See ["Install MongoDB Community Edition"](https://www.mongodb.com/docs/manual/administration/install-community/#std-label-install-mdb-community-edition) in the MongoDB documentation.
|
||||
[^10]: See ["SQLite Setup with Docker Compose"](https://docs.ferretdb.io/quickstart-guide/docker/#sqlite-setup-with-docker-compose) in the FerretDB documentation.
|
@ -17,8 +17,10 @@ import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
**Redis has relicensed away from open source!**
|
||||
|
||||
The original BSD-3-Clause applies to version `7.2.4`. This discussion applies to
|
||||
KeyDB and other servers that support the "Redis serialization protocol" (RESP).
|
||||
The original BSD-3-Clause still applies to version `7.2.4`.
|
||||
|
||||
This demo has been tested with KeyDB and other servers that support the "Redis
|
||||
serialization protocol" (RESP).
|
||||
|
||||
:::
|
||||
|
||||
@ -40,7 +42,7 @@ This demo was tested in the following environments:
|
||||
|:--------------|:-------------------|:----------:|
|
||||
| KeyDB `6.3.4` | `redis` (`4.6.13`) | 2024-03-25 |
|
||||
| Redis `6.2.9` | `redis` (`4.6.11`) | 2023-12-04 |
|
||||
| Redis `7.2.3` | `redis` (`4.6.11`) | 2023-12-04 |
|
||||
| Redis `7.2.4` | `redis` (`4.6.11`) | 2024-03-26 |
|
||||
|
||||
:::
|
||||
|
||||
|
@ -4,6 +4,11 @@ pagination_prev: demos/cloud/index
|
||||
pagination_next: demos/bigdata/index
|
||||
---
|
||||
|
||||
import current from '/version.js';
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
The [SheetJS Standalone scripts](/docs/getting-started/installation/standalone)
|
||||
can be integrated in a Chromium extension.
|
||||
|
||||
@ -14,7 +19,7 @@ tables with a content script and a background script.
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested on 2024 March 11 against Chrome 122.
|
||||
This demo was last tested on 2024 March 30 against Chrome 122.
|
||||
|
||||
:::
|
||||
|
||||
@ -131,7 +136,8 @@ for(var i = 0; i < tables.length; ++i) {
|
||||
The demo extension includes multiple features to demonstrate sample usage.
|
||||
Production extensions should include proper error handling.
|
||||
|
||||
<details open><summary><b>Testing Unpacked Extension</b> (click to hide)</summary>
|
||||
<Tabs>
|
||||
<TabItem name="zip" value="Prepared Extension">
|
||||
|
||||
1) Download the zip for the desired Manifest version:
|
||||
|
||||
@ -142,13 +148,186 @@ Production extensions should include proper error handling.
|
||||
|
||||
3) Drag and drop the downloaded zip file into the window.
|
||||
|
||||
</details>
|
||||
</TabItem>
|
||||
<TabItem name="crx" value="Extension from Scratch">
|
||||
|
||||
1) Create a new extension using `create-chrome-ext`[^1]:
|
||||
|
||||
```bash
|
||||
npm create chrome-ext@latest sheetjs-crx -- --template vanilla-ts
|
||||
cd sheetjs-crx
|
||||
npm install
|
||||
```
|
||||
|
||||
2) Edit the highlighted lines in `package.json`:
|
||||
|
||||
```js title="package.json" (edit highlighted lines)
|
||||
{
|
||||
"name": "sheetjs-crx",
|
||||
// highlight-next-line
|
||||
"displayName": "SheetJS Demo",
|
||||
"version": "0.0.0",
|
||||
"author": "**",
|
||||
// highlight-next-line
|
||||
"description": "Sample Extension using SheetJS to interact with Chrome",
|
||||
```
|
||||
|
||||
3) Edit `manifest.ts` and add to the `permissions` array:
|
||||
|
||||
```ts title="manifest.ts"
|
||||
permissions: ['sidePanel', 'storage',
|
||||
"activeTab",
|
||||
"bookmarks",
|
||||
"contextMenus",
|
||||
"downloads",
|
||||
"tabs"
|
||||
],
|
||||
```
|
||||
|
||||
4) Install the SheetJS dependency and start the dev server:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
curl -o .\public\img\logo-48.png https://docs.sheetjs.com/logo.png
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz
|
||||
npm run dev`}
|
||||
</CodeBlock>
|
||||
|
||||
The build step will create a `build` subfolder.
|
||||
|
||||
5) Replace `src/popup/index.ts` with the following codeblock:
|
||||
|
||||
```ts title="src/popup/index.ts"
|
||||
import { version, utils, writeFileXLSX } from 'xlsx';
|
||||
import './index.css'
|
||||
|
||||
/* recursively walk the bookmark tree */
|
||||
const recurse_bookmarks = (data, tree, path) => {
|
||||
if(tree.url) data.push({Name: tree.title, Location: tree.url, Path:path});
|
||||
var T = path ? (path + "::" + tree.title) : tree.title;
|
||||
(tree.children||[]).forEach(function(C) { recurse_bookmarks(data, C, T); });
|
||||
};
|
||||
|
||||
const export_bookmarks = () => {
|
||||
chrome.bookmarks.getTree(function(res) {
|
||||
var data = [];
|
||||
res.forEach(function(t) { recurse_bookmarks(data, t, ""); });
|
||||
|
||||
/* create worksheet */
|
||||
var ws = utils.json_to_sheet(data, { header: ['Name', 'Location', 'Path'] });
|
||||
|
||||
/* create workbook and export */
|
||||
var wb = utils.book_new();
|
||||
utils.book_append_sheet(wb, ws, 'Bookmarks');
|
||||
writeFileXLSX(wb, "bookmarks.xlsx");
|
||||
});
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const root = document.getElementById('app')!
|
||||
|
||||
const xprt = document.createElement("button"); // sjsdownload
|
||||
xprt.type = "button"; xprt.innerHTML = "Export Bookmarks";
|
||||
root.appendChild(xprt);
|
||||
xprt.addEventListener("click", export_bookmarks);
|
||||
|
||||
const vers = document.createElement("a");
|
||||
vers.innerHTML = "SheetJS " + version;
|
||||
root.appendChild(vers);
|
||||
vers.addEventListener("click", () => { chrome.tabs.create({url: "https://sheetjs.com/"}); });
|
||||
});
|
||||
```
|
||||
|
||||
6) Replace `src/background/index.ts` with the following codeblock:
|
||||
|
||||
```ts title="src/background/index.ts"
|
||||
chrome.runtime.onInstalled.addListener(function() {
|
||||
chrome.contextMenus.create({
|
||||
type: "normal",
|
||||
id: "sjsexport",
|
||||
title: "Export Table to XLSX",
|
||||
contexts: ["page", "selection"]
|
||||
});
|
||||
chrome.contextMenus.create({
|
||||
type: "normal",
|
||||
id: "sj5export",
|
||||
title: "Export All Tables in Page",
|
||||
contexts: ["page", "selection"]
|
||||
});
|
||||
chrome.contextMenus.onClicked.addListener(function(info/*, tab*/) {
|
||||
var mode = "";
|
||||
switch(info.menuItemId) {
|
||||
case 'sjsexport': mode = "JS"; break;
|
||||
case 'sj5export': mode = "J5"; break;
|
||||
default: return;
|
||||
}
|
||||
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
|
||||
chrome.tabs.sendMessage(tabs[0].id, {Sheet:mode}, sjsexport_cb);
|
||||
});
|
||||
});
|
||||
|
||||
chrome.contextMenus.create({
|
||||
id: "sjsabout",
|
||||
title: "About",
|
||||
contexts: ["browser_action"]
|
||||
});
|
||||
chrome.contextMenus.onClicked.addListener(function(info/*, tab*/) {
|
||||
if(info.menuItemId !== "sjsabout") return;
|
||||
chrome.tabs.create({url: "https://sheetjs.com/"});
|
||||
});
|
||||
});
|
||||
|
||||
function sjsexport_cb(wb) {
|
||||
if(!wb || !wb.SheetNames || !wb.Sheets) { return alert("Error in exporting table"); }
|
||||
const b64 = XLSX.write(wb, {bookType: "xlsx", type: "base64"});
|
||||
chrome.downloads.download({
|
||||
url: `data:application/octet-stream;base64,${b64}`,
|
||||
filename: `SheetJSTables.xlsx`
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
7) Replace `src/contentScript/index.ts` with the following codeblock:
|
||||
|
||||
```ts title="src/contentScript/index.ts"
|
||||
import { utils } from 'xlsx';
|
||||
var coords = [0,0];
|
||||
document.addEventListener('mousedown', function(mouse) {
|
||||
if(mouse && mouse.button == 2) coords = [mouse.clientX, mouse.clientY];
|
||||
});
|
||||
|
||||
chrome.runtime.onMessage.addListener(function(msg, sender, cb) {
|
||||
if(!msg || !msg['Sheet']) return;
|
||||
if(msg.Sheet == "JS") {
|
||||
var elt = document.elementFromPoint(coords[0], coords[1]);
|
||||
while(elt != null) {
|
||||
if(elt.tagName.toLowerCase() == "table") return cb(utils.table_to_book(elt));
|
||||
elt = elt.parentElement;
|
||||
}
|
||||
} else if(msg.Sheet == "J5") {
|
||||
var tables = document.getElementsByTagName("table");
|
||||
var wb = utils.book_new();
|
||||
for(var i = 0; i < tables.length; ++i) {
|
||||
var ws = utils.table_to_sheet(tables[i]);
|
||||
utils.book_append_sheet(wb, ws, "Table" + i);
|
||||
}
|
||||
return cb(wb);
|
||||
}
|
||||
cb(coords);
|
||||
});
|
||||
```
|
||||
|
||||
8) Open `chrome://extensions/` in the browser and enable Developer mode
|
||||
|
||||
9) Click "Load unpacked" and select the `build` folder within the project.
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
### Bookmark Exporter
|
||||
|
||||
<details open><summary><b>Testing</b> (click to hide)</summary>
|
||||
|
||||
0) Go to <https://sheetjs.com> and create a bookmark in the browser.
|
||||
0) Open <https://sheetjs.com> in the browser and create a bookmark.
|
||||
|
||||
1) Click the Extensions icon (puzzle icon to the right of the address bar) and
|
||||
select "SheetJS Demo".
|
||||
@ -203,7 +382,7 @@ chrome.bookmarks.getTree(function(res) {
|
||||
|
||||
<details open><summary><b>Testing</b> (click to hide)</summary>
|
||||
|
||||
1) Go to <https://sheetjs.com/demo/table>
|
||||
1) Open <https://sheetjs.com/demo/table> in the browser.
|
||||
|
||||
2) Right-click anywhere in the page and select "SheetJS Demo" > "Export All Tables in Page"
|
||||
|
||||
@ -255,3 +434,5 @@ sequenceDiagram
|
||||
Note over P: Create Data URL
|
||||
P->>U: `chrome.downloads.download`
|
||||
```
|
||||
|
||||
[^1]: See the [`create-chrome-ext` package](https://github.com/guocaoyi/create-chrome-ext) for more details.
|
@ -30,7 +30,7 @@ flowchart LR
|
||||
|
||||
:::note Tested Deployments
|
||||
|
||||
This demo was last tested by SheetJS users on 2023 October 3 in Maple 2023.
|
||||
This demo was last tested by SheetJS users on 2024 March 31 in Maple 2024.
|
||||
|
||||
:::
|
||||
|
||||
@ -54,8 +54,8 @@ The extension function ultimately pairs the SheetJS `read`[^2] and `write`[^3]
|
||||
methods to read data from the old file and write a new file:
|
||||
|
||||
```js
|
||||
var wb = XLSX.read(original_file_data, {type: "buffer"});
|
||||
var new_file_data = XLSX.write(wb, {type: "array", bookType: "xlsx"});
|
||||
var workbook = XLSX.read(original_file_data, { type: "buffer" });
|
||||
var new_file_data = XLSX.write(workbook, { type: "array", bookType: "xlsx" });
|
||||
```
|
||||
|
||||
The extension function will receive a file name and perform the following steps:
|
||||
@ -81,8 +81,9 @@ flowchart LR
|
||||
|
||||
### C Extensions
|
||||
|
||||
Maple C extensions are shared libraries or DLLs that use special Maple methods
|
||||
for parsing arguments and returning values.
|
||||
Maple extensions are shared libraries or DLLs that use special Maple methods for
|
||||
parsing arguments and returning values. They are typically written in the C
|
||||
programming language.
|
||||
|
||||
To simplify the flow, the new function will take one argument (the original file
|
||||
name) and return one value (the new file name).
|
||||
@ -125,7 +126,7 @@ with(ExcelTools);
|
||||
Import(SheetToXLSX("pres.numbers"))
|
||||
```
|
||||
|
||||
0) Ensure "Windows Subsystem for Linux" (WSL) and Visual Studio are installed.
|
||||
0) Install "Windows Subsystem for Linux" (WSL)[^5] and Visual Studio[^6].
|
||||
|
||||
1) Open a new "x64 Native Tools Command Prompt" window and create a project
|
||||
folder `c:\sheetjs-maple`:
|
||||
@ -137,11 +138,11 @@ cd sheetjs-maple
|
||||
```
|
||||
|
||||
2) Copy the headers and `lib` files from the Maple folder to the project folder.
|
||||
For example, using Maple 2023 on Windows x64:
|
||||
For example, using Maple 2024 on Windows x64:
|
||||
|
||||
```powershell
|
||||
copy "C:\Program Files\Maple 2023\extern\include\"*.h .
|
||||
copy "c:\Program Files\Maple 2023\bin.x86_64_WINDOWS"\*.lib .
|
||||
copy "C:\Program Files\Maple 2024\extern\include\"*.h .
|
||||
copy "c:\Program Files\Maple 2024\bin.x86_64_WINDOWS"\*.lib .
|
||||
```
|
||||
|
||||
3) Run `bash` to enter WSL
|
||||
@ -206,4 +207,6 @@ The result will show the data from `pres.numbers`
|
||||
[^1]: See ["ExcelTools"](https://www.maplesoft.com/support/help/Maple/view.aspx?path=ExcelTools) in the Maple documentation.
|
||||
[^2]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^3]: See [`write` in "Writing Files"](/docs/api/write-options)
|
||||
[^4]: See ["C OpenMaple and ExternalCalling Application Program Interface (API)"](https://www.maplesoft.com/support/help/maple/view.aspx?path=OpenMaple%2FC%2FAPI) in the Maple documentation.
|
||||
[^4]: See ["C OpenMaple and ExternalCalling Application Program Interface (API)"](https://www.maplesoft.com/support/help/maple/view.aspx?path=OpenMaple%2FC%2FAPI) in the Maple documentation.
|
||||
[^5]: In a PowerShell terminal window, run `wsl --install Ubuntu`
|
||||
[^6]: See [the Visual Studio website](https://visualstudio.microsoft.com/#vs-section) for download links. In the Visual Studio Installer, install the "Desktop development with C++" workflow.
|
@ -6,8 +6,7 @@ sidebar_position: 1
|
||||
import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
|
||||
<details>
|
||||
<summary><b>File Format Support</b> (click to show)</summary>
|
||||
<details><summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
Dates are a core concept in nearly every spreadsheet application in existence.
|
||||
Some legacy spreadsheet apps only supported dates. Others supported times as a
|
||||
@ -254,7 +253,7 @@ if(!(wb?.Workbook?.WBProps?.date1904)) {
|
||||
}
|
||||
```
|
||||
|
||||
:::note Why does the 1904 date system exist?
|
||||
<details><summary><b>Why does the 1904 date system exist?</b> (click to show) </summary>
|
||||
|
||||
1900 was not a leap year. For the Gregorian calendar, the general rules are:
|
||||
- every multiple of 400 is a leap year
|
||||
@ -268,13 +267,13 @@ the `@date` function:
|
||||
```
|
||||
@date(0,2,28) -> 59 // Lotus accepts 2/28/1900
|
||||
@date(0,2,29) -> 60 // <--2/29/1900 was not a real date
|
||||
@date(0.2,30) -> ERR // Lotus rejects 2/30/1900
|
||||
@date(0,2,30) -> ERR // Lotus rejects 2/30/1900
|
||||
```
|
||||
|
||||
Excel extends the tradition in the default date system. The 1904 date system
|
||||
starts the count in 1904, skipping the bad date.
|
||||
|
||||
:::
|
||||
</details>
|
||||
|
||||
### Relative Epochs
|
||||
|
||||
@ -292,6 +291,8 @@ of universal time.
|
||||
|
||||
## How Files Store Dates and Times
|
||||
|
||||
<details><summary><b>Technical Details</b> (click to show)</summary>
|
||||
|
||||
XLS, XLSB, and most binary formats store the raw date codes. Special number
|
||||
formats are used to indicate that the values are intended to be dates/times.
|
||||
|
||||
@ -310,6 +311,8 @@ Numbers uses a calendar date system, but records pure time values as if they are
|
||||
absolute times in 1904 January 01. It is spiritually equivalent to the 1904 mode
|
||||
in Excel and other spreadsheet applications.
|
||||
|
||||
</details>
|
||||
|
||||
## How JavaScript Engines Understand Time
|
||||
|
||||
JavaScript provides a `Date` object which represents an *absolute* time. Under
|
||||
@ -632,4 +635,22 @@ A single `Array#map` operation can create a fixed dataset:
|
||||
|
||||
```js
|
||||
const new_rows = rows.map(({birthday, ...rest}) => ({birthday: new Date(birthday), ...rest}))
|
||||
```
|
||||
```
|
||||
|
||||
The `Date` constructor interprets the dates in local time.
|
||||
|
||||
:::caution pass
|
||||
|
||||
Excel and other spreadsheet software do not typically support dates before 1900.
|
||||
If there are dates before the threshold, it is strongly recommended to pass
|
||||
strings instead of `Date` objects.
|
||||
|
||||
:::
|
||||
|
||||
:::warning pass
|
||||
|
||||
JavaScript string to `Date` conversion is "implementation-dependent" and may
|
||||
misinterpret some date formats. When designing APIs, it is strongly recommended
|
||||
to pass ISO 8601 strings when possible.
|
||||
|
||||
:::
|
||||
|
@ -4,8 +4,7 @@ sidebar_label: Hyperlinks
|
||||
sidebar_position: 3
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary><b>File Format Support</b> (click to show)</summary>
|
||||
<details><summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
Traditional spreadsheet software, including Excel, support "Cell Links". The
|
||||
entire cell text is clickable.
|
||||
@ -31,17 +30,34 @@ and writers apply the hyperlink to the entire cell text.
|
||||
|
||||
</details>
|
||||
|
||||
Hyperlinks are stored in the `l` key of cell objects. The `Target` field of the
|
||||
hyperlink object is the target of the link, including the URI fragment. Tooltips
|
||||
are stored in the `Tooltip` field and are displayed when hovering over the text.
|
||||
Spreadsheet hyperlinks are clickable references to other locations. They serve
|
||||
the same role as the HTML `<a>` tag.
|
||||
|
||||
Spreadsheet applications can process "internal" (cells, ranges, and defined
|
||||
names) and "external" (websites, email addresses, and local files) references.
|
||||
|
||||
SheetJS hyperlink objects are stored in the `l` key of cell objects. Hyperlink
|
||||
objects include the following fields:
|
||||
|
||||
- `Target` (required) describes the reference.
|
||||
- `Tooltip` is the tooltip text. Tooltips are shown when hovering over the text.
|
||||
|
||||
For example, the following snippet creates a link from cell `A1` to
|
||||
<https://sheetjs.com> with the tip `"Find us @ SheetJS.com!"`:
|
||||
|
||||
```js
|
||||
ws["A1"].l = { Target: "https://sheetjs.com", Tooltip: "Find us @ SheetJS.com!" };
|
||||
/* create worksheet with cell A1 = "https://sheetjs.com" */
|
||||
var ws = XLSX.utils.aoa_to_sheet([["https://sheetjs.com"]]);
|
||||
|
||||
/* add hyperlink */
|
||||
ws["A1"].l = {
|
||||
Target: "https://sheetjs.com",
|
||||
Tooltip: "Find us @ SheetJS.com!"
|
||||
};
|
||||
```
|
||||
|
||||
![Cell A1 is a hyperlink with a custom tooltip](pathname:///hyperlink/tooltip.png)
|
||||
|
||||
:::note pass
|
||||
|
||||
Following traditional software, hyperlinks are applied to entire cell objects.
|
||||
@ -60,11 +76,26 @@ general hyperlink styling.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
## External Hyperlinks
|
||||
|
||||
Spreadsheet software will typically launch other programs to handle external
|
||||
hyperlinks. For example, clicking a "Web Link" will open a new browser window.
|
||||
|
||||
### Web Links
|
||||
|
||||
HTTP and HTTPS links can be used directly:
|
||||
|
||||
```js
|
||||
ws["A2"].l = { Target: "https://docs.sheetjs.com/docs/csf/features/hyperlinks#web-links" };
|
||||
ws["A3"].l = { Target: "http://localhost:7262/yes_localhost_works" };
|
||||
```
|
||||
|
||||
<details open><summary><b>Live Example</b> (click to hide)</summary>
|
||||
|
||||
```jsx live
|
||||
/* The live editor requires this function wrapper */
|
||||
function ExportSimpleLink(props) { return ( <button onClick={() => {
|
||||
function ExportSimpleLink() { return ( <button onClick={() => {
|
||||
/* Create worksheet */
|
||||
var ws = XLSX.utils.aoa_to_sheet([ [ "Link", "No Link" ] ]);
|
||||
/* Add link */
|
||||
@ -82,54 +113,7 @@ function ExportSimpleLink(props) { return ( <button onClick={() => {
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
<details><summary><b>Extract all links from a file</b> (click to show)</summary>
|
||||
|
||||
The following example iterates through each worksheet and each cell to find all
|
||||
links. The table shows sheet name, cell address, and target for each link.
|
||||
|
||||
```jsx live
|
||||
function SheetJSParseLinks(props) {
|
||||
const [rows, setRows] = React.useState([]);
|
||||
|
||||
return ( <>
|
||||
<input type="file" onChange={async(e) => {
|
||||
let rows = [];
|
||||
/* parse workbook */
|
||||
const file = e.target.files[0];
|
||||
const data = await file.arrayBuffer();
|
||||
const wb = XLSX.read(data);
|
||||
|
||||
const html = [];
|
||||
wb.SheetNames.forEach(n => {
|
||||
var ws = wb.Sheets[n]; if(!ws) return;
|
||||
var ref = XLSX.utils.decode_range(ws["!ref"]);
|
||||
for(var R = 0; R <= ref.e.r; ++R) for(var C = 0; C <= ref.e.c; ++C) {
|
||||
var addr = XLSX.utils.encode_cell({r:R,c:C});
|
||||
if(!ws[addr] || !ws[addr].l) continue;
|
||||
var link = ws[addr].l;
|
||||
rows.push({ws:n, addr, Target: link.Target});
|
||||
}
|
||||
});
|
||||
setRows(rows);
|
||||
}}/>
|
||||
<table><tr><th>Sheet</th><th>Address</th><th>Link Target</th></tr>
|
||||
{rows.map(r => (<tr><td>{r.ws}</td><td>{r.addr}</td><td>{r.Target}</td></tr>))}
|
||||
</table>
|
||||
</> );
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Remote Links
|
||||
|
||||
HTTP and HTTPS links can be used directly:
|
||||
|
||||
```js
|
||||
ws["A2"].l = { Target: "https://docs.sheetjs.com/docs/csf/features/hyperlinks" };
|
||||
ws["A3"].l = { Target: "http://localhost:7262/yes_localhost_works" };
|
||||
```
|
||||
### Mail Links
|
||||
|
||||
Excel also supports `mailto` email links with subject line:
|
||||
|
||||
@ -145,7 +129,7 @@ address input in the form never leaves your machine.**
|
||||
|
||||
```jsx live
|
||||
/* The live editor requires this function wrapper */
|
||||
function ExportRemoteLink(props) {
|
||||
function ExportRemoteLink() {
|
||||
const [email, setEmail] = React.useState("ignored@dev.null");
|
||||
const set_email = React.useCallback((evt) => setEmail(evt.target.value));
|
||||
|
||||
@ -172,7 +156,7 @@ function ExportRemoteLink(props) {
|
||||
|
||||
</details>
|
||||
|
||||
## Local Links
|
||||
### Local Links
|
||||
|
||||
Links to absolute paths should use the `file://` URI scheme:
|
||||
|
||||
@ -195,7 +179,7 @@ Relative Paths have undefined behavior in the SpreadsheetML 2003 format. Excel
|
||||
|
||||
:::
|
||||
|
||||
## Internal Links
|
||||
## Internal Hyperlinks
|
||||
|
||||
Links where the target is a cell or range or defined name in the same workbook
|
||||
("Internal Links") are marked with a leading hash character:
|
||||
@ -218,7 +202,7 @@ The defined name `SheetJSDN` points to the range `A1:B2` in the second sheet.
|
||||
|
||||
```jsx live
|
||||
/* The live editor requires this function wrapper */
|
||||
function ExportInternalLink(props) { return ( <button onClick={() => {
|
||||
function ExportInternalLink() { return ( <button onClick={() => {
|
||||
/* Create empty workbook */
|
||||
var wb = XLSX.utils.book_new();
|
||||
|
||||
@ -279,7 +263,7 @@ HTML table. The hyperlink in the second row will be parsed as a cell-level link.
|
||||
|
||||
```jsx live
|
||||
/* The live editor requires this function wrapper */
|
||||
function ExportHyperlink(props) {
|
||||
function ExportHyperlink() {
|
||||
|
||||
/* Callback invoked when the button is clicked */
|
||||
const xport = React.useCallback(() => {
|
||||
@ -314,7 +298,7 @@ has a standard HTML link.
|
||||
|
||||
```jsx live
|
||||
/* The live editor requires this function wrapper */
|
||||
function ExportALinks(props) {
|
||||
function ExportALinks() {
|
||||
const [ __html, setHTML ] = React.useState("");
|
||||
React.useEffect(() => {
|
||||
/* Create worksheet */
|
||||
@ -335,5 +319,46 @@ function ExportALinks(props) {
|
||||
|
||||
</details>
|
||||
|
||||
#### Miscellany
|
||||
|
||||
<details><summary><b>Extract all links from a file</b> (click to show)</summary>
|
||||
|
||||
The following example iterates through each worksheet and each cell to find all
|
||||
links. The table shows sheet name, cell address, and target for each link.
|
||||
|
||||
```jsx live
|
||||
function SheetJSParseLinks() {
|
||||
const [rows, setRows] = React.useState([]);
|
||||
|
||||
return ( <>
|
||||
<input type="file" onChange={async(e) => {
|
||||
let rows = [];
|
||||
/* parse workbook */
|
||||
const file = e.target.files[0];
|
||||
const data = await file.arrayBuffer();
|
||||
const wb = XLSX.read(data);
|
||||
|
||||
const html = [];
|
||||
wb.SheetNames.forEach(n => {
|
||||
var ws = wb.Sheets[n]; if(!ws) return;
|
||||
var ref = XLSX.utils.decode_range(ws["!ref"]);
|
||||
for(var R = 0; R <= ref.e.r; ++R) for(var C = 0; C <= ref.e.c; ++C) {
|
||||
var addr = XLSX.utils.encode_cell({r:R,c:C});
|
||||
if(!ws[addr] || !ws[addr].l) continue;
|
||||
var link = ws[addr].l;
|
||||
rows.push({ws:n, addr, Target: link.Target});
|
||||
}
|
||||
});
|
||||
setRows(rows);
|
||||
}}/>
|
||||
<table><tr><th>Sheet</th><th>Address</th><th>Link Target</th></tr>
|
||||
{rows.map(r => (<tr><td>{r.ws}</td><td>{r.addr}</td><td>{r.Target}</td></tr>))}
|
||||
</table>
|
||||
</> );
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
[^1]: The primary SheetJS DOM parsing methods are [`table_to_book`, `table_to_sheet`, and `sheet_add_dom`](/docs/api/utilities/html#html-table-input)
|
||||
[^2]: HTML strings can be written using [`bookType: "html"` in the `write` or `writeFile` methods](/docs/api/write-options) or by using the [dedicated `sheet_to_html` utility function](/docs/api/utilities/html#html-table-output)
|
@ -1,11 +1,10 @@
|
||||
---
|
||||
title: Cell Comments and Notes
|
||||
sidebar_label: Cell Comments
|
||||
sidebar_position: 4
|
||||
---
|
||||
|
||||
# Cell Comments
|
||||
|
||||
<details>
|
||||
<summary><b>File Format Support</b> (click to show)</summary>
|
||||
<details><summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
Comments and Notes have evolved over the years.
|
||||
|
||||
@ -42,6 +41,33 @@ The letter R (R) marks features parsed but not written in the format.
|
||||
|
||||
</details>
|
||||
|
||||
Comments and notes are cell annotations. Cells with comments or notes are marked
|
||||
with a small triangle or `¬` in the upper-right corner.
|
||||
|
||||
Excel notes are standalone text boxes with adjustable background colors and
|
||||
support for rich text. Historically people "replied" to comments by adding text
|
||||
to the end of existing comments.
|
||||
|
||||
Excel comments are simple text boxes that allow users to enter plain text. Users
|
||||
can reply to comments.
|
||||
|
||||
The following screenshot shows a spreadsheet with comments and a note.
|
||||
|
||||
- The note is associated with cell A1 (the cell with the red triangle). It has
|
||||
a green gradient background fill.
|
||||
- The comments are associated with cell A2 (the cell with the blue `¬`). There
|
||||
are 2 comments from different authors. A "Reply" box appears below the thread.
|
||||
|
||||
![Excel comments and notes](pathname:///comments/types.png)
|
||||
|
||||
:::info pass
|
||||
|
||||
Google Sheets "notes" do not currently support rich text or background colors.
|
||||
|
||||
Apple Numbers supports "comments" but does not support "notes".
|
||||
|
||||
:::
|
||||
|
||||
## Basic Structure
|
||||
|
||||
Cell comments are objects stored in the `c` array of cell objects.
|
||||
|
@ -1,11 +1,9 @@
|
||||
---
|
||||
title: Defined Names
|
||||
sidebar_position: 5
|
||||
---
|
||||
|
||||
# Defined Names
|
||||
|
||||
<details>
|
||||
<summary><b>File Format Support</b> (click to show)</summary>
|
||||
<details><summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
Defined names have evolved over the decades, with new features added over time:
|
||||
|
||||
@ -27,7 +25,62 @@ no way to specify a Unicode defined name in the SYLK format.
|
||||
|
||||
</details>
|
||||
|
||||
`wb.Workbook.Names` is an array of defined name objects which have the keys:
|
||||
Defined names (sometimes called "named ranges") are labeled references to cells,
|
||||
ranges, constants or formulae. Meaningful labels can make formula expressions
|
||||
more readable and more robust to worksheet changes.
|
||||
|
||||
<details><summary><b>Why are Defined Names useful?</b> (click to show)</summary>
|
||||
|
||||
For example, the `NPV` formula function calculates the net present value of a
|
||||
series of cashflows. In large workbooks, raw data will be stored in separate
|
||||
worksheets and the interest rate will be stored in a separate "Model Parameters"
|
||||
worksheet. Formulae may have references to multiple sheets:
|
||||
|
||||
```
|
||||
=NPV('Model Parameters'!B2,Data!B2:F2)
|
||||
^^^^^^^^^^^^^^^^^^^^^ --- interest rate
|
||||
```
|
||||
|
||||
A defined name `Interest` referencing `'Model Parameters'!B2` would greatly
|
||||
simplify the formula:
|
||||
|
||||
```
|
||||
=NPV(Interest,Data!B2:F2)
|
||||
^^^^^^^^ --- interest rate
|
||||
```
|
||||
|
||||
Judicious use of Defined Names generally lead to fewer formula errors.
|
||||
|
||||
</details>
|
||||
|
||||
## Storage
|
||||
|
||||
The `Workbook` property of SheetJS workbook objects store workbook attributes.
|
||||
The `Names` property of `Workbook` is an array of SheetJS defined name objects.
|
||||
|
||||
:::caution pass
|
||||
|
||||
Parsers do not always create the `Names` array or `Workbook` structure. Code
|
||||
should test for the existence of the defined names array before use:
|
||||
|
||||
```js
|
||||
var wb = XLSX.utils.book_new();
|
||||
|
||||
/* ensure the workbook structure exists */
|
||||
/* highlight-start */
|
||||
if(!wb.Workbook) wb.Workbook = {};
|
||||
if(!wb.Workbook.Names) wb.Workbook.Names = [];
|
||||
/* highlight-end */
|
||||
|
||||
/* add a new defined name */
|
||||
wb.Workbook.Names.push({ Name: "MyData", Ref: "Sheet1!$A$1:$A$2" });
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Defined Name Object
|
||||
|
||||
SheetJS defined name objects support the following properties:
|
||||
|
||||
| Key | Name in app | Description |
|
||||
|:----------|:------------|:---------------------------------------------------|
|
||||
@ -36,19 +89,7 @@ no way to specify a Unicode defined name in the SYLK format.
|
||||
| `Ref` | "Refers To" | A1-Style Reference (`"Sheet1!$A$1:$D$20"`) |
|
||||
| `Comment` | "Comment" | Comment (for supported file formats) |
|
||||
|
||||
Parsers do not always create the `Names` structure. Parsing and writing code
|
||||
should test for the existence of the defined names array before use:
|
||||
|
||||
```js
|
||||
/* ensure the workbook structure exists */
|
||||
if(!wb.Workbook) wb.Workbook = {};
|
||||
if(!wb.Workbook.Names) wb.Workbook.Names = [];
|
||||
|
||||
/* add a new defined name */
|
||||
wb.Workbook.Names.push({ Name: "MyData", Ref: "Sheet1!$A$1:$A$2" });
|
||||
```
|
||||
|
||||
## Ranges
|
||||
### Ranges
|
||||
|
||||
Defined name references in formulae are internally shifted to the cell address.
|
||||
For example, given the defined name
|
||||
@ -73,7 +114,7 @@ The recommended approach is to fix the rows and columns of the reference:
|
||||
{ Name: "MyData", Ref: "Sheet1!$A$1:$A$2" } // absolute reference
|
||||
```
|
||||
|
||||
## Scoped Defined Names
|
||||
### Scope
|
||||
|
||||
Excel allows two sheet-scoped defined names to share the same name. However, a
|
||||
sheet-scoped name cannot collide with a workbook-scope name. Workbook writers
|
||||
|
@ -1,11 +1,9 @@
|
||||
---
|
||||
title: Number Formats
|
||||
sidebar_position: 6
|
||||
---
|
||||
|
||||
# Number Formats
|
||||
|
||||
<details>
|
||||
<summary><b>File Format Support</b> (click to show)</summary>
|
||||
<details><summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
Modern applications separate "content" from "presentation". A value like `$3.50`
|
||||
is typically stored as the underlying value (`3.50`) with a format (`$0.00`).
|
||||
@ -64,19 +62,19 @@ To simplify editing, the applications will store the underlying values and the
|
||||
number formats separately. For example, `$3.50` will be represented as the value
|
||||
`3.5` with a number format that mandates a `$` sigil and 2 decimal places.
|
||||
|
||||
Number format metadata can be attached to each cell object in the `z` property:
|
||||
The `z` property of SheetJS cell objects stores the number format metadata:
|
||||
|
||||
```js
|
||||
/* set the format of cell B2 to "0.00%" */
|
||||
worksheet["B2"].z = "0.00%";
|
||||
```
|
||||
|
||||
When requested, the cell formatted text will be stored in the `w` property.
|
||||
When requested, the formatted text will be stored in the `w` property.
|
||||
|
||||
## Live Demo
|
||||
|
||||
This example generates a worksheet with common number formats.
|
||||
The number formats are explicitly assigned:
|
||||
This example generates a worksheet with common number formats. The number
|
||||
formats are explicitly assigned:
|
||||
|
||||
```js
|
||||
/* assign number formats */
|
||||
|
@ -1,4 +1,5 @@
|
||||
---
|
||||
title: VBA and Macros
|
||||
sidebar_position: 7
|
||||
---
|
||||
|
||||
@ -7,13 +8,10 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
# VBA and Macros
|
||||
<details><summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
<details>
|
||||
<summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
Note that XLSX does not support macros. The XLSM file format is nearly
|
||||
identical to XLSX and supports macros.
|
||||
XLSX does not support macros. The XLSM file format is nearly identical to XLSX
|
||||
and supports macros.
|
||||
|
||||
| Formats | Basic | Storage Representation |
|
||||
|:--------|:-----:|:-----------------------------------|
|
||||
@ -27,13 +25,39 @@ no way to embed VBA in the XLSX format.
|
||||
|
||||
</details>
|
||||
|
||||
VBA Macros are stored in a special data blob that is exposed in the `vbaraw`
|
||||
property of the workbook object when the `bookVBA` option is `true`. They are
|
||||
supported in `XLSM`, `XLSB`, and `BIFF8 XLS` formats. The supported format
|
||||
writers automatically insert the data blobs if it is present in the workbook and
|
||||
associate with the worksheet names.
|
||||
Visual Basic for Applications (VBA) is a scripting platform embedded in Excel.
|
||||
Users can include user-defined functions and macro code within spreadsheets.
|
||||
|
||||
:::note pass
|
||||
The `vbaraw` property of the SheetJS workbook object is an encoded data blob
|
||||
which includes the VBA macros and other metadata.
|
||||
|
||||
The SheetJS `read` and `readFile` methods do not pull VBA metadata by default.
|
||||
If the `bookVBA` option is set to true, the `vbaraw` blob is created.
|
||||
|
||||
```js
|
||||
var workbook = XLSX.read(data, { bookVBA: true });
|
||||
var encoded_vba_blob = workbook.vbaraw;
|
||||
```
|
||||
|
||||
The SheetJS `write` and `writeFile` methods will save the `vbaraw` blob if it is
|
||||
present in the workbook object and if the output file format supports macros.
|
||||
|
||||
```js
|
||||
workbook.vbaraw = encoded_vba_blob;
|
||||
XLSX.writeFile(workbook, "SheetJSNewMacro.xlsm");
|
||||
```
|
||||
|
||||
:::info pass
|
||||
|
||||
Newer versions of Excel support a new JavaScript API for writing user-defined
|
||||
functions. Those addins are not stored in the spreadsheet files.
|
||||
|
||||
[The "Excel JavaScript API" demo](/docs/demos/extensions/excelapi) covers usage
|
||||
of SheetJS libraries within the API.
|
||||
|
||||
:::
|
||||
|
||||
:::tip pass
|
||||
|
||||
The `vbaraw` property stores raw bytes. [SheetJS Pro](https://sheetjs.com/pro)
|
||||
offers a special component for extracting macro text from the VBA blob, editing
|
||||
@ -89,7 +113,7 @@ function SheetJSVBAFormula() { return ( <button onClick={async () => {
|
||||
workbook.vbaraw = blob;
|
||||
|
||||
/* create an XLSM file and try to save to SheetJSVBANeu.xlsm */
|
||||
XLSX.writeFile(workbook, "SheetJSVBANeu.xlsm", { bookVBA: true });
|
||||
XLSX.writeFile(workbook, "SheetJSVBANeu.xlsm");
|
||||
}}><b>Click to Generate file!</b></button> ); }
|
||||
```
|
||||
|
||||
@ -129,7 +153,7 @@ XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
|
||||
workbook.vbaraw = blob;
|
||||
|
||||
/* create an XLSM file and try to save to SheetJSVBANeu.xlsm */
|
||||
XLSX.writeFile(workbook, "SheetJSVBANeu.xlsm", { bookVBA: true });
|
||||
XLSX.writeFile(workbook, "SheetJSVBANeu.xlsm");
|
||||
})();
|
||||
```
|
||||
|
||||
@ -214,7 +238,6 @@ To ensure the writers export the VBA blob:
|
||||
|
||||
- The output format must support VBA (`xlsm` or `xlsb` or `xls` or `biff8`)
|
||||
- The workbook object must have a valid `vbaraw` field
|
||||
- The `write` or `writeFile` call must include the option `bookVBA: true`
|
||||
|
||||
This example uses [`vbaProject.bin`](pathname:///vba/vbaProject.bin) from the
|
||||
[sample file](pathname:///vba/SheetJSVBAFormula.xlsm):
|
||||
@ -241,7 +264,7 @@ function SheetJSVBAPrepared() { return ( <button onClick={async () => {
|
||||
workbook.vbaraw = blob;
|
||||
|
||||
/* create an XLSM file and try to save to SheetJSVBAPreparedNeu.xlsm */
|
||||
XLSX.writeFile(workbook, "SheetJSVBAPreparedNeu.xlsm", { bookVBA: true });
|
||||
XLSX.writeFile(workbook, "SheetJSVBAPreparedNeu.xlsm");
|
||||
}}><b>Click to Generate file!</b></button> ); }
|
||||
```
|
||||
|
||||
|
@ -3,8 +3,7 @@ title: Row Properties
|
||||
sidebar_position: 8
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary><b>File Format Support</b> (click to show)</summary>
|
||||
<details><summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
By default, all rows in a workbook are "Visible" and have a standard height.
|
||||
|
||||
|
@ -3,8 +3,7 @@ title: Column Properties
|
||||
sidebar_position: 9
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary><b>File Format Support</b> (click to show)</summary>
|
||||
<details><summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
By default, all columns in a workbook are "Visible" and have a standard width.
|
||||
|
||||
|
@ -3,8 +3,7 @@ title: Sheet Visibility
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
<details>
|
||||
<summary><b>File Format Support</b> (click to show)</summary>
|
||||
<details><summary><b>File Format Support</b> (click to show)</summary>
|
||||
|
||||
By default, all sheets in a workbook are "Visible". The standard "Hidden" state
|
||||
is controlled through the context menu in the sheet tab bar. The "Very Hidden"
|
||||
@ -20,13 +19,13 @@ state is controlled through the "Visibility" property in the VBA editor.
|
||||
|
||||
</details>
|
||||
|
||||
Excel enables hiding sheets in the lower tab bar. The sheet data is stored in
|
||||
the file but the UI does not readily make it available.
|
||||
Excel can hide sheet tabs from the lower tab bar. The sheet data is stored in
|
||||
the file but the tabs are not displayed until they are unhidden.
|
||||
|
||||
Standard "hidden" sheets are revealed in the "Unhide" menu.
|
||||
Standard "hidden" sheets are listed in the "Unhide" menu.
|
||||
|
||||
Excel also has "very hidden" sheets which cannot be revealed in the menu. They
|
||||
are only accessible in the VB Editor!
|
||||
Excel "very hidden" sheets cannot be revealed in the menu. They are only visible
|
||||
in the Visual Basic Editor!
|
||||
|
||||
## Storage
|
||||
|
||||
|
BIN
docz/static/comments/types.png
Normal file
BIN
docz/static/comments/types.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 163 KiB |
BIN
docz/static/hyperlink/tooltip.png
Normal file
BIN
docz/static/hyperlink/tooltip.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
Loading…
Reference in New Issue
Block a user