This commit is contained in:
SheetJS 2023-10-13 06:04:30 -04:00
parent e1402a8424
commit 45d0ed0e13
15 changed files with 402 additions and 105 deletions

@ -47,22 +47,22 @@ export default function BasicTable() {
:::note
This demo was last run on 2023 May 11 against Material UI 5.13.0 paired with
Emotion 11.11.0
This demo was last run on 2023 October 12 against Material UI 5.14.13 paired
with Emotion 11.11.1
:::
1) Create a new TypeScript `create-react-app` app:
1) Create a new app using `vite`:
```bash
npx create-react-app sheetjs-mui --template typescript
npm create vite@latest sheetjs-mui -- --template react-ts
cd sheetjs-mui
```
2) Install dependencies:
<CodeBlock language="bash">{`\
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/material@5.13.0 @emotion/react@11.11.0 @emotion/styled@11.11.0`}
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/material@5.14.13 @emotion/react@11.11.1 @emotion/styled@11.11.0`}
</CodeBlock>
3) Download [`App.tsx`](pathname:///mui/table/App.tsx) and replace `src/App.tsx`.
@ -74,7 +74,7 @@ curl -L -o src/App.tsx https://docs.sheetjs.com/mui/table/App.tsx
4) Start the development server:
```bash
npm start
npm run dev
```
The script should open the live demo in a web browser. Click the "Export" button
@ -194,22 +194,22 @@ export default function App() {
:::note
This demo was last run on 2023 May 11 against MUI data grid 6.3.1 paired with
Emotion 11.11.0
This demo was last run on 2023 October 12 against MUI data grid 6.3.1 paired
with Emotion 11.11.1
:::
1) Create a new TypeScript `create-react-app` app:
1) Create a new app using `vite`:
```bash
npx create-react-app sheetjs-muidg --template typescript
npm create vite@latest sheetjs-muidg -- --template react-ts
cd sheetjs-muidg
```
2) Install dependencies:
<CodeBlock language="bash">{`\
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/x-data-grid @emotion/react @emotion/styled`}
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz @mui/x-data-grid@6.16.1 @emotion/react@11.11.1 @emotion/styled@11.11.0`}
</CodeBlock>
3) Download [`App.tsx`](pathname:///mui/dg/App.tsx) and replace `src/App.tsx`.
@ -221,7 +221,7 @@ curl -L -o src/App.tsx https://docs.sheetjs.com/mui/dg/App.tsx
4) Start the development server:
```bash
npm start
npm run dev
```
When the page loads, it will fetch and process <https://sheetjs.com/pres.numbers>

@ -30,7 +30,7 @@ download and parse remote workbook files.
- ["Local Files"](#local-files) uses native libraries to read and write files on
the device.
The "Complete Example" creates an app that looks like the screenshots below:
The "Local Files" example creates an app that looks like the screenshots below:
<table><thead><tr>
<th><a href="#demo">iOS</a></th>

@ -1,5 +1,6 @@
---
title: NativeScript
title: Native Sheets in NativeScript
sidebar_label: NativeScript
pagination_prev: demos/static/index
pagination_next: demos/desktop/index
sidebar_position: 2
@ -10,14 +11,25 @@ sidebar_custom_props:
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
imported from any component or script in the app.
export const g = {style: {color:"green"}};
export const r = {style: {color:"red"}};
export const y = {style: {color:"yellow"}};
[NativeScript](https://nativescript.org/) is a mobile app framework. It builds
iOS and Android apps that use JavaScript for describing layouts and events.
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
This demo uses NativeScript and SheetJS to process and generate spreadsheets.
We'll explore how to load SheetJS in a NativeScript app; parse and generate
spreadsheets stored on the device; and fetch and parse remote files.
The "Complete Example" creates an app that looks like the screenshots below:
<table><thead><tr>
<th><a href="#demo">iOS</a></th>
<th><a href="#demo">Android</a></th>
<th><a href="#complete-example">iOS</a></th>
<th><a href="#complete-example">Android</a></th>
</tr></thead><tbody><tr><td>
![iOS screenshot](pathname:///nativescript/ios.png)
@ -28,11 +40,39 @@ The "Complete Example" creates an app that looks like the screenshots below:
</td></tr></tbody></table>
## Integration Details
:::info pass
The discussion covers the NativeScript + Angular integration. Familiarity with
Angular and TypeScript is assumed.
:::
:::warning Telemetry
Before starting this demo, manually disable telemetry.
NativeScript 8.6.0 split the telemetry into two parts: "usage" and "error". Both
must be disabled separately:
```bash
npx -p nativescript ns usage-reporting disable
npx -p nativescript ns error-reporting disable
```
To verify telemetry was disabled:
```bash
npx -p nativescript ns usage-reporting status
npx -p nativescript ns error-reporting status
```
:::
## Integration Details
The [SheetJS NodeJS Module](/docs/getting-started/installation/nodejs) can be
imported from any component or script in the app.
The `@nativescript/core/file-system` package provides classes for file access.
The `File` class does not support binary data, but the file access singleton
from `@nativescript/core` does support reading and writing `ArrayBuffer`.
@ -51,7 +91,8 @@ function get_url_for_filename(filename: string): string {
### Reading Local Files
`getFileAccess().readBufferAsync` can read data:
`getFileAccess().readBufferAsync` can read data into an `ArrayBuffer` object.
The SheetJS `read` method[^1] can parse this data into a workbook object.[^2]
```ts
import { getFileAccess } from '@nativescript/core';
@ -67,10 +108,27 @@ const ab: ArrayBuffer = await getFileAccess().readBufferAsync(url);
const wb = read(ab);
```
After parsing into a workbook, the `sheet_to_json`[^3] method can generate row
data objects:
```ts
import { utils } from 'xlsx';
/* grab first sheet */
const wsname: string = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
/* generate array of row objects */
const data = utils.sheet_to_json(ws);
```
### Writing Local Files
`getFileAccess().writeBufferAsync` can write data. iOS supports `Uint8Array`
directly but Android requires a true array of numbers:
The SheetJS `write` method[^4] with the option `type: "binary"` will generate
`Uint8Array` objects. `getFileAccess().writeBufferAsync` can write data from a
`Uint8Array` object to the device.
iOS supports `Uint8Array` directly but Android requires a true array of numbers:
```ts
import { getFileAccess } from '@nativescript/core';
@ -86,10 +144,15 @@ const u8: Uint8Array = write(wb, { bookType: 'xls', type: 'binary' });
await getFileAccess().writeBufferAsync(url, global.isAndroid ? (Array.from(u8) as any) : u8);
```
A worksheet can be generated from an array of row objects with the SheetJS
`json_to_sheet` method[^5]. After generating an array, the `book_new` and
`book_append_sheet` methods[^6] can create the workbook.
### Fetching Remote Files
`getFile` from `@nativescript/core/http` can download files. After storing the
file in a temporary folder, `getFileAccess().readBufferAsync` can read the data:
file in a temporary folder, `getFileAccess().readBufferAsync` can read the data
and the SheetJS `read` method[^7] can parse the file:
```ts
import { knownFolders, path, getFileAccess } from '@nativescript/core'
@ -109,34 +172,120 @@ const ab: ArrayBuffer = await getFileAccess().readBufferAsync(file.path);
const wb = read(ab);
```
## Demo
## Complete Example
:::note
This demo was tested on an Intel Mac on 2023 May 21. NativeScript version
(as verified with `ns --version`) is `8.5.3`.
The project was last tested on 2023 October 12. NativeScript version
(as verified with `npx -p nativescript ns --version`) was `8.6.0`.
The iOS simulator runs iOS 16.2 on an iPhone 14 Pro Max.
The iOS demo was last tested on 2023-10-12 with `@nativescript/ios`
version `8.6.1` on an emulated iPhone 15 Pro Max + iOS 17.0
The Android simulator runs Android 12.0 (S) API 31 on a Pixel 3.
The Android demo was last tested on 2023-10-12 with `@nativescript/android`
version `8.6.2` on an emulated Pixel 3 + Android 13 ("Tiramisu") API 33.
:::
0) Follow the official Environment Setup instructions
### Platform Configuration
0) Disable telemetry:
```bash
npx -p nativescript ns usage-reporting disable
npx -p nativescript ns error-reporting disable
```
1) Follow the official Environment Setup instructions[^8].
:::caution pass
When the demo was last tested, the latest version of the Android API was 34.
NativeScript did not support that API level. The exact error message from
`npx -p nativescript ns doctor ios` clearly stated supported versions:
(x is red, body text is yellow)
```
✖ No compatible version of the Android SDK Build-tools are installed on your system. You can install any version in the following range: '>=23 <=33'.
```
The SDK Platform `Android 13.0 ("Tiramisu")` was compatible with NativeScript.
Until NativeScript properly supports API level 34, "Tiramisu" must be used.
This requires installing the following packages from Android Studio:
- `Android 13.0 ("Tiramisu")` API Level `33`
- `Android SDK Build-Tools` Version `33.0.2`
:::
2) Test the local system configuration for Android development:
```bash
npx -p nativescript ns doctor android
```
In the last macOS test, the following output was displayed:
<details open><summary><b>Expected output</b> (click to hide)</summary>
<pre>
<span {...g}></span> Getting environment information{'\n'}
{'\n'}
<b>No issues were detected.</b>{'\n'}
<span {...g}></span> Your ANDROID_HOME environment variable is set and points to correct directory.{'\n'}
<span {...g}></span> Your adb from the Android SDK is correctly installed.{'\n'}
<span {...g}></span> The Android SDK is installed.{'\n'}
<span {...g}></span> A compatible Android SDK for compilation is found.{'\n'}
<span {...g}></span> Javac is installed and is configured properly.{'\n'}
<span {...g}></span> The Java Development Kit (JDK) is installed and is configured properly.{'\n'}
<span {...g}></span> Getting NativeScript components versions information...{'\n'}
<span {...g}></span> Component nativescript has 8.6.0 version and is up to date.
</pre>
</details>
3) Test the local system configuration for iOS development (macOS only):
```bash
npx -p nativescript ns doctor ios
```
In the last macOS test, the following output was displayed:
<details open><summary><b>Expected output</b> (click to hide)</summary>
<pre>
<span {...g}></span> Getting environment information{'\n'}
{'\n'}
No issues were detected.{'\n'}
<span {...g}></span> Xcode is installed and is configured properly.{'\n'}
<span {...g}></span> xcodeproj is installed and is configured properly.{'\n'}
<span {...g}></span> CocoaPods are installed.{'\n'}
<span {...g}></span> CocoaPods update is not required.{'\n'}
<span {...g}></span> CocoaPods are configured properly.{'\n'}
<span {...g}></span> Your current CocoaPods version is newer than 1.0.0.{'\n'}
<span {...g}></span> Python installed and configured correctly.{'\n'}
<span {...g}></span> The Python 'six' package is found.{'\n'}
<span {...g}></span> Xcode version 15.0.0 satisfies minimum required version 10.{'\n'}
<span {...g}></span> Getting NativeScript components versions information...{'\n'}
<span {...g}></span> Component nativescript has 8.6.0 version and is up to date.
</pre>
</details>
### Base Project
1) Create a skeleton NativeScript + Angular app:
4) Create a skeleton NativeScript + Angular app:
```bash
ns create SheetJSNS --ng
npx -p nativescript ns create SheetJSNS --ng
```
2) Launch the app in the iOS simulator to verify that the demo built properly:
5) Launch the app in the android simulator to verify the app:
```bash
cd SheetJSNS
ns run ios
npx -p nativescript ns run android
```
(this may take a while)
@ -144,16 +293,22 @@ ns run ios
Once the simulator launches and the test app is displayed, end the script by
selecting the terminal and entering the key sequence `CTRL + C`
3) From the project folder, install the library:
6) From the project folder, install the library:
<CodeBlock language="bash">{`\
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz`}
</CodeBlock>
4) To confirm the library was loaded, change the title to show the version. The
differences are highlighted.
### Add SheetJS
`src/app/item/items.component.ts` should import the version string:
:::note pass
The goal of this section is to display the SheetJS library version number.
:::
7) Edit `src/app/item/items.component.ts` so that the component imports the
SheetJS version string and adds it to a `version` variable in the component:
```ts title="src/app/item/items.component.ts"
// highlight-next-line
@ -171,7 +326,8 @@ export class ItemsComponent implements OnInit {
// ...
```
`src/app/item/items.component.html` should use the version in the title:
8) Edit the template `src/app/item/items.component.html` to reference `version`
in the title of the action bar:
```xml title="src/app/item/items.component.html"
<!-- highlight-next-line -->
@ -181,13 +337,19 @@ export class ItemsComponent implements OnInit {
<!-- ... -->
```
Relaunch the app with `ns run ios` and the title bar should show the version.
9) Relaunch the app in the Android simulator:
![NativeScript Step 4](pathname:///mobile/nativescript4.png)
```bash
npx -p nativescript ns run android
```
The title bar should show the version.
![NativeScript Step 4](pathname:///nativescript/step4.png)
### Local Files
5) Add the Import and Export buttons to the template:
10) Add the Import and Export buttons to the template:
```xml title="src/app/item/items.component.html"
<ActionBar [title]="version"></ActionBar>
@ -206,6 +368,8 @@ Relaunch the app with `ns run ios` and the title bar should show the version.
</StackLayout>
```
11) Add the `import` and `export` methods in the component script:
```ts title="src/app/item/items.component.ts"
// highlight-start
import { version, utils, read, write } from 'xlsx';
@ -250,11 +414,11 @@ export class ItemsComponent implements OnInit {
}
```
Restart the app process and two buttons should show up at the top:
12) Restart the app process. Two buttons should show up at the top:
![NativeScript Step 5](pathname:///mobile/nativescript5.png)
![NativeScript Step 5](pathname:///nativescript/step5.png)
6) Implement import and export by adding the highlighted lines:
13) Implement import and export by adding the highlighted lines:
```ts title="src/app/item/items.component.ts"
/* Import button */
@ -306,51 +470,33 @@ Restart the app process and two buttons should show up at the top:
}
```
### iOS
Relaunch the app with `ns run ios`
The app can be tested with the following sequence in the simulator:
- Tap "Export File". A dialog will print where the file was written
- Open the file with a spreadsheet editor.
After the header row, insert a row with cell A2 = 0, B2 = SheetJS, C2 = Library:
```
id | name | role
0 | SheetJS | Library
1 | Ter Stegen | Goalkeeper
3 | Piqué | Defender
...
```
Restart the app after saving the file.
- Tap "Import File". A dialog will print the path of the file that was read.
The first item in the list will change:
![NativeScript Step 7](pathname:///mobile/nativescript7.png)
### Android
Launch the app with `ns run android`. If the app does not automatically launch,
manually open the `SheetJSNS` app.
14) Launch the app in the Android Simulator:
The app can be tested with the following sequence in the simulator:
```bash
npx -p nativescript ns run android
````
- Tap "Export File". A dialog will print where the file was written. Typically
If the app does not automatically launch, manually open the `SheetJSNS` app.
15) Tap "Export File". A dialog will print where the file was written. Typically
the URL is `/data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls`
- Pull the file from the simulator:
16) Pull the file from the simulator:
```bash
adb root
adb pull /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls SheetJSNS.xls
```
- Open `SheetJSNS.xls` with a spreadsheet editor.
If the emulator cannot be rooted:
```bash
adb shell "run-as org.nativescript.SheetJSNS cat /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls" > SheetJSNS.xls
```
17) Open `SheetJSNS.xls` with a spreadsheet editor.
After the header row, insert a row with cell A2 = 0, B2 = SheetJS, C2 = Library:
@ -362,18 +508,53 @@ id | name | role
...
```
- Push the file back to the simulator:
18) Push the file back to the simulator:
```bash
adb push SheetJSNS.xls /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls
```
- Tap "Import File". A dialog will print the path of the file that was read.
The first item in the list will change.
If the emulator cannot be rooted:
```bash
dd if=SheetJSNS.xls | adb shell "run-as org.nativescript.SheetJSNS dd of=/data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.xls"
```
19) Tap "Import File". A dialog will print the path of the file that was read.
The first item in the list will change.
### iOS
20) Launch the app in the iOS Simulator:
```bash
npx -p nativescript ns run ios
```
21) Tap "Export File". A dialog will print where the file was written.
22) Open the file with a spreadsheet editor.
After the header row, insert a row with cell A2 = 0, B2 = SheetJS, C2 = Library:
```
id | name | role
0 | SheetJS | Library
1 | Ter Stegen | Goalkeeper
3 | Piqué | Defender
...
```
23) Restart the app after saving the file.
24) Tap "Import File". A dialog will print the path of the file that was read.
The first item in the list will change:
![NativeScript Step 7](pathname:///nativescript/step7.png)
### Fetching Files
7) In `src/app/item/items.component.ts`, make `ngOnInit` asynchronous:
25) In `src/app/item/items.component.ts`, make `ngOnInit` asynchronous:
```ts title="src/app/item/items.component.ts"
async ngOnInit(): Promise<void> {
@ -381,7 +562,7 @@ adb push SheetJSNS.xls /data/user/0/org.nativescript.SheetJSNS/files/SheetJSNS.x
}
```
8) Replace `item.service.ts` with the following:
26) Replace `item.service.ts` with the following:
```ts title="src/app/item/item.service.ts"
import { Injectable } from '@angular/core'
@ -414,4 +595,19 @@ export class ItemService {
}
```
Relaunching the app in iOS or Android simulator should show Presidential data.
27) Relaunch the app in the Android simulator:
```bash
npx -p nativescript ns run android
````
The app should show Presidential data.
[^1]: See [`read` in "Reading Files"](/docs/api/parse-options)
[^2]: See ["Workbook Object"](/docs/csf/book)
[^3]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
[^4]: See [`write` in "Writing Files"](/docs/api/write-options)
[^5]: See [`json_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-objects-input)
[^6]: See ["Workbook Helpers" in "Utilities"](/docs/api/utilities/wb) for details on `book_new` and `book_append_sheet`.
[^7]: See [`read` in "Reading Files"](/docs/api/parse-options)
[^8]: See ["Local setup"](https://docs.nativescript.org/setup/#local-setup) in the NativeScript documentation. For Windows and Linux, follow the "Android" instructions. For macOS, follow both the iOS and Android instructions.

@ -50,7 +50,7 @@ This demo was tested in the following deployments:
| Architecture | Version | Node Target | Date |
|:-------------|:--------|:------------|:-----------|
| `darwin-x64` | `5.8.1` | `18.5.0` | 2023-05-08 |
| `darwin-x64` | `5.8.1` | `18.5.0` | 2023-10-11 |
| `darwin-arm` | `5.8.1` | `18.5.0` | 2023-09-25 |
| `win10-x64` | `5.8.1` | `18.5.0` | 2023-10-09 |
| `win11-arm` | `5.8.1` | `18.5.0` | 2023-09-25 |
@ -72,7 +72,7 @@ This demo was tested in the following deployments:
| Architecture | Version | Node Target | Date |
|:-------------|:--------|:------------|:-----------|
| `darwin-x64` | `2.0.1` | `20.1.0` | 2023-05-08 |
| `darwin-x64` | `2.1.2` | `20.8.0` | 2023-10-12 |
| `darwin-arm` | `2.1.1` | `20.7.0` | 2023-09-25 |
| `win10-x64` | `2.1.2` | `16.20.2` | 2023-10-09 |
| `linux-x64` | `2.1.2` | `20.8.0` | 2023-10-11 |
@ -239,7 +239,7 @@ This demo was last tested in the following deployments:
| Architecture | V8 Version | Crate | Date |
|:-------------|:--------------|:---------|:-----------|
| `darwin-x64` | `11.4.183.2` | `0.71.2` | 2023-05-22 |
| `darwin-x64` | `11.8.172.13` | `0.79.2` | 2023-10-12 |
| `darwin-arm` | `11.4.183.2` | `0.71.2` | 2023-05-22 |
| `win10-x64` | `11.8.172.13` | `0.79.2` | 2023-10-09 |
| `win11-x64` | `11.7.439.6` | `0.75.1` | 2023-08-31 |
@ -350,7 +350,7 @@ This demo was last tested in the following deployments:
| Architecture | Version | Date |
|:-------------|:---------|:-----------|
| `darwin-x64` | `1.33.2` | 2023-05-08 |
| `darwin-x64` | `1.37.1` | 2023-10-12 |
| `darwin-arm` | `1.34.1` | 2023-06-05 |
| `win10-x64` | `1.37.1` | 2023-10-09 |
| `win11-arm` | `1.37.0` | 2023-09-26 |

@ -9,31 +9,59 @@ sidebar_custom_props:
import current from '/version.js';
import CodeBlock from '@theme/CodeBlock';
MongoDB is a popular document-oriented database engine.
[MongoDB](https://mongodb.github.io/node-mongodb-native/) is a document-oriented
database engine.
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
data from spreadsheets.
This demo uses SheetJS to exchange data between spreadsheets and MongoDB. We'll
explore how to use save tables from a MongoDB collection to spreadsheets and how
to add data from spreadsheets into a collection.
:::note
This demo was last tested on 2023 October 12 with MongoDB CE 7.0.2, MongoDB
connector module 5.7.0 and NodeJS 20.8.0
:::
## Integration Details
The [SheetJS NodeJS module](/docs/getting-started/installation/nodejs) can be
loaded in NodeJS scripts that use the `mongodb` NodeJS connector library.
It is straightforward to treat collections as worksheets. Each object maps to
a row in the table.
## Integration Details
The official NodeJS connector is `mongodb`.
#### Importing Data
Data stored in an array of objects can be added to MongoDB Collections using
`Collection#insertMany`. `sheet_to_json` can generate data from worksheets:
`Collection#insertMany`[^1]. The SheetJS `sheet_to_json` method[^2] can generate
data from worksheets:
```js
/* import data from a worksheet to a collection */
const aoo = XLSX.utils.sheet_to_json(ws);
await collection.insertMany(aoo, {ordered: true});
```
Typically worksheet objects are extracted from workbook objects[^3] generated
from the SheetJS `read` or `readFile` methods[^4].
#### Exporting Data
`Collection#find` can pull an array of objects from a Mongo Collection.
`Collection#find`[^5] can pull an array of objects from a Mongo Collection.
The SheetJS `json_to_sheet` method[^6] can take the result and generate a
worksheet object.
:::info pass
Normally the method adds a `_id` field to each object. The recommended way to
remove the field is to use a `projection` to suppress the ID:
remove the field is to use a `projection` to suppress the ID.
:::
```js
/* generate an array of objects from a collection */
@ -43,16 +71,12 @@ const aoo = await collection.find({}, {projection:{_id:0}}).toArray();
const ws = utils.json_to_sheet(aoo);
```
Using `book_new` and `book_append_sheet`[^7], a workbook object can be created.
This workbook is typically exported to the filesystem with `writeFile`[^8].
## Complete Example
:::note
This demo was last tested on 2023 August 20 with MongoDB CE 7.0.0, MongoDB
connector module 5.7.0 and NodeJS 20.5.1.
:::
0) Install MongoDB 6.0 Community Edition. The macOS steps required `brew`:
0) Install MongoDB 7.0 Community Edition[^9]. The macOS steps required `brew`:
```bash
brew tap mongodb/brew
@ -61,12 +85,23 @@ 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:
```bash
/usr/local/opt/mongodb-community/bin/mongod --config /usr/local/etc/mongod.conf
```
If Homebrew is configured to use `/opt/homebrew`, the command is:
```bash
/opt/homebrew/opt/mongodb-community/bin/mongod --config /opt/homebrew/etc/mongod.conf
```
:::
2) Create base project and install the dependencies:
<CodeBlock language="bash">{`\
@ -122,4 +157,21 @@ This script:
- creates a SheetJS worksheet from the collection (highlighted in the snippet)
- creates a SheetJS workbook, adds the worksheet, and exports to XLSX
4) Run `node SheetJSMongoCRUD.mjs` and open `SheetJSMongoCRUD.xlsx`
4) Run the script:
```bash
node SheetJSMongoCRUD.mjs
```
There should be no errors in the terminal. The script will generate the file
`SheetJSMongoCRUD.xlsx`. That file can be opened in a spreadsheet editor.
[^1]: See [`insertMany`](https://mongodb.github.io/node-mongodb-native/5.7/classes/Collection.html#insertMany) in the MongoDB documentation.
[^2]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
[^3]: See ["Workbook Object"](/docs/csf/book)
[^4]: See [`read` and `readFile` in "Reading Files"](/docs/api/parse-options)
[^5]: See [`find`](https://mongodb.github.io/node-mongodb-native/5.7/classes/Collection.html#find) in the MongoDB documentation.
[^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.

@ -332,6 +332,49 @@ includes a live demo.
:::
#### Google Tag Manager
:::caution pass
Google Tag Manager is known to intercept and corrupt links. This issue will
manifest as UUID file names like `01234567-89ab-cdef-0123-456789abcdef` .
:::
For sites using GTM, it is recommended to patch `document.createElement` and
revert after performing the export.
<details><summary><b>GTM Workaround</b> (click to show)</summary>
The workaround is to ensure new `A` elements created by `document.createElement`
have the `target` attribute set to `_blank`.
After calling `writeFile`, the old version of the method should be restored.
```js title="GTM Workaround"
/* preparation */
document.createElement2 = document.createElement;
document.createElement = function(...args) {
if(args.length == 1 && args[0].toLowerCase() == "a") {
const a = document.createElement2("a");
a.target = "_blank";
return a;
}
return document.createElement2.call(this, ...args);
};
/* export (XLSX.writeFile) */
XLSX.writeFile(wb, "SheetJS.xlsx");
/* cleanup */
setTimeout(() => {
document.createElement = document.createElement2;
delete document.createElement2;
}, 1000);
```
</details>
### File API
_Reading Files_

@ -288,7 +288,13 @@ JS and the DOM API do not have a standard approach for creating files. There was
a `saveAs` proposal as part of "File API: Writer" but it was abandoned in 2014.
The library integrates a number of platform-specific techniques for different
environments. In modern web browsers, the library uses the `download` attribute.
environments. In modern web browsers, the library creates an `A` element with
the `download` attribute and clicks the link. A full analysis is included in the
["Local File Access" demo](/docs/demos/local/file#html5-download-attribute)
If the filename looks like a UUID (hexadecimal characters and hyphens), this is
a known issue with Google Tag Manager (GTM) rewriting links. There is a special
[workaround](/docs/demos/local/file#google-tag-manager) for sites that use GTM.
Third party libraries like `FileSaver.js` provide an implementation of `saveAs`
that include more browser-specific workarounds.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB