forked from sheetjs/docs.sheetjs.com
		
	standalone
This commit is contained in:
		
							parent
							
								
									4c191dcc59
								
							
						
					
					
						commit
						584af134db
					
				| @ -28,14 +28,13 @@ new versions are released! | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| :::warning | ||||
| :::warning pass | ||||
| 
 | ||||
| A number of services host older versions of the SheetJS libraries.  Due to | ||||
| syncing issues, they are generally out of date. | ||||
| 
 | ||||
| They are known CDN bugs. | ||||
| 
 | ||||
| <https://cdn.sheetjs.com/> is the authoritative source for SheetJS modules. | ||||
| **The SheetJS CDN** <https://cdn.sheetjs.com/> **is the authoritative source** | ||||
| **for SheetJS scripts** | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| @ -67,6 +66,23 @@ scratch, a single script tag should be added at the top of the HTML page: | ||||
| 
 | ||||
| </details> | ||||
| 
 | ||||
| ### Vendoring | ||||
| 
 | ||||
| For general stability, "vendoring" scripts is the recommended approach: | ||||
| 
 | ||||
| <p>1) Download the script (<code parentName="pre">xlsx.full.min.js</code>) for | ||||
|    the desired version. The current version is available at <a href={`https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}>https://cdn.sheetjs.com/xlsx-{current}/package/dist/xlsx.full.min.js</a></p> | ||||
| 
 | ||||
| 2) Move the script to a `public` folder with other scripts. | ||||
| 
 | ||||
| 3) Reference the local script from HTML pages: | ||||
| 
 | ||||
| ```html | ||||
| <script src="/public/xlsx.full.min.js"></script> | ||||
| ``` | ||||
| 
 | ||||
| This script assigns to `window.XLSX`. The global can be used in other scripts. | ||||
| 
 | ||||
| ### Internet Explorer and Older Browsers | ||||
| 
 | ||||
| For broad compatibility with JavaScript engines, the library is written using | ||||
| @ -104,11 +120,11 @@ importScripts("https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.mi | ||||
| 
 | ||||
| ## ECMAScript Module Imports | ||||
| 
 | ||||
| :::caution | ||||
| :::caution pass | ||||
| 
 | ||||
| This section refers to imports using `script type="module"`.  For imports in | ||||
| modern projects using Webpack or React or Angular or VueJS, the installation is | ||||
| described [in the next section](/docs/getting-started/installation/frameworks). | ||||
| described [in "Frameworks and Bundlers"](/docs/getting-started/installation/frameworks). | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| @ -132,15 +148,19 @@ set_cptable(cptable); | ||||
| </script>`} | ||||
| </CodeBlock> | ||||
| 
 | ||||
| Dynamic imports with `import()` can be used in data export scenarios.  This | ||||
| example will download the library only when the export button is pressed: | ||||
| Web Worker support is noted in [the "Web Workers" demo](/docs/demos/bigdata/worker#installation) | ||||
| 
 | ||||
| ### Dynamic Imports | ||||
| 
 | ||||
| Dynamic imports with `import()` will only download the SheetJS scripts when they | ||||
| are used. This example will download the library when data is exported: | ||||
| 
 | ||||
| <CodeBlock language="html">{`\ | ||||
| <button id="xport">Export</button> | ||||
| <script type="module"> | ||||
| xport.addEventListener("click", async() => { | ||||
| \n\ | ||||
|   /* dynamically import the library in the event listener */ | ||||
|   /* dynamically import the script in the event listener */ | ||||
|   // highlight-next-line | ||||
|   const XLSX = await import("https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs"); | ||||
| \n\ | ||||
| @ -152,11 +172,38 @@ xport.addEventListener("click", async() => { | ||||
| </script>`} | ||||
| </CodeBlock> | ||||
| 
 | ||||
| Web Worker support is noted in [the demo](/docs/demos/bigdata/worker#installation) | ||||
| :::caution pass | ||||
| 
 | ||||
| The callback functions must be marked as `async` and the script block must have | ||||
| the attribute `type="module"` | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| If Encoding support is required, `cpexcel.full.mjs` must be manually imported: | ||||
| 
 | ||||
| <CodeBlock language="html">{`\ | ||||
| <button id="xport">Export</button> | ||||
| <script type="module"> | ||||
| xport.addEventListener("click", async() => { | ||||
| \n\ | ||||
|   /* dynamically import the scripts in the event listener */ | ||||
|   // highlight-start | ||||
|   const XLSX = await import("https://cdn.sheetjs.com/xlsx-${current}/package/xlsx.mjs"); | ||||
|   const cptable = await import("https://cdn.sheetjs.com/xlsx-${current}/package/dist/cpexcel.full.mjs"); | ||||
|   XLSX.set_cptable(cptable); | ||||
|   // highlight-end | ||||
| \n\ | ||||
|   const wb = XLSX.utils.book_new(); | ||||
|   const ws = XLSX.utils.aoa_to_sheet([["a","b","c"],[1,2,3]]); | ||||
|   XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); | ||||
|   XLSX.writeFile(wb, "SheetJSESMTest.xlsx"); | ||||
| }); | ||||
| </script>`} | ||||
| </CodeBlock> | ||||
| 
 | ||||
| ## Bower | ||||
| 
 | ||||
| :::caution | ||||
| :::warning pass | ||||
| 
 | ||||
| Bower is deprecated and the maintainers recommend using other tools. | ||||
| 
 | ||||
|  | ||||
| @ -51,7 +51,7 @@ This demo was tested in the following environments: | ||||
| | Windows 10     | x64  | `v0.71.25`  | 2023-07-24 | | ||||
| | Windows 11     | x64  | `v0.71.11`  | 2023-05-11 | | ||||
| | MacOS 12.6     | x64  | `v0.71.26`  | 2023-07-23 | | ||||
| | MacOS 13.4     | arm  | `v0.71.18`  | 2023-07-06 | | ||||
| | MacOS 13.4     | ARM  | `v0.71.18`  | 2023-07-06 | | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,7 @@ | ||||
| --- | ||||
| title: Redis | ||||
| 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_next: demos/local/index | ||||
| sidebar_custom_props: | ||||
| @ -9,6 +11,18 @@ sidebar_custom_props: | ||||
| import current from '/version.js'; | ||||
| import CodeBlock from '@theme/CodeBlock'; | ||||
| 
 | ||||
| [Redis](https://redis.io/) is a open source in-memory data store. It is capable | ||||
| of storing sets, lists and other simple data structures. | ||||
| 
 | ||||
| [SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing | ||||
| data from spreadsheets. | ||||
| 
 | ||||
| This demo defines a schema for storing Redis databases in spreadsheets. We'll | ||||
| explore how to use SheetJS and Redis NodeJS connector modules to pull data | ||||
| from XLSX files to a Redis database and to serialize a database to a workbook. | ||||
| 
 | ||||
| #### Overview | ||||
| 
 | ||||
| Redis has 5 core data types: "String", List", "Set", "Sorted Set", and "Hash". | ||||
| Since the keys and values are limited to simple strings (and numbers), it is | ||||
| possible to store complete databases in a single worksheet. | ||||
| @ -17,7 +31,7 @@ possible to store complete databases in a single worksheet. | ||||
| 
 | ||||
| ## Integration Details | ||||
| 
 | ||||
| :::note | ||||
| :::note pass | ||||
| 
 | ||||
| [`SheetJSRedis.mjs`](pathname:///nosql/SheetJSRedis.mjs) exports the methods: | ||||
| - `redis_to_ws` creates a SheetJS worksheet by querying a redis client | ||||
| @ -25,11 +39,32 @@ possible to store complete databases in a single worksheet. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| The first row holds the data type and the second row holds the property name. | ||||
| ### Array of Arrays | ||||
| 
 | ||||
| The "Exporting Data" snippets generate arrays of arrays that can be added to a | ||||
| worksheet using `sheet_add_aoa`.  Since the data is column-oriented, the goal is | ||||
| to add the data starting in the first row of the column after the data: | ||||
| The shared data representation is an "array of arrays"[^1]. Each array within | ||||
| the structure corresponds to one row. | ||||
| 
 | ||||
| The Redis to SheetJS converter generates an array of arrays of the data by | ||||
| running queries to fetch data from the database. The SheetJS `aoa_to_sheet` and | ||||
| `sheet_add_aoa`[^2] methods build up worksheets from arrays of arrays. Once the | ||||
| worksheet is created, it can be added to a SheetJS workbook object[^3] and | ||||
| exported using `writeFile`[^4]. | ||||
| 
 | ||||
| The SheetJS to Redis converter works in reverse. Workbook files are parsed with | ||||
| the SheetJS `readFile` method[^5] and the desired worksheet is pulled from the | ||||
| workbook object. An array of arrays can be created with the `sheet_to_json`[^6] | ||||
| utility function. The data structure can be scanned to generate Redis queries. | ||||
| 
 | ||||
| ### Appending Columns | ||||
| 
 | ||||
| Since the data is column-oriented, the goal is to add the data starting on the | ||||
| first row of the column after the data. | ||||
| 
 | ||||
| To calculate the starting point for writing data, SheetJS provides `encode_cell` | ||||
| and `decode_range` utility functions for working with addresses and ranges[^7]. | ||||
| 
 | ||||
| The following snippet takes an array of arrays of values and writes the values | ||||
| to a worksheet starting from the column after the worksheet range: | ||||
| 
 | ||||
| ```js | ||||
| function add_aoa_to_next_column(worksheet, aoa) { | ||||
| @ -45,14 +80,7 @@ function add_aoa_to_next_column(worksheet, aoa) { | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| The "Importing Data" snippets generate redis queries. The `ws_to_redis` function | ||||
| first generates an array of arrays with `sheet_to_json`: | ||||
| 
 | ||||
| ```js | ||||
| const aoa = XLSX.utils.sheet_to_json(worksheet, { header: 1 }); | ||||
| ``` | ||||
| 
 | ||||
| #### Strings | ||||
| ### Strings | ||||
| 
 | ||||
| Strings can be stored in a unified String table. The first column holds keys | ||||
| and the second column holds values: | ||||
| @ -67,7 +95,11 @@ XXX|    A    |   B   | | ||||
| ``` | ||||
| 
 | ||||
| The SheetJS array-of-arrays representation of the string table is an array of | ||||
| key/value pairs: | ||||
| key/value pairs. | ||||
| 
 | ||||
| The pairs can be generated from Redis by querying for all of the keys using the | ||||
| `KEYS`[^8] method, testing if the corresponding value is a string using the | ||||
| `TYPE`[^9] method, and fetching string values using the `GET`[^10] method: | ||||
| 
 | ||||
| ```js | ||||
| const aoa = ["Strings"]; aoa.length = 2; // [ "Strings", empty ] | ||||
| @ -80,7 +112,7 @@ for(let key of keys) { | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| #### Lists | ||||
| ### Lists | ||||
| 
 | ||||
| Lists are unidimensional and can be stored in their own columns. | ||||
| 
 | ||||
| @ -94,15 +126,18 @@ XXX|    C    | | ||||
| ``` | ||||
| 
 | ||||
| The SheetJS array-of-arrays representation of lists is a column of values. | ||||
| `LRANGE` returns a simple array of values. `sheet_add_aoa` interprets the result | ||||
| as one row. The code transposes the result with `values.map(v => [v])`. | ||||
| 
 | ||||
| Redis `LRANGE`[^11] returns a simple array of values. `sheet_add_aoa` interprets | ||||
| the result as one row, so the data should be transposed. | ||||
| 
 | ||||
| The code transposes the result with `values.map(v => [v])`. | ||||
| 
 | ||||
| ```js | ||||
| const values = await client.LRANGE(key, 0, -1); | ||||
| const aoa = [ ["List"], [key] ].concat(values.map(v => [v])); | ||||
| ``` | ||||
| 
 | ||||
| #### Sets | ||||
| ### Sets | ||||
| 
 | ||||
| Sets are unidimensional and can be stored in their own columns. | ||||
| 
 | ||||
| @ -116,15 +151,18 @@ XXX|   D   | | ||||
| ``` | ||||
| 
 | ||||
| The SheetJS array-of-arrays representation of sets is a column of values. | ||||
| `SMEMBERS` returns a simple array of values. `sheet_add_aoa` interprets result | ||||
| as one row. The code transposes the result with `values.map(v => [v])`. | ||||
| 
 | ||||
| Redis `SMEMBERS`[^12] returns an array of values. `sheet_add_aoa` interprets the | ||||
| result as one row, so the data should be transposed. | ||||
| 
 | ||||
| The code transposes the result with `values.map(v => [v])`. | ||||
| 
 | ||||
| ```js | ||||
| const values = await client.SMEMBERS(key); | ||||
| const aoa = [ ["Set"], [key] ].concat(values.map(v => [v])); | ||||
| ``` | ||||
| 
 | ||||
| #### Sorted Sets | ||||
| ### Sorted Sets | ||||
| 
 | ||||
| Sorted Sets have an associated score which can be stored in the second column. | ||||
| 
 | ||||
| @ -138,14 +176,15 @@ XXX|    E    | F | | ||||
| ``` | ||||
| 
 | ||||
| The SheetJS array-of-arrays representation is an array of key/score pairs. | ||||
| `ZRANGE_WITHSCORES` returns an array of objects which can be reshaped. | ||||
| 
 | ||||
| `ZRANGE_WITHSCORES`[^13] returns an array of objects which can be reshaped. | ||||
| 
 | ||||
| ```js | ||||
| const values = await client.ZRANGE_WITHSCORES(key, 0, -1); | ||||
| const aoa = [ ["Sorted"], [key] ].concat(values.map(v => [v.value, v.score])); | ||||
| ``` | ||||
| 
 | ||||
| #### Hashes | ||||
| ### Hashes | ||||
| 
 | ||||
| Hashes are stored like the string table, with key and value columns in order. | ||||
| 
 | ||||
| @ -159,7 +198,8 @@ XXX|   G   |   H   | | ||||
| ``` | ||||
| 
 | ||||
| The SheetJS array-of-arrays representation is an array of key/value pairs. | ||||
| `HGETALL` returns a plain object which can be converted using `Object.entries`: | ||||
| 
 | ||||
| `HGETALL`[^14] returns an object which can be converted using `Object.entries`: | ||||
| 
 | ||||
| ```js | ||||
| const values = await client.HGETALL(key); | ||||
| @ -170,8 +210,8 @@ const aoa = [ ["Hash"], [key] ].concat(Object.entries(values)); | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| This demo was last tested on 2023 May 11 with Redis 7.0.11, Redis connector | ||||
| module 4.6.6 and NodeJS 20.1.0. | ||||
| This demo was last tested on 2023 August 22 with Redis 7.2.0, Redis connector | ||||
| module 4.6.7 and NodeJS 20.5.1. | ||||
| 
 | ||||
| ::: | ||||
| 
 | ||||
| @ -187,10 +227,10 @@ this demo also requires NodeJS version 18 or later. | ||||
| 
 | ||||
| :::note | ||||
| 
 | ||||
| This demo was last tested on Intel macOS.  Redis was installed with: | ||||
| This demo was last tested on macOS.  Redis was installed with: | ||||
| 
 | ||||
| ```bash | ||||
| brew install redis@7.0.11 | ||||
| brew install redis | ||||
| ``` | ||||
| 
 | ||||
| The following command started the server process: | ||||
| @ -214,7 +254,7 @@ curl -LO https://docs.sheetjs.com/nosql/SheetJSRedisTest.mjs | ||||
| 2) Install dependencies: | ||||
| 
 | ||||
| <CodeBlock language="bash">{`\ | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz redis@4.6.6`} | ||||
| npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz redis@4.6.7`} | ||||
| </CodeBlock> | ||||
| 
 | ||||
| 3) Run the test script: | ||||
| @ -226,3 +266,18 @@ node SheetJSRedisTest.mjs | ||||
| Inspect the output and compare with the data in `SheetJSRedisTest.mjs`. | ||||
| 
 | ||||
| Open `SheetJSRedis.xlsx` and verify the columns have the correct data | ||||
| 
 | ||||
| [^1]: See ["Array of Arrays" in "Utility Functions"](/docs/api/utilities/array#array-of-arrays) | ||||
| [^2]: See ["Array of Arrays Input" in "Utility Functions"](/docs/api/utilities/array#array-of-arrays-input). | ||||
| [^3]: See ["Workbook Helpers" in "Utility Functions"](/docs/api/utilities/wb) | ||||
| [^4]: See [`writeFile` in "Writing Files"](/docs/api/write-options) | ||||
| [^5]: See [`readFile` in "Reading Files"](/docs/api/parse-options) | ||||
| [^6]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output) | ||||
| [^7]: See ["Utilities" in "Addresses and Ranges"](/docs/csf/general#utilities) | ||||
| [^8]: See [`KEYS`](https://redis.io/commands/keys/) in the Redis documentation. | ||||
| [^9]: See [`TYPE`](https://redis.io/commands/type/) in the Redis documentation. | ||||
| [^10]: See [`GET`](https://redis.io/commands/get/) in the Redis documentation. | ||||
| [^11]: See [`LRANGE`](https://redis.io/commands/lrange/) in the Redis documentation. | ||||
| [^12]: See [`SMEMBERS`](https://redis.io/commands/smembers/) in the Redis documentation. | ||||
| [^13]: The official command is [`ZRANGE`](https://redis.io/commands/zrange/). `ZRANGE_WITHSCORES` is a special command supported by the NodeJS wrapper. | ||||
| [^14]: See [`HGETALL`](https://redis.io/commands/hgetall/) in the Redis documentation. | ||||
|  | ||||
| @ -40,9 +40,9 @@ These instructions were tested on the following platforms: | ||||
| | Platform                      | Test Date  | | ||||
| |:------------------------------|:-----------| | ||||
| | Linux (Steam Deck Holo 3.4.8) | 2023-07-12 | | ||||
| | Linux (Ubuntu 18.04 aarch64)  | 2023-04-13 | | ||||
| | Linux (Ubuntu 18.04 AArch64)  | 2023-04-13 | | ||||
| | MacOS 10.13 (x64)             | 2023-04-04 | | ||||
| | MacOS 13.0 (arm64)            | 2023-04-13 | | ||||
| | MacOS 13.0 (ARM64)            | 2023-04-13 | | ||||
| | Windows 10 (x64) + WSL Ubuntu | 2023-07-23 | | ||||
| | Windows 11 (x64) + WSL Ubuntu | 2023-04-04 | | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user