forked from sheetjs/docs.sheetjs.com
		
	visibility
This commit is contained in:
		
							parent
							
								
									f270ad6b3f
								
							
						
					
					
						commit
						481b147e97
					
				@ -336,7 +336,7 @@ case it is easier to post-process the raw data:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
let last_year = 0;
 | 
			
		||||
raw_data.forEach(r => (r[0] != null) ? (last_year = r[0]) : (r[0] = last_year));
 | 
			
		||||
raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::caution pass
 | 
			
		||||
@ -411,6 +411,32 @@ raw_data.forEach(r => {
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Observing that `r[0]` must equal `last_value`, the inner statement can be
 | 
			
		||||
rewritten to compute the final value and assign to both variables:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
let last_value = null;
 | 
			
		||||
raw_data.forEach(r => {
 | 
			
		||||
  last_value = r[0] = (r[0] != null ? r[0] : last_value);
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::caution pass
 | 
			
		||||
 | 
			
		||||
It is tempting to take advantage of implicit logical rules:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
let last_value = null;
 | 
			
		||||
raw_data.forEach(r => {
 | 
			
		||||
  last_value = r[0] = (r[0] || last_value);
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This is strongly discouraged since the value `0` is false. The explicit `null`
 | 
			
		||||
test distinguishes `null` and `undefined` from `0`
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
After post-processing, the rows now have proper year fields:
 | 
			
		||||
@ -443,7 +469,7 @@ function SheetJSAoAFilled() {
 | 
			
		||||
    const raw_data = XLSX.utils.sheet_to_json(worksheet, {header:1});
 | 
			
		||||
    /* fill years */
 | 
			
		||||
    var last_year = 0;
 | 
			
		||||
    raw_data.forEach(r => (r[0] != null) ? (last_year = r[0]) : (r[0] = last_year));
 | 
			
		||||
    raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
 | 
			
		||||
 | 
			
		||||
    /* pull Excel rows 13:16 (SheetJS 12:15) */
 | 
			
		||||
    const rows_13_16 = raw_data.slice(12,16);
 | 
			
		||||
@ -479,7 +505,7 @@ function SheetJSAoAFiltered() {
 | 
			
		||||
    const raw_data = XLSX.utils.sheet_to_json(worksheet, {header:1});
 | 
			
		||||
    /* fill years */
 | 
			
		||||
    var last_year = 0;
 | 
			
		||||
    raw_data.forEach(r => (r[0] != null) ? (last_year = r[0]) : (r[0] = last_year));
 | 
			
		||||
    raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
 | 
			
		||||
    /* select data rows */
 | 
			
		||||
    const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2023);
 | 
			
		||||
    /* display data */
 | 
			
		||||
@ -553,7 +579,7 @@ function SheetJSObjects() {
 | 
			
		||||
    const raw_data = XLSX.utils.sheet_to_json(worksheet, {header:1});
 | 
			
		||||
    /* fill years */
 | 
			
		||||
    var last_year = 0;
 | 
			
		||||
    raw_data.forEach(r => (r[0] != null) ? (last_year = r[0]) : (r[0] = last_year));
 | 
			
		||||
    raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
 | 
			
		||||
    /* select data rows */
 | 
			
		||||
    const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2023);
 | 
			
		||||
    /* generate row objects */
 | 
			
		||||
@ -660,7 +686,7 @@ function StudentAidTotal() {
 | 
			
		||||
 | 
			
		||||
    /* fill years */
 | 
			
		||||
    var last_year = 0;
 | 
			
		||||
    raw_data.forEach(r => (r[0] != null) ? (last_year = r[0]) : (r[0] = last_year));
 | 
			
		||||
    raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
 | 
			
		||||
 | 
			
		||||
    /* select data rows */
 | 
			
		||||
    const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2023);
 | 
			
		||||
@ -715,7 +741,7 @@ Save the following script to `SheetJSStandaloneDemo.html`:
 | 
			
		||||
\n\
 | 
			
		||||
  /* fill years */
 | 
			
		||||
  var last_year = 0;
 | 
			
		||||
  raw_data.forEach(r => (r[0] != null) ? (last_year = r[0]) : (r[0] = last_year));
 | 
			
		||||
  raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
 | 
			
		||||
\n\
 | 
			
		||||
  /* select data rows */
 | 
			
		||||
  const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2023);
 | 
			
		||||
@ -768,7 +794,7 @@ const XLSX = require("xlsx");
 | 
			
		||||
 | 
			
		||||
  /* fill years */
 | 
			
		||||
  var last_year = 0;
 | 
			
		||||
  raw_data.forEach(r => (r[0] != null) ? (last_year = r[0]) : (r[0] = last_year));
 | 
			
		||||
  raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
 | 
			
		||||
 | 
			
		||||
  /* select data rows */
 | 
			
		||||
  const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2023);
 | 
			
		||||
@ -783,7 +809,6 @@ const XLSX = require("xlsx");
 | 
			
		||||
    console.log(`${o.FY}\t${o.FQ||""}\t${o.total}`);
 | 
			
		||||
  });
 | 
			
		||||
})();
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
After saving the script, run the script:
 | 
			
		||||
@ -829,7 +854,7 @@ Save the following script to `SheetJSNW.html`:
 | 
			
		||||
\n\
 | 
			
		||||
  /* fill years */
 | 
			
		||||
  var last_year = 0;
 | 
			
		||||
  raw_data.forEach(r => (r[0] != null) ? (last_year = r[0]) : (r[0] = last_year));
 | 
			
		||||
  raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
 | 
			
		||||
\n\
 | 
			
		||||
  /* select data rows */
 | 
			
		||||
  const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2023);
 | 
			
		||||
