forked from sheetjs/docs.sheetjs.com
localstorage
This commit is contained in:
parent
d54a1e4ee0
commit
dbe0554b9b
@ -4,8 +4,10 @@ pagination_prev: demos/desktop/index
|
||||
pagination_next: demos/grid
|
||||
---
|
||||
|
||||
At the time of writing (2023 February 15), Airtable recommends Personal Access
|
||||
Tokens for interacting with the official API.
|
||||
Airtable recommends Personal Access Tokens for interacting with their API. When
|
||||
fetching data from the API, the result will include an array of row objects that
|
||||
can be converted to a worksheet with `XLSX.utils.json_to_sheet`. The API methods
|
||||
to write data will accept row objects generated by `XLSX.utils.sheet_to_json`.
|
||||
|
||||
## NodeJS Integration
|
||||
|
||||
@ -76,6 +78,13 @@ async function airtable_load_worksheet(table, worksheet) {
|
||||
|
||||
## Complete Example
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last tested on 2023 February 15. At the time, it was possible to
|
||||
create a free account with API access.
|
||||
|
||||
:::
|
||||
|
||||
0) Create a free Airtable account.
|
||||
|
||||
### Personal Access Token
|
||||
|
@ -9,23 +9,80 @@ sidebar_custom_props:
|
||||
The Storage API, encompassing `localStorage` and `sessionStorage`, describes
|
||||
simple key-value stores that only support string values and keys.
|
||||
|
||||
Arrays of objects can be stored using `JSON.stringify` using row index as key:
|
||||
This demo covers two common use patterns:
|
||||
|
||||
- "Row Objects" shows a simple convention for loading and storing row objects
|
||||
- "Simple Strings" discusses how to persist and recover a raw Storage
|
||||
|
||||
## Row Objects
|
||||
|
||||
Consider the following array of objects of data:
|
||||
|
||||
```js
|
||||
const aoo = XLSX.utils.sheet_to_json(ws);
|
||||
for(var i = 0; i < aoo.length; ++i) localStorage.setItem(i, JSON.stringify(aoo[i]));
|
||||
[
|
||||
{ Name: "Barack Obama", Index: 44 },
|
||||
{ Name: "Donald Trump", Index: 45 },
|
||||
{ Name: "Joseph Biden", Index: 46 }
|
||||
]
|
||||
```
|
||||
|
||||
Recovering the array of objects is possible by using `JSON.parse`:
|
||||
Storage API expects values to be strings. The simplest approach is to stringify
|
||||
row objects using `JSON.stringify` and store using the row index as a key:
|
||||
|
||||
| Key | Value |
|
||||
|:---:|:-------------------------------------|
|
||||
| 0 | `{"Name":"Barack Obama","Index":44}` |
|
||||
| 1 | `{"Name":"Donald Trump","Index":45}` |
|
||||
| 2 | `{"Name":"Joseph Biden","Index":46}` |
|
||||
|
||||
#### Importing Data
|
||||
|
||||
Starting from a worksheet, `XLSX.utils.sheet_to_json` generates an array of row
|
||||
objects. `localStorage.setItem` will store data in Local Storage:
|
||||
|
||||
```js
|
||||
const aoo = [];
|
||||
for(var i = 0; i < localStorage.length; ++i) aoo.push(JSON.parse(localStorage.getItem(i)));
|
||||
const ws = XLSX.utils.json_to_sheet(aoo);
|
||||
function sheet_to_localStorage(worksheet) {
|
||||
const aoo = XLSX.utils.sheet_to_json(worksheet);
|
||||
for(let i = 0; i < aoo.length; ++i) {
|
||||
localStorage.setItem(i, JSON.stringify(aoo[i]));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This example will fetch <https://sheetjs.com/data/cd.xls>, fill `localStorage` with
|
||||
rows, then generate a worksheet from the rows and write to a new file.
|
||||
#### Exporting Data
|
||||
|
||||
`localStorage.length` returns the total number of entries. A simple `for` loop
|
||||
can cover the keys (integers from `0` to `localStorage.length - 1` inclusive)
|
||||
|
||||
`localStorage.getItem` will load the stringified data from the Local Storage. A
|
||||
new array of objects can be constructed by using `JSON.parse` and pushing to an
|
||||
array. `XLSX.utils.json_to_sheet` can create a new worksheet from that array:
|
||||
|
||||
```js
|
||||
function localStorage_to_sheet() {
|
||||
const aoo = [];
|
||||
for(let i = 0; i < localStorage.length; ++i) {
|
||||
aoo.push(JSON.parse(localStorage.getItem(i)));
|
||||
}
|
||||
return XLSX.utils.json_to_sheet(aoo);
|
||||
}
|
||||
```
|
||||
|
||||
### Live Demo
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last tested on 2023 February 26.
|
||||
|
||||
:::
|
||||
|
||||
This example will fetch <https://sheetjs.com/pres.numbers>, fill `localStorage`
|
||||
with rows, then generate a worksheet from the rows and write to a new file.
|
||||
|
||||
After saving the exported file, the Local Storage can be inspected in the
|
||||
"Local Storage" section of the "Application" Tab of Developer Tools:
|
||||
|
||||
![Local Storage view in Developer Tools](pathname:///storageapi/lstorage.png)
|
||||
|
||||
:::caution
|
||||
|
||||
@ -36,14 +93,13 @@ is strongly recommended to convert that array to a worksheet directly.
|
||||
|
||||
```jsx live
|
||||
function SheetJStorage() {
|
||||
const [url, setUrl] = React.useState("https://sheetjs.com/data/cd.xls");
|
||||
const [url, setUrl] = React.useState("https://sheetjs.com/pres.numbers");
|
||||
const set_url = React.useCallback((evt) => setUrl(evt.target.value));
|
||||
const [out, setOut] = React.useState("");
|
||||
const xport = React.useCallback(async() => {
|
||||
// get first worksheet data as array of objects
|
||||
const ab = await (await fetch(url)).arrayBuffer();
|
||||
const wb = XLSX.read(ab), wsname = wb.SheetNames[0];
|
||||
const aoo = XLSX.utils.sheet_to_json(wb.Sheets[wsname]);
|
||||
const wb = XLSX.read(await (await fetch(url)).arrayBuffer());
|
||||
const aoo = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]]);
|
||||
|
||||
// reset and populate localStorage
|
||||
localStorage.clear();
|
||||
@ -65,9 +121,59 @@ function SheetJStorage() {
|
||||
XLSX.writeFile(new_wb, "SheetJStorage.xlsx");
|
||||
});
|
||||
|
||||
return ( <> {out && (<><a href={url}>{url}</a><pre>{out}</pre></>)}
|
||||
return ( <>
|
||||
{out && (<><a href={url}>{url}</a><pre>{out}</pre></>)}
|
||||
<b>URL: </b><input type="text" value={url} onChange={set_url} size="50"/>
|
||||
<br/><button onClick={xport}><b>Fetch!</b></button>
|
||||
</> );
|
||||
}
|
||||
```
|
||||
|
||||
## Simple Strings
|
||||
|
||||
The ["Row Objects" approach](#row-objects) is strongly recommended when trying
|
||||
to store or recover arrays of row objects.
|
||||
|
||||
When the goal is to save an existing Storage, the general representation is an
|
||||
array of pairs. Consider the following data in Local Storage:
|
||||
|
||||
| Key | Value |
|
||||
|:---:|:----------|
|
||||
| "b" | "Logical" |
|
||||
| "n" | "Numeric" |
|
||||
| "s" | "Textual" |
|
||||
|
||||
The natural representation is an array of arrays:
|
||||
|
||||
```js
|
||||
[
|
||||
[ "b", "Logical" ],
|
||||
[ "n", "Numeric" ],
|
||||
[ "s", "Textual" ]
|
||||
]
|
||||
```
|
||||
|
||||
#### Exporting Storage
|
||||
|
||||
In modern browsers, `Object.entries` will generate an array of key/value pairs.
|
||||
`XLSX.utils.aoa_to_sheet` will interpret that array as a worksheet with 2 cols:
|
||||
|
||||
```js
|
||||
function localStorage_to_ws() {
|
||||
const aoa = Object.entries(localStorage);
|
||||
return XLSX.utils.aoa_to_sheet(aoa);
|
||||
}
|
||||
```
|
||||
|
||||
#### Importing Storage
|
||||
|
||||
In the other direction, the worksheet is assumed to store keys in column A and
|
||||
values in column B. `XLSX.utils.sheet_to_json` with the `header: 1` option
|
||||
will generate key/value pairs that can be assigned to a storage:
|
||||
|
||||
```js
|
||||
function ws_to_localStorage(ws) {
|
||||
const aoa = XLSX.utils.sheet_to_json(ws, { header: 1 });
|
||||
aoa.forEach(([key, val]) => localStorage.setItem(key, val));
|
||||
}
|
||||
```
|
||||
|
@ -125,23 +125,34 @@ importScripts("https://cdn.sheetjs.com/xlsx-latest/package/dist/xlsx.full.min.js
|
||||
|
||||
For production use, it is highly encouraged to download and host the script.
|
||||
|
||||
<details><summary><b>ECMAScript Module Support</b> (click to show)</summary>
|
||||
<details open><summary><b>ECMAScript Module Support</b> (click to hide)</summary>
|
||||
|
||||
:::note Browser Compatibility
|
||||
|
||||
ESM is supported in Web Workers in the Chromium family of browsers (including
|
||||
Chrome and Edge) as well as in browsers powered by WebKit (including Safari).
|
||||
|
||||
For support in legacy browsers like Firefox, `importScripts` should be used.
|
||||
For legacy browsers like Firefox and IE, `importScripts` should be used.
|
||||
|
||||
:::
|
||||
|
||||
Browser ESM imports require a complete URL including the `.mjs` extension:
|
||||
|
||||
```js
|
||||
import * as XLSX from "https://cdn.sheetjs.com/xlsx-latest/package/xlsx.mjs";
|
||||
```
|
||||
|
||||
When using modules, the script must be served with the correct MIME type and the
|
||||
Worker constructor must set the `type` option:
|
||||
When using Worker ESM, the Worker constructor must set the `type` option:
|
||||
|
||||
```js
|
||||
const worker = new Worker(
|
||||
url_to_worker_script,
|
||||
// highlight-next-line
|
||||
{ type: "module" } // second argument to Worker constructor
|
||||
);
|
||||
```
|
||||
|
||||
Inline workers additionally require the Blob MIME type `text/javascript`:
|
||||
|
||||
```js
|
||||
const worker_code = `\
|
||||
@ -158,13 +169,15 @@ const worker = new Worker(
|
||||
)
|
||||
),
|
||||
// highlight-next-line
|
||||
{type: "module"} // second argument to Worker constructor
|
||||
{ type: "module" } // second argument to Worker constructor
|
||||
);
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Downloading a Remote File
|
||||
## Live Demos
|
||||
|
||||
### Downloading a Remote File
|
||||
|
||||
:::note fetch in Web Workers
|
||||
|
||||
@ -252,7 +265,7 @@ self.addEventListener('message', async(e) => {
|
||||
|
||||
</details>
|
||||
|
||||
## Creating a Local File
|
||||
### Creating a Local File
|
||||
|
||||
:::caution Writing files from Web Workers
|
||||
|
||||
@ -357,7 +370,7 @@ self.addEventListener('message', async(e) => {
|
||||
|
||||
</details>
|
||||
|
||||
## User-Submitted File
|
||||
### User-Submitted File
|
||||
|
||||
:::note FileReaderSync
|
||||
|
||||
@ -375,9 +388,9 @@ sequenceDiagram
|
||||
actor User
|
||||
participant Page
|
||||
participant Worker
|
||||
User->>Page: click button
|
||||
User->>Page: submit file
|
||||
activate Page
|
||||
Page->>Worker: send URL
|
||||
Page->>Worker: send pointer
|
||||
deactivate Page
|
||||
activate Worker
|
||||
Note over Worker: fetch file
|
||||
@ -454,7 +467,7 @@ self.addEventListener('message', (e) => {
|
||||
|
||||
</details>
|
||||
|
||||
## Streaming Write
|
||||
### Streaming Write
|
||||
|
||||
A more general discussion, including row-oriented processing demos, is included
|
||||
in the ["Large Datasets"](/docs/demos/stream#browser) demo.
|
||||
|
BIN
docz/static/storageapi/lstorage.png
Normal file
BIN
docz/static/storageapi/lstorage.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 99 KiB |
Loading…
Reference in New Issue
Block a user