@ -923,7 +948,7 @@ const App = () => {
 | 
			
		||||
 | 
			
		||||
    /* fill years */
 | 
			
		||||
    var last_year = 0;
 | 
			
		||||
    raw_data.forEach(r => (r[0] != null) ? (last_year = r[0]) : (r[0] = last_year));
 | 
			
		||||
    raw_data.forEach(r => last_year = r[0] = (r[0] != null ? r[0] : last_year));
 | 
			
		||||
 | 
			
		||||
    /* select data rows */
 | 
			
		||||
    const rows = raw_data.filter(r => r[0] >= 2007 && r[0] <= 2023);
 | 
			
		||||
 | 
			
		||||
@ -453,7 +453,6 @@ const columns = Array.from({ length: range.e.c + 1 }, (_, i) => ({
 | 
			
		||||
  /* column labels: encode_col translates 0 -> "A", 1 -> "B", 2 -> "C", ... */
 | 
			
		||||
  name: XLSX.utils.encode_col(i)
 | 
			
		||||
}));
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
@ -94,7 +94,7 @@ npx browserify xlsxworker.js > worker.js
 | 
			
		||||
 | 
			
		||||
4) Spin up a local web server:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
```bash
 | 
			
		||||
npx http-server
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -1191,7 +1191,7 @@ This demo was last tested on 2023 May 07 against ViteJS `4.3.5`
 | 
			
		||||
 | 
			
		||||
1) Create a new ViteJS project:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
```bash
 | 
			
		||||
npm create vite@latest sheetjs-vite -- --template vue-ts
 | 
			
		||||
cd sheetjs-vite
 | 
			
		||||
npm i
 | 
			
		||||
@ -1258,7 +1258,7 @@ writeFileXLSX(workbook, "Presidents.xlsx");
 | 
			
		||||
5) Run `npx vite build` and verify the generated pages work by running a local
 | 
			
		||||
web server in the `dist` folder:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
```bash
 | 
			
		||||
npx http-server dist/
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -265,7 +265,7 @@ Open that script.
 | 
			
		||||
 | 
			
		||||
Searching for `Bill Clinton` reveals the following:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
```js
 | 
			
		||||
{"Name":"Bill Clinton","Index":42}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -215,7 +215,7 @@ const wb = XLSX.read(ab);
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was tested on an Intel Mac on 2023 July 02 with RN `0.72.1`.
 | 
			
		||||
This demo was tested on an Intel Mac on 2023 August 20 with RN `0.72.4`.
 | 
			
		||||
 | 
			
		||||
The iOS simulator runs iOS 16.2 on an iPhone SE (3rd generation).
 | 
			
		||||
 | 
			
		||||
@ -226,7 +226,7 @@ The Android simulator runs Android 12.0 (S) API 31 on a Pixel 3.
 | 
			
		||||
1) Create project:
 | 
			
		||||
 | 
			
		||||
```bash
 | 
			
		||||
npx -y react-native@0.72.1 init SheetJSRNFetch --version="0.72.1"
 | 
			
		||||
npx -y react-native@0.72.4 init SheetJSRNFetch --version="0.72.4"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
2) Install shared dependencies:
 | 
			
		||||
@ -253,9 +253,9 @@ curl -LO https://docs.sheetjs.com/reactnative/App.tsx
 | 
			
		||||
When the demo was last tested on macOS, `java -version` displayed the following:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
openjdk version "11.0.19" 2023-04-18 LTS
 | 
			
		||||
OpenJDK Runtime Environment Zulu11.64+19-CA (build 11.0.19+7-LTS)
 | 
			
		||||
OpenJDK 64-Bit Server VM Zulu11.64+19-CA (build 11.0.19+7-LTS, mixed mode)
 | 
			
		||||
openjdk version "11.0.20" 2023-07-18 LTS
 | 
			
		||||
OpenJDK Runtime Environment Zulu11.66+15-CA (build 11.0.20+8-LTS)
 | 
			
		||||
OpenJDK 64-Bit Server VM Zulu11.66+15-CA (build 11.0.20+8-LTS, mixed mode)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
@ -296,7 +296,7 @@ tapping "Import data from a spreadsheet", verify that the app shows new data:
 | 
			
		||||
 | 
			
		||||
:::warning pass
 | 
			
		||||
 | 
			
		||||
iOS testing requires macOS. It does not work on Windows.
 | 
			
		||||
iOS testing requires macOS. It does not work on Windows or Linux.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -253,7 +253,6 @@ This uses two functions that should be added to the component script:
 | 
			
		||||
// highlight-end
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
The app should now show two buttons at the bottom:
 | 
			
		||||
 | 
			
		||||
@ -13,8 +13,11 @@ sidebar_custom_props:
 | 
			
		||||
import current from '/version.js';
 | 
			
		||||
import CodeBlock from '@theme/CodeBlock';
 | 
			
		||||
 | 
			
		||||
AlaSQL is a pure JavaScript in-memory SQL database.  It has built-in support for
 | 
			
		||||
SheetJS through the `XLSX` target operator.
 | 
			
		||||
[AlaSQL](https://alasql.org/) is a pure JavaScript in-memory SQL database. It
 | 
			
		||||
has built-in support for SheetJS through the `XLSX` target operator.
 | 
			
		||||
 | 
			
		||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
 | 
			
		||||
data from spreadsheets.
 | 
			
		||||
 | 
			
		||||
This demo covers basic concepts pertaining to data import and export.  The
 | 
			
		||||
official documentation includes advanced examples and deployment tips as well as
 | 
			
		||||
@ -27,7 +30,7 @@ This demo was tested in the following environments:
 | 
			
		||||
| Environment         | AlaSQL |    Date    |
 | 
			
		||||
|:--------------------|:-------|:----------:|
 | 
			
		||||
| NodeJS              | 3.1.0  | 2023-07-24 |
 | 
			
		||||
| Standalone (Chrome) | 3.0.0  | 2023-04-09 |
 | 
			
		||||
| Standalone (Chrome) | 3.0.0  | 2023-08-20 |
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -47,8 +47,8 @@ const ws = utils.json_to_sheet(aoo);
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
This demo was last tested on 2023 February 23 with MongoDB CE 6.0.4, MongoDB
 | 
			
		||||
connector module 5.1.0 and NodeJS 18.14.2.
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
@ -57,11 +57,11 @@ connector module 5.1.0 and NodeJS 18.14.2.
 | 
			
		||||
```bash
 | 
			
		||||
brew tap mongodb/brew
 | 
			
		||||
brew update
 | 
			
		||||
brew install mongodb-community@6.0
 | 
			
		||||
brew install mongodb-community
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
1) Start a MongoDB server on `localhost` (follow official instructions). To run
 | 
			
		||||
in the foreground on Intel MacOS:
 | 
			
		||||
1) Start a MongoDB server on `localhost` (follow official instructions).
 | 
			
		||||
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
 | 
			
		||||
@ -73,7 +73,7 @@ in the foreground on Intel MacOS:
 | 
			
		||||
mkdir sheetjs-mongo
 | 
			
		||||
cd sheetjs-mongo
 | 
			
		||||
npm init -y
 | 
			
		||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz mongodb@5.1.0`}
 | 
			
		||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz mongodb@5.7.0`}
 | 
			
		||||
</CodeBlock>
 | 
			
		||||
 | 
			
		||||
3) Save the following to `SheetJSMongoCRUD.mjs` (the key step is highlighted):
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,7 @@ This demo was verified by NetSuite consultants in the following deployments:
 | 
			
		||||
 | 
			
		||||
| `@NScriptType`  | `@NApiVersion` | Date       |
 | 
			
		||||
|:----------------|:---------------|:-----------|
 | 
			
		||||
| ScheduledScript | 2.1            | 2023-03-09 |
 | 
			
		||||
| ScheduledScript | 2.1            | 2023-08-18 |
 | 
			
		||||
| Restlet         | 2.1            | 2023-04-20 |
 | 
			
		||||
| Suitelet        | 2.1            | 2023-07-21 |
 | 
			
		||||
| MapReduceScript | 2.1            | 2023-07-31 |
 | 
			
		||||
 | 
			
		||||
@ -350,7 +350,6 @@ fn eval_code_ab(scope: &mut v8::HandleScope, code: &str) -> Vec<u8> {
 | 
			
		||||
    result.byte_length()
 | 
			
		||||
  ).to_vec(); }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
@ -299,7 +299,7 @@ curl -LO https://sheetjs.com/pres.numbers`}
 | 
			
		||||
 | 
			
		||||
6) Run the test program:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
```bash
 | 
			
		||||
./sheetjs.ch pres.numbers
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -361,6 +361,6 @@ ready, it will read the bundled test data and print the contents as CSV.
 | 
			
		||||
 | 
			
		||||
5) Run the script using the ChakraCore standalone binary:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
```bash
 | 
			
		||||
./ch xlsx.chakra.js
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
@ -4,11 +4,18 @@ pagination_next: solutions/input
 | 
			
		||||
hide_table_of_contents: true
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# Demo Projects
 | 
			
		||||
# Demos
 | 
			
		||||
 | 
			
		||||
Demos include complete examples and short discussions.  For features that can
 | 
			
		||||
run in the web browser, demos will include interactive examples.
 | 
			
		||||
 | 
			
		||||
:::tip pass
 | 
			
		||||
 | 
			
		||||
If a demo for a library or framework is not included here, please leave a note
 | 
			
		||||
in the [issue tracker](https://git.sheetjs.com/sheetjs/docs.sheetjs.com/issues)
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
### JavaScript APIs
 | 
			
		||||
 | 
			
		||||
- [`XMLHttpRequest and fetch`](/docs/demos/net/network)
 | 
			
		||||
@ -66,6 +73,7 @@ run in the web browser, demos will include interactive examples.
 | 
			
		||||
- [`NextJS`](/docs/demos/static/nextjs)
 | 
			
		||||
- [`NuxtJS`](/docs/demos/static/nuxtjs)
 | 
			
		||||
- [`SvelteKit`](/docs/demos/static/svelte)
 | 
			
		||||
- [`Webpack`](/docs/demos/static/webpack)
 | 
			
		||||
 | 
			
		||||
### App Extensions
 | 
			
		||||
 | 
			
		||||
@ -129,10 +137,3 @@ run in the web browser, demos will include interactive examples.
 | 
			
		||||
- [`QuickJS (C)`](/docs/demos/engines/quickjs)
 | 
			
		||||
- [`ExecJS (Ruby)`](/docs/demos/engines/rb)
 | 
			
		||||
- [`JavaScript::Engine (Perl)`](/docs/demos/engines/perl)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
:::note
 | 
			
		||||
 | 
			
		||||
If a demo for a library or framework is not included here, please leave a note.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
@ -522,7 +522,7 @@ const workbook = XLSX.read(data);`}</CodeBlock>
 | 
			
		||||
 | 
			
		||||
Deno must be run with the `--allow-net` flag to enable network requests:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
```bash
 | 
			
		||||
deno run --allow-net test-fetch.ts
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -88,3 +88,12 @@ discussed in more detail in ["Defined Names"](/docs/csf/features/names)
 | 
			
		||||
| `CodeName`      | [VBA Workbook Name](/docs/csf/features/vba)                |
 | 
			
		||||
| `date1904`      | epoch: 0/false for 1900 system, 1/true for 1904            |
 | 
			
		||||
| `filterPrivacy` | Warn or strip personally identifying info on save          |
 | 
			
		||||
 | 
			
		||||
### Sheet Metadata
 | 
			
		||||
 | 
			
		||||
`wb.Workbook.Sheets` is an array of sheet metadata objects which have the keys:
 | 
			
		||||
 | 
			
		||||
| Key             | Description                                         |
 | 
			
		||||
|:----------------|:----------------------------------------------------|
 | 
			
		||||
| `Hidden`        | [Sheet Visibility](/docs/csf/features/visibility)   |
 | 
			
		||||
| `CodeName`      | [VBA Sheet Code Name](/docs/csf/features/vba)       |
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
---
 | 
			
		||||
sidebar_position: 3
 | 
			
		||||
sidebar_position: 1
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# Dates and Times
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
---
 | 
			
		||||
sidebar_position: 1
 | 
			
		||||
sidebar_position: 2
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# Formulae
 | 
			
		||||
@ -16,17 +16,17 @@ while the writer will translate from A1-Style strings to the file format.
 | 
			
		||||
|:------------------|:-----:|:-----:|:-----:|:-------:|:-----------------------|
 | 
			
		||||
| XLSX / XLSM       |   ✔   |   ✔   |   ✔   |    ✔    | A1-Style strings       |
 | 
			
		||||
| XLSB              |   ✔   |       |   ✔   |    ✔    | BIFF parsed tokens     |
 | 
			
		||||
| XLS               |   ✔   |       |   ✔   |    *    | BIFF parsed tokens     |
 | 
			
		||||
| XLML              |   ✔   |   ✔   |   ✔   |    *    | RC-style strings       |
 | 
			
		||||
| SYLK              |   ✔   |   ✔   |       |    *    | A1/RC-style strings    |
 | 
			
		||||
| CSV / TXT         |   ✔   |   ✔   |   *   |    *    | A1-Style strings       |
 | 
			
		||||
| ODS / FODS / UOS  |   ✔   |   ✔   |       |    *    | OpenFormula strings    |
 | 
			
		||||
| WK\*              |   ✔   |       |       |    *    | Lotus parsed tokens    |
 | 
			
		||||
| WQ\* / WB\* / QPW |       |       |       |    *    | Quattro Pro tokens     |
 | 
			
		||||
| NUMBERS           |       |       |       |    *    | Numbers parsed tokens  |
 | 
			
		||||
| XLS               |   ✔   |       |   ✔   |    ✕    | BIFF parsed tokens     |
 | 
			
		||||
| XLML              |   ✔   |   ✔   |   ✔   |    ✕    | RC-style strings       |
 | 
			
		||||
| SYLK              |   ✔   |   ✔   |       |    ✕    | A1/RC-style strings    |
 | 
			
		||||
| CSV / TXT         |   ✔   |   ✔   |   ✕   |    ✕    | A1-Style strings       |
 | 
			
		||||
| ODS / FODS / UOS  |   ✔   |   ✔   |       |    ✕    | OpenFormula strings    |
 | 
			
		||||
| WK\*              |   ✔   |       |       |    ✕    | Lotus parsed tokens    |
 | 
			
		||||
| WQ\* / WB\* / QPW |       |       |       |    ✕    | Quattro Pro tokens     |
 | 
			
		||||
| NUMBERS           |       |       |       |    ✕    | Numbers parsed tokens  |
 | 
			
		||||
 | 
			
		||||
Asterisks (*) mark features that are not supported by the file formats. There is
 | 
			
		||||
no way to mark a dynamic array formula in the XLS file format.
 | 
			
		||||
X (✕) marks features that are not supported by the file formats. There is no way
 | 
			
		||||
to mark a dynamic array formula in the XLS file format.
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
@ -163,7 +163,7 @@ function ConcatFormula(props) {
 | 
			
		||||
  };
 | 
			
		||||
  return ( <>
 | 
			
		||||
    <input type="file" onChange={process_file}/><br/>
 | 
			
		||||
    <b>addr: </b><input type="text" value={addr} onChange={setaddr} size="6"/>
 | 
			
		||||
    <b>Cell: </b><input type="text" value={addr} onChange={setaddr} size="6"/>
 | 
			
		||||
    {!ws[addr] ? ( <b>Cell {addr} not found</b> ) : ( <table>
 | 
			
		||||
      <tr><td>Formula</td><td><code>{ws[addr].f}</code></td></tr>
 | 
			
		||||
      <tr><td>Value</td><td><code>{ws[addr].v}</code></td></tr>
 | 
			
		||||
@ -201,6 +201,8 @@ var worksheet = XLSX.utils.aoa_to_sheet([
 | 
			
		||||
 | 
			
		||||
<details open><summary><b>Live Example</b> (click to hide)</summary>
 | 
			
		||||
 | 
			
		||||
This demo creates a worksheet where `A1=1`, `A2=2`, and `A3=A1+A2`.
 | 
			
		||||
 | 
			
		||||
```jsx live
 | 
			
		||||
/* The live editor requires this function wrapper */
 | 
			
		||||
function ExportSimpleFormula(props) {
 | 
			
		||||
@ -238,10 +240,13 @@ var worksheet = XLSX.utils.aoa_to_sheet([
 | 
			
		||||
])
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::note pass
 | 
			
		||||
 | 
			
		||||
If the actual results are needed in JS, [SheetJS Pro](https://sheetjs.com/pro)
 | 
			
		||||
offers a formula calculator component for evaluating expressions, updating
 | 
			
		||||
values and dependent cells, and refreshing entire workbooks.
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
## Array Formulae
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
---
 | 
			
		||||
sidebar_position: 2
 | 
			
		||||
sidebar_position: 3
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
# Hyperlinks
 | 
			
		||||
@ -124,7 +124,7 @@ function SheetJSParseLinks(props) {
 | 
			
		||||
 | 
			
		||||
## Remote Links
 | 
			
		||||
 | 
			
		||||
HTTP / HTTPS links can be used directly:
 | 
			
		||||
HTTP and HTTPS links can be used directly:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
ws["A2"].l = { Target: "https://docs.sheetjs.com/docs/csf/features/hyperlinks" };
 | 
			
		||||
@ -208,6 +208,14 @@ ws["C3"].l = { Target: "#SheetJSDName" }; /* Link to Defined Name */
 | 
			
		||||
 | 
			
		||||
<details><summary><b>Live Example</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
This demo creates a workbook with two worksheets. In the first worksheet:
 | 
			
		||||
 | 
			
		||||
- Cell `A1` ("Same") will link to the range `B2:D4` in the first sheet
 | 
			
		||||
- Cell `B1` ("Cross") will link to the range `B2:D4` in the second sheet
 | 
			
		||||
- Cell `C1` ("Name") will link to the range in the defined name `SheetJSDN`
 | 
			
		||||
 | 
			
		||||
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={() => {
 | 
			
		||||
@ -248,10 +256,13 @@ XLSX documents.  A workaround was added in library version 0.18.12.
 | 
			
		||||
 | 
			
		||||
## HTML
 | 
			
		||||
 | 
			
		||||
The HTML DOM parser will process `<a>` links in the table:
 | 
			
		||||
The HTML DOM parser[^1] will process `<a>` links in the table.
 | 
			
		||||
 | 
			
		||||
<details open><summary><b>Live Example</b> (click to hide)</summary>
 | 
			
		||||
 | 
			
		||||
This example uses `table_to_book` to generate a SheetJS workbook object from a
 | 
			
		||||
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) {
 | 
			
		||||
@ -278,3 +289,37 @@ function ExportHyperlink(props) {
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
The HTML writer[^2] will generate `<a>` links.
 | 
			
		||||
 | 
			
		||||
<details open><summary><b>Live Example</b> (click to hide)</summary>
 | 
			
		||||
 | 
			
		||||
This example creates a worksheet where `A1` has a link and `B1` does not. The
 | 
			
		||||
`sheet_to_html` function generates an HTML table where the topleft table cell
 | 
			
		||||
has a standard HTML link.
 | 
			
		||||
 | 
			
		||||
```jsx live
 | 
			
		||||
/* The live editor requires this function wrapper */
 | 
			
		||||
function ExportALinks(props) {
 | 
			
		||||
  const [ __html, setHTML ] = React.useState("");
 | 
			
		||||
  React.useEffect(() => {
 | 
			
		||||
    /* Create worksheet */
 | 
			
		||||
    var ws = XLSX.utils.aoa_to_sheet([ [ "Link", "No Link" ] ]);
 | 
			
		||||
    /* Add link */
 | 
			
		||||
    ws["A1"].l = {
 | 
			
		||||
      Target: "https://sheetjs.com",
 | 
			
		||||
      Tooltip: "Find us @ SheetJS.com!"
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /* Generate HTML */
 | 
			
		||||
    setHTML(XLSX.utils.sheet_to_html(ws));
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return ( <div dangerouslySetInnerHTML={{__html}}/> );
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</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)
 | 
			
		||||
@ -167,7 +167,6 @@ function SheetJSComments2() {
 | 
			
		||||
    XLSX.writeFile(wb, "SheetJSComments2.xlsx");
 | 
			
		||||
  }}>Click me to generate a sample file</button>);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										150
									
								
								docz/docs/07-csf/07-features/08-visibility.md
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										150
									
								
								docz/docs/07-csf/07-features/08-visibility.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,150 @@
 | 
			
		||||
---
 | 
			
		||||
title: Sheet Visibility
 | 
			
		||||
sidebar_position: 7
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
<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"
 | 
			
		||||
state is controlled through the "Visibility" property in the VBA editor.
 | 
			
		||||
 | 
			
		||||
| Formats   | Hidden | Very Hidden |
 | 
			
		||||
|:----------|:------:|:-----------:|
 | 
			
		||||
| XLSX/XLSM |   ✔    |      ✔      |
 | 
			
		||||
| XLSB      |   ✔    |      ✔      |
 | 
			
		||||
| XLML      |   ✔    |      ✔      |
 | 
			
		||||
| BIFF8 XLS |   ✔    |      ✔      |
 | 
			
		||||
| BIFF5 XLS |   ✔    |      ✔      |
 | 
			
		||||
 | 
			
		||||
</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.
 | 
			
		||||
 | 
			
		||||
Standard "hidden" sheets are revealed 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!
 | 
			
		||||
 | 
			
		||||
## Storage
 | 
			
		||||
 | 
			
		||||
The visibility setting is stored in the `Hidden` property of the corresponding
 | 
			
		||||
[metadata in the `wb.Workbook.Sheets` array](/docs/csf/book#sheet-metadata)
 | 
			
		||||
 | 
			
		||||
The recognized values are listed below:
 | 
			
		||||
 | 
			
		||||
| Value | Definition  | VB Editor "Visible" Property |
 | 
			
		||||
|:-----:|:------------|:-----------------------------|
 | 
			
		||||
|   0   | Visible     | `-1 - xlSheetVisible`        |
 | 
			
		||||
|   1   | Hidden      | ` 0 - xlSheetHidden`         |
 | 
			
		||||
|   2   | Very Hidden | ` 2 - xlSheetVeryHidden`     |
 | 
			
		||||
 | 
			
		||||
If the respective Sheet entry does not exist or if the `Hidden` property is not
 | 
			
		||||
set, the worksheet is visible.
 | 
			
		||||
 | 
			
		||||
### Parsing
 | 
			
		||||
 | 
			
		||||
Since worksheet visibility is stored in the workbook, both the workbook object
 | 
			
		||||
and the sheet name must be known to determine visibility setting.
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
function get_sheet_visibility(workbook, sheet_name) {
 | 
			
		||||
  // if the metadata does not exist for the sheet, the sheet is visible
 | 
			
		||||
  if(!workbook.Workbook) return 0;
 | 
			
		||||
  if(!workbook.Workbook.Sheets) return 0;
 | 
			
		||||
 | 
			
		||||
  var idx = workbook.SheetNames.indexOf(sheet_name);
 | 
			
		||||
  if(idx == -1) throw new Error(`Sheet ${sheet_name} missing from workbook`);
 | 
			
		||||
 | 
			
		||||
  var meta = workbook.Workbook.Sheets[idx];
 | 
			
		||||
  return meta && meta.Hidden || 0;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Typically the distinction between "hidden" and "very hidden" is not relevant for
 | 
			
		||||
applications. The values were chosen to make logical negation work as expected:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
function is_sheet_visible(workbook, sheet_name) {
 | 
			
		||||
  return !get_sheet_visibility(workbook, sheet_name); // true if visible
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Writing
 | 
			
		||||
 | 
			
		||||
When assigning, the entire workbook metadata structure should be tested and
 | 
			
		||||
constructed if necessary:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
function set_sheet_visibility(workbook, sheet_name, Hidden) {
 | 
			
		||||
  var idx = workbook.SheetNames.indexOf(sheet_name);
 | 
			
		||||
  if(idx == -1) throw new Error(`Sheet ${sheet_name} missing from workbook`);
 | 
			
		||||
 | 
			
		||||
  // if the metadata does not exist for the sheet, create it
 | 
			
		||||
  if(!workbook.Workbook) workbook.Workbook = {};
 | 
			
		||||
  if(!workbook.Workbook.Sheets) workbook.Workbook.Sheets = [];
 | 
			
		||||
  if(!workbook.Workbook.Sheets[idx]) workbook.Workbook.Sheets[idx] = {};
 | 
			
		||||
 | 
			
		||||
  // set visibility
 | 
			
		||||
  workbook.Workbook.Sheets[idx].Hidden = Hidden;
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Demo
 | 
			
		||||
 | 
			
		||||
[This test file](pathname:///files/sheet_visibility.xlsx) has three sheets:
 | 
			
		||||
 | 
			
		||||
- "Visible" is visible
 | 
			
		||||
- "Hidden" is hidden
 | 
			
		||||
- "VeryHidden" is very hidden
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
The live demo fetches the test file and displays visibility information.
 | 
			
		||||
 | 
			
		||||
```jsx live
 | 
			
		||||
function Visibility(props) {
 | 
			
		||||
  const [wb, setWB] = React.useState({SheetNames:[]});
 | 
			
		||||
  const [sheets, setSheets] = React.useState([]);
 | 
			
		||||
  const vis = [ "Visible", "Hidden", "Very Hidden" ];
 | 
			
		||||
 | 
			
		||||
  React.useEffect(async() => {
 | 
			
		||||
    const f = await fetch("/files/sheet_visibility.xlsx");
 | 
			
		||||
    const ab = await f.arrayBuffer();
 | 
			
		||||
    const wb = XLSX.read(ab);
 | 
			
		||||
    setWB(wb);
 | 
			
		||||
    /* State will be set to the `Sheets` property array */
 | 
			
		||||
    setSheets(wb.Workbook.Sheets);
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return (<table>
 | 
			
		||||
    <thead><tr><th>Name</th><th>Value</th><th>Hidden</th></tr></thead>
 | 
			
		||||
    <tbody>{wb.SheetNames.map((n,i) => {
 | 
			
		||||
      const h = ((((wb||{}).Workbook||{}).Sheets||[])[i]||{}).Hidden||0;
 | 
			
		||||
      return ( <tr key={i}>
 | 
			
		||||
        <td>{n}</td>
 | 
			
		||||
        <td>{h} - {vis[h]}</td>
 | 
			
		||||
        <td>{!h ? "No" : "Yes"}</td>
 | 
			
		||||
      </tr> );
 | 
			
		||||
    })}</tbody></table>);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::info pass
 | 
			
		||||
 | 
			
		||||
The live codeblock tests for visibility with:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const h = ((((wb||{}).Workbook||{}).Sheets||[])[i]||{}).Hidden||0;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
With modern JS, this can be written as
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
const h = wb?.Workbook?.Sheets?.[i]?.Hidden||0;
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
:::
 | 
			
		||||
 | 
			
		||||
@ -138,91 +138,3 @@ follow the priority order:
 | 
			
		||||
3) use `wch` character count if available
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
## Sheet Visibility
 | 
			
		||||
 | 
			
		||||
<details>
 | 
			
		||||
  <summary><b>Format Support</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
**Hidden Sheets**: XLSX/M, XLSB, BIFF8/BIFF5 XLS, XLML
 | 
			
		||||
 | 
			
		||||
**Very Hidden Sheets**: XLSX/M, XLSB, BIFF8/BIFF5 XLS, XLML
 | 
			
		||||
 | 
			
		||||
</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.  Standard hidden sheets
 | 
			
		||||
are revealed in the "Unhide" menu.  Excel also has "very hidden" sheets which
 | 
			
		||||
cannot be revealed in the menu.  It is only accessible in the VB Editor!
 | 
			
		||||
 | 
			
		||||
The visibility setting is stored in the `Hidden` property of sheet props array.
 | 
			
		||||
 | 
			
		||||
| Value | Definition  | VB Editor "Visible" Property |
 | 
			
		||||
|:-----:|:------------|:-----------------------------|
 | 
			
		||||
|   0   | Visible     | `-1 - xlSheetVisible`        |
 | 
			
		||||
|   1   | Hidden      | ` 0 - xlSheetHidden`         |
 | 
			
		||||
|   2   | Very Hidden | ` 2 - xlSheetVeryHidden`     |
 | 
			
		||||
 | 
			
		||||
If the respective Sheet entry does not exist or if the `Hidden` property is not
 | 
			
		||||
set, the worksheet is visible.
 | 
			
		||||
 | 
			
		||||
**List all worksheets and their visibility settings**
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
wb.Workbook.Sheets.map(function(x) { return [x.name, x.Hidden] })
 | 
			
		||||
// [ [ 'Visible', 0 ], [ 'Hidden', 1 ], [ 'VeryHidden', 2 ] ]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
**Check if worksheet is visible**
 | 
			
		||||
 | 
			
		||||
Non-Excel formats do not support the Very Hidden state.  The best way to test
 | 
			
		||||
if a sheet is visible is to check if the `Hidden` property is logical truth:
 | 
			
		||||
 | 
			
		||||
```js
 | 
			
		||||
wb.Workbook.Sheets.map(function(x) { return [x.name, !x.Hidden] })
 | 
			
		||||
// [ [ 'Visible', true ], [ 'Hidden', false ], [ 'VeryHidden', false ] ]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
<details>
 | 
			
		||||
  <summary><b>Live Example</b> (click to show)</summary>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
[This test file](pathname:///files/sheet_visibility.xlsx) has three sheets:
 | 
			
		||||
 | 
			
		||||
- "Visible" is visible
 | 
			
		||||
- "Hidden" is hidden
 | 
			
		||||
- "VeryHidden" is very hidden
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
**Live demo**
 | 
			
		||||
 | 
			
		||||
```jsx live
 | 
			
		||||
function Visibility(props) {
 | 
			
		||||
  const [sheets, setSheets] = React.useState([]);
 | 
			
		||||
  const names = [ "Visible", "Hidden", "Very Hidden" ];
 | 
			
		||||
 | 
			
		||||
  React.useEffect(async() => {
 | 
			
		||||
    const f = await fetch("/files/sheet_visibility.xlsx");
 | 
			
		||||
    const ab = await f.arrayBuffer();
 | 
			
		||||
    const wb = XLSX.read(ab);
 | 
			
		||||
 | 
			
		||||
    /* State will be set to the `Sheets` property array */
 | 
			
		||||
    setSheets(wb.Workbook.Sheets);
 | 
			
		||||
  }, []);
 | 
			
		||||
 | 
			
		||||
  return (<table>
 | 
			
		||||
    <thead><tr><th>Name</th><th>Value</th><th>Hidden</th></tr></thead>
 | 
			
		||||
    <tbody>{sheets.map((x,i) => (<tr key={i}>
 | 
			
		||||
 | 
			
		||||
      <td>{x.name}</td>
 | 
			
		||||
 | 
			
		||||
      <td>{x.Hidden} - {names[x.Hidden]}</td>
 | 
			
		||||
 | 
			
		||||
      <td>{!x.Hidden ? "No" : "Yes"}</td>
 | 
			
		||||
 | 
			
		||||
    </tr>))}</tbody></table>);
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
</details>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										31
									
								
								docz/static/mongodb/SheetJSMongoCRUD.mjs
									
									
									
									
									
										Normal file
									
								
							
							
								
								
								
								
								
									
									
								
							
						
						
									
										31
									
								
								docz/static/mongodb/SheetJSMongoCRUD.mjs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
import { writeFile, set_fs, utils } from 'xlsx';
 | 
			
		||||
import * as fs from 'fs'; set_fs(fs);
 | 
			
		||||
import { MongoClient } from 'mongodb';
 | 
			
		||||
 | 
			
		||||
const url = 'mongodb://localhost:27017/sheetjs';
 | 
			
		||||
const db_name = 'sheetjs';
 | 
			
		||||
 | 
			
		||||
/* Connect to mongodb server */
 | 
			
		||||
const client = await MongoClient.connect(url, { useUnifiedTopology: true });
 | 
			
		||||
 | 
			
		||||
/* Sample data table */
 | 
			
		||||
const db = client.db(db_name);
 | 
			
		||||
try { await db.collection('pres').drop(); } catch(e) {}
 | 
			
		||||
const pres = db.collection('pres');
 | 
			
		||||
await pres.insertMany([
 | 
			
		||||
  { name: "Barack Obama", idx: 44 },
 | 
			
		||||
  { name: "Donald Trump", idx: 45 },
 | 
			
		||||
  { name: "Joseph Biden", idx: 46 }
 | 
			
		||||
], {ordered: true});
 | 
			
		||||
 | 
			
		||||
/* Create worksheet from collection */
 | 
			
		||||
const aoo = await pres.find({}, {projection:{_id:0}}).toArray();
 | 
			
		||||
const ws = utils.json_to_sheet(aoo);
 | 
			
		||||
 | 
			
		||||
/* Export to XLSX */
 | 
			
		||||
const wb = utils.book_new();
 | 
			
		||||
utils.book_append_sheet(wb, ws, "Presidents");
 | 
			
		||||
writeFile(wb, "SheetJSMongoCRUD.xlsx");
 | 
			
		||||
 | 
			
		||||
/* Close connection */
 | 
			
		||||
client.close();
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user