2022-05-20 08:48:21 +00:00
|
|
|
---
|
2022-08-26 05:39:17 +00:00
|
|
|
title: Google Sheets
|
2023-02-28 11:40:44 +00:00
|
|
|
pagination_prev: demos/local/index
|
|
|
|
pagination_next: demos/extensions/index
|
2022-05-20 08:48:21 +00:00
|
|
|
---
|
|
|
|
|
2023-04-27 09:12:19 +00:00
|
|
|
import current from '/version.js';
|
2022-05-20 08:48:21 +00:00
|
|
|
import Tabs from '@theme/Tabs';
|
|
|
|
import TabItem from '@theme/TabItem';
|
2023-04-27 09:12:19 +00:00
|
|
|
import CodeBlock from '@theme/CodeBlock';
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-11-13 20:45:13 +00:00
|
|
|
This demo uses `node-google-spreadsheet` to interact with Google Sheets v4 API.
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
:::caution
|
|
|
|
|
|
|
|
Google Sheets deprecates APIs quickly and there is no guarantee that the
|
|
|
|
referenced API version will be available in the future.
|
|
|
|
|
|
|
|
:::
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2023-04-18 04:46:43 +00:00
|
|
|
:::note
|
|
|
|
|
|
|
|
This demo focuses on external data processing. For Google Apps Script custom
|
|
|
|
functions, [the "Google Sheets" extension demo](/docs/demos/extensions/gsheet)
|
|
|
|
covers Apps Script integration.
|
|
|
|
|
|
|
|
:::
|
|
|
|
|
2022-05-20 08:48:21 +00:00
|
|
|
## Initial Configuration
|
|
|
|
|
|
|
|
Install the dependencies:
|
|
|
|
|
2023-04-27 09:12:19 +00:00
|
|
|
<CodeBlock language="bash">{`\
|
|
|
|
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz google-spreadsheet@3.3.0`}
|
|
|
|
</CodeBlock>
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
The library README has a [guide](https://theoephraim.github.io/node-google-spreadsheet/#/getting-started/authentication)
|
|
|
|
for configuring a service worker with write access to the document. Following
|
|
|
|
the service worker guide, the JSON key should be saved to `key.json`.
|
|
|
|
|
|
|
|
The following helper function attempts to authenticate and access the specified
|
|
|
|
sheet by ID. The code should be copied and saved to `common.js`:
|
|
|
|
|
|
|
|
<details><summary><b>Code</b> (click to show)</summary>
|
|
|
|
|
|
|
|
```js title=common.js
|
|
|
|
const fs = require("fs");
|
|
|
|
const { GoogleSpreadsheet } = require('google-spreadsheet');
|
|
|
|
|
|
|
|
module.exports = async(ID) => {
|
|
|
|
/* get credentials */
|
|
|
|
const creds = JSON.parse(fs.readFileSync('key.json'));
|
|
|
|
|
|
|
|
/* initialize sheet and authenticate */
|
|
|
|
const doc = new GoogleSpreadsheet(ID);
|
|
|
|
await doc.useServiceAccountAuth(creds);
|
|
|
|
await doc.loadInfo();
|
|
|
|
return doc;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
## Export Document Data
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
The goal is to create an XLSB export from a Google Sheet. Google Sheets does
|
2022-10-10 01:42:23 +00:00
|
|
|
not natively support the XLSB format. SheetJS fills the gap.
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
<details><summary><b>How to run locally</b> (click to show)</summary>
|
|
|
|
|
2022-11-13 20:45:13 +00:00
|
|
|
0) Follow the [Initial Configuration](#initial-configuration).
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
1) Create a new Google Sheet and share with the generated service account. It
|
|
|
|
should be granted the "Editor" role
|
|
|
|
|
|
|
|
2) Install the dependencies:
|
|
|
|
|
2023-04-27 09:12:19 +00:00
|
|
|
<CodeBlock language="bash">{`\
|
|
|
|
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz google-spreadsheet@3.3.0`}
|
|
|
|
</CodeBlock>
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
2) Save the following snippet to `common.js`:
|
|
|
|
|
|
|
|
```js title=common.js
|
|
|
|
const fs = require("fs");
|
|
|
|
const { GoogleSpreadsheet } = require('google-spreadsheet');
|
|
|
|
|
|
|
|
module.exports = async(ID) => {
|
|
|
|
/* get credentials */
|
|
|
|
const creds = JSON.parse(fs.readFileSync('key.json'));
|
|
|
|
|
|
|
|
/* initialize sheet and authenticate */
|
|
|
|
const doc = new GoogleSpreadsheet(ID);
|
|
|
|
await doc.useServiceAccountAuth(creds);
|
|
|
|
await doc.loadInfo();
|
|
|
|
return doc;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
3) Save the following snippet to `pull.js`:
|
|
|
|
|
|
|
|
```js title=pull.js
|
|
|
|
const XLSX = require("xlsx");
|
|
|
|
|
|
|
|
/* create a blank workbook */
|
|
|
|
const wb = XLSX.utils.book_new();
|
|
|
|
|
|
|
|
const init = require("./common");
|
|
|
|
const ID = "<google sheet ID>";
|
|
|
|
|
|
|
|
(async() => {
|
|
|
|
|
|
|
|
const doc = await init(ID);
|
|
|
|
|
|
|
|
for(let i = 0; i < doc.sheetsByIndex.length; ++i) {
|
|
|
|
const sheet = doc.sheetsByIndex[i];
|
|
|
|
const name = sheet.title;
|
|
|
|
|
|
|
|
/* get the header and data rows */
|
|
|
|
await sheet.loadHeaderRow();
|
|
|
|
const header = sheet.headerValues;
|
|
|
|
const rows = await sheet.getRows();
|
|
|
|
const aoa = [header].concat(rows.map(r => r._rawData));
|
|
|
|
|
|
|
|
/* generate a SheetJS Worksheet */
|
|
|
|
const ws = XLSX.utils.aoa_to_sheet(aoa);
|
|
|
|
|
|
|
|
/* add to workbook */
|
|
|
|
XLSX.utils.book_append_sheet(wb, ws, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* write to SheetJS.xlsb */
|
|
|
|
XLSX.writeFile(wb, "SheetJS.xlsb");
|
|
|
|
|
|
|
|
})();
|
|
|
|
```
|
|
|
|
|
|
|
|
4) Replace `<google sheet ID>` with the ID of the actual document.
|
|
|
|
|
|
|
|
5) Run `node pull.js` once. It will create `SheetJS.xlsb`.
|
|
|
|
|
|
|
|
6) Open `SheetJS.xlsb` and confirm the contents are the same as Google Sheets.
|
|
|
|
|
|
|
|
7) Change some cells in the Google Sheets Document.
|
|
|
|
|
|
|
|
8) Run `node pull.js` again and reopen `SheetJS.xlsb` to confirm value changes.
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
### Convert a Single Sheet
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
The idea is to extract the raw data from the Google Sheet headers and combine
|
|
|
|
with the raw data rows to produce a large array of arrays.
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
```js
|
2022-10-10 01:42:23 +00:00
|
|
|
async function wb_append_sheet(sheet, name, wb) {
|
|
|
|
/* get the header and data rows */
|
|
|
|
await sheet.loadHeaderRow();
|
|
|
|
const header = sheet.headerValues;
|
|
|
|
const rows = await sheet.getRows();
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* construct the array of arrays */
|
|
|
|
const aoa = [header].concat(rows.map(r => r._rawData));
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* generate a SheetJS Worksheet */
|
|
|
|
const ws = XLSX.utils.aoa_to_sheet(aoa);
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* add to workbook */
|
|
|
|
XLSX.utils.book_append_sheet(wb, ws, name);
|
2022-05-20 08:48:21 +00:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
### Convert a Workbook
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
`doc.sheetsByIndex` is an array of worksheets in the Google Sheet Document. By
|
|
|
|
looping across the sheets, the entire workbook can be written:
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
```js
|
2022-10-10 01:42:23 +00:00
|
|
|
async function doc_to_wb(doc) {
|
|
|
|
/* Create a new workbook object */
|
|
|
|
const wb = XLSX.utils.book_new();
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Loop across the Document sheets */
|
|
|
|
for(let i = 0; i < doc.sheetsByIndex.length; ++i) {
|
|
|
|
const sheet = doc.sheetsByIndex[i];
|
|
|
|
/* Get the worksheet name */
|
|
|
|
const name = sheet.title;
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Add sheet to workbook */
|
|
|
|
await add_sheet_to_wb(sheet, name, wb);
|
|
|
|
}
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
return wb;
|
2022-05-20 08:48:21 +00:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
## Update Document Data
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
The goal is to refresh a Google Sheet based on a local file.
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
<details><summary><b>How to run locally</b> (click to show)</summary>
|
|
|
|
|
2022-11-13 20:45:13 +00:00
|
|
|
0) Follow the [Initial Configuration](#initial-configuration).
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
1) Create a new Google Sheet and share with the generated service account. It
|
|
|
|
should be granted the "Editor" role
|
|
|
|
|
|
|
|
2) Install the dependencies:
|
|
|
|
|
2023-04-27 09:12:19 +00:00
|
|
|
<CodeBlock language="bash">{`\
|
|
|
|
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz google-spreadsheet@3.3.0`}
|
|
|
|
</CodeBlock>
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
2) Save the following snippet to `common.js`:
|
|
|
|
|
|
|
|
```js title=common.js
|
|
|
|
const fs = require("fs");
|
|
|
|
const { GoogleSpreadsheet } = require('google-spreadsheet');
|
|
|
|
|
|
|
|
module.exports = async(ID) => {
|
|
|
|
/* get credentials */
|
|
|
|
const creds = JSON.parse(fs.readFileSync('key.json'));
|
|
|
|
|
|
|
|
/* initialize sheet and authenticate */
|
|
|
|
const doc = new GoogleSpreadsheet(ID);
|
|
|
|
await doc.useServiceAccountAuth(creds);
|
|
|
|
await doc.loadInfo();
|
|
|
|
return doc;
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
3) Save the following snippet to `push.js`:
|
|
|
|
|
|
|
|
```js title=push.js
|
|
|
|
const XLSX = require("xlsx");
|
|
|
|
const fs = require("fs");
|
|
|
|
/* create dummy worksheet if `sheetjs.xlsx` does not exist */
|
|
|
|
if(!fs.existsSync("sheetjs.xlsx")) {
|
|
|
|
const wb = XLSX.utils.book_new();
|
|
|
|
const ws1 = XLSX.utils.aoa_to_sheet([["a","b","c"],[1,2,3]]); XLSX.utils.book_append_sheet(wb, ws1, "Sheet1");
|
|
|
|
const ws2 = XLSX.utils.aoa_to_sheet([["a","b","c"],[4,5,6]]); XLSX.utils.book_append_sheet(wb, ws2, "Sheet2");
|
|
|
|
XLSX.writeFile(wb, "sheetjs.xlsx");
|
|
|
|
}
|
|
|
|
/* read and parse sheetjs.xlsx */
|
|
|
|
const wb = XLSX.readFile("sheetjs.xlsx");
|
|
|
|
|
|
|
|
const init = require("./common");
|
|
|
|
const ID = "<google sheet ID>";
|
|
|
|
|
|
|
|
(async() => {
|
|
|
|
|
|
|
|
const doc = await init(ID);
|
|
|
|
|
|
|
|
/* clear workbook */
|
|
|
|
{
|
|
|
|
/* delete all sheets after the first sheet */
|
|
|
|
const old_sheets = doc.sheetsByIndex;
|
|
|
|
for(let i = 1; i < old_sheets.length; ++i) {
|
|
|
|
await old_sheets[i].delete();
|
|
|
|
}
|
|
|
|
/* clear first worksheet */
|
|
|
|
old_sheets[0].clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* write worksheets */
|
|
|
|
{
|
|
|
|
const name = wb.SheetNames[0];
|
|
|
|
const ws = wb.Sheets[name];
|
|
|
|
/* first worksheet already exists */
|
|
|
|
const sheet = doc.sheetsByIndex[0];
|
|
|
|
|
|
|
|
/* update worksheet name */
|
|
|
|
await sheet.updateProperties({title: name});
|
|
|
|
|
|
|
|
/* generate array of arrays from the first worksheet */
|
|
|
|
const aoa = XLSX.utils.sheet_to_json(ws, {header: 1});
|
|
|
|
|
|
|
|
/* set document header row to first row of the AOA */
|
|
|
|
await sheet.setHeaderRow(aoa[0])
|
|
|
|
|
|
|
|
/* add the remaining rows */
|
|
|
|
await sheet.addRows(aoa.slice(1));
|
|
|
|
|
|
|
|
/* the other worksheets must be created manually */
|
|
|
|
for(let i = 1; i < wb.SheetNames.length; ++i) {
|
|
|
|
const name = wb.SheetNames[i];
|
|
|
|
const ws = wb.Sheets[name];
|
|
|
|
|
|
|
|
const sheet = await doc.addSheet({title: name});
|
|
|
|
const aoa = XLSX.utils.sheet_to_json(ws, {header: 1});
|
|
|
|
await sheet.setHeaderRow(aoa[0])
|
|
|
|
await sheet.addRows(aoa.slice(1));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
})();
|
|
|
|
```
|
|
|
|
|
|
|
|
4) Replace `<google sheet ID>` with the ID of the actual document.
|
|
|
|
|
|
|
|
5) Run `node push.js` once. It will create `sheetjs.xlsx` and update the sheet.
|
|
|
|
|
|
|
|
6) Edit `sheetjs.xlsx` with some new data
|
|
|
|
|
|
|
|
7) Run `node push.js` again and watch the Google Sheet update!
|
|
|
|
|
|
|
|
</details>
|
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
### Clear the Document
|
|
|
|
|
|
|
|
Google Sheets does not allow users to delete every worksheet. This function
|
|
|
|
deletes every worksheet after the first, then clears the first worksheet:
|
|
|
|
|
|
|
|
```js
|
|
|
|
/* clear google sheets doc */
|
|
|
|
async function doc_clear(doc) {
|
|
|
|
/* delete all sheets after the first sheet */
|
|
|
|
const old_sheets = doc.sheetsByIndex;
|
|
|
|
for(let i = 1; i < old_sheets.length; ++i) await old_sheets[i].delete();
|
|
|
|
|
|
|
|
/* clear first worksheet */
|
|
|
|
old_sheets[0].clear();
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Update First Sheet
|
|
|
|
|
|
|
|
There are two steps: "update worksheet name" and "update worksheet data":
|
|
|
|
|
|
|
|
#### Update Sheet Name
|
|
|
|
|
|
|
|
The worksheet name is assigned by using the `updateProperties` method. The
|
|
|
|
desired sheet name is the name of the first worksheet from the file.
|
|
|
|
|
|
|
|
```js
|
|
|
|
async function doc_update_first_sheet_name(doc, wb) {
|
|
|
|
/* get first worksheet name */
|
|
|
|
const wsname = wb.SheetNames[0];
|
|
|
|
|
|
|
|
/* get first gsheet */
|
|
|
|
const sheet = doc.sheetsByIndex[0];
|
|
|
|
|
|
|
|
/* update worksheet name */
|
|
|
|
await sheet.updateProperties({title: wsname});
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Update Sheet Data
|
|
|
|
|
|
|
|
`sheet.addRows` reads an Array of Arrays of values. `XLSX.utils.sheet_to_json`
|
|
|
|
can generate this exact shape with the option `header: 1`. Unfortunately
|
|
|
|
Google Sheets requires at least one "Header Row". This can be implemented by
|
|
|
|
converting the entire worksheet to an Array of Arrays and setting the header
|
|
|
|
row to the first row of the result:
|
|
|
|
|
|
|
|
```js
|
|
|
|
async function doc_update_first_sheet_data(doc, wb) {
|
|
|
|
/* get first worksheet */
|
|
|
|
const ws = wb.Sheets[wb.SheetNames[0]];
|
|
|
|
/* generate array of arrays from the first worksheet */
|
|
|
|
const aoa = XLSX.utils.sheet_to_json(ws, {header: 1});
|
|
|
|
|
|
|
|
/* get first gsheet */
|
|
|
|
const sheet = doc.sheetsByIndex[0];
|
|
|
|
/* set document header row to first row of the AOA */
|
|
|
|
await sheet.setHeaderRow(aoa[0]);
|
|
|
|
|
|
|
|
/* add the remaining rows */
|
|
|
|
await sheet.addRows(aoa.slice(1));
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
### Append Remaining Worksheets
|
|
|
|
|
|
|
|
Each name in the SheetJS Workbook `SheetNames` array maps to a worksheet. The
|
|
|
|
list of names not including the first sheet is `wb.SheetNames.slice(1)`.
|
|
|
|
|
|
|
|
There are two steps for each sheet: "create new sheet" and "load data".
|
|
|
|
|
|
|
|
Due to JavaScript `async` idiosyncrasies, a plain `for` loop must be used:
|
|
|
|
|
|
|
|
```js
|
|
|
|
async function doc_append_remaining_sheets(doc, wb) {
|
|
|
|
const names = wb.SheetNames.slice(1);
|
|
|
|
|
|
|
|
/* loop across names */
|
|
|
|
for(let i = 0; i < names.length; ++i) {
|
|
|
|
/* wb.SheetNames[i] is the sheet name */
|
|
|
|
const name = wb.SheetNames[i];
|
|
|
|
/* wb.Sheets[name] is the worksheet object */
|
|
|
|
const ws = wb.Sheets[name];
|
|
|
|
|
|
|
|
/* create new google sheet */
|
|
|
|
const sheet = await doc_add_new_sheet(doc, name);
|
|
|
|
/* load sheet with data */
|
|
|
|
await sheet_load_from_ws(sheet, ws);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
#### Add a New Worksheet
|
|
|
|
|
|
|
|
`doc.addSheet` accepts a properties object that includes the worksheet name:
|
|
|
|
|
|
|
|
```js
|
|
|
|
async function doc_add_new_sheet(doc, name) {
|
|
|
|
return await doc.addSheet({title: name});
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
This creates a new worksheet, sets the tab name, and returns a reference to the
|
|
|
|
created worksheet.
|
|
|
|
|
|
|
|
#### Update Worksheet Data
|
|
|
|
|
|
|
|
```js
|
|
|
|
async function sheet_load_from_ws(sheet, ws) {
|
|
|
|
/* generate array of arrays from the first worksheet */
|
|
|
|
const aoa = XLSX.utils.sheet_to_json(ws, {header: 1});
|
|
|
|
|
|
|
|
/* set document header row to first row of the AOA */
|
|
|
|
await sheet.setHeaderRow(aoa[0]);
|
|
|
|
|
|
|
|
/* add the remaining rows */
|
|
|
|
await sheet.addRows(aoa.slice(1));
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Raw File Exports
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
`node-google-spreadsheet` can download the XLSX or ODS export of the document.
|
|
|
|
The functions return NodeJS `Buffer` data that can be parsed using SheetJS.
|
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
This example prints the worksheet names and CSV exports of each sheet.
|
2022-05-20 08:48:21 +00:00
|
|
|
|
|
|
|
<Tabs>
|
|
|
|
<TabItem value="xlsx" label="XLSX">
|
|
|
|
|
|
|
|
```js
|
|
|
|
const XLSX = require("xlsx");
|
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
(async() => {
|
|
|
|
/* Connect to Google Sheet */
|
|
|
|
const ID = "<google sheet id>";
|
|
|
|
const doc = await require("./common")(ID);
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Get file export */
|
|
|
|
// highlight-next-line
|
|
|
|
const buf = await doc.downloadAsXLSX();
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Parse with SheetJS */
|
|
|
|
const wb = XLSX.read(buf);
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Loop over the worksheet names */
|
|
|
|
wb.SheetNames.forEach(name => {
|
|
|
|
/* Print the name to the console */
|
|
|
|
console.log(name);
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Get the corresponding worksheet object */
|
|
|
|
const sheet = wb.Sheets[name];
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Print a CSV export of the worksheet */
|
|
|
|
console.log(XLSX.utils.sheet_to_csv(sheet));
|
|
|
|
});
|
|
|
|
})();
|
2022-05-20 08:48:21 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
</TabItem>
|
|
|
|
|
|
|
|
<TabItem value="ods" label="ODS">
|
|
|
|
|
|
|
|
```js
|
|
|
|
const XLSX = require("xlsx");
|
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
(async() => {
|
|
|
|
/* Connect to Google Sheet */
|
|
|
|
const ID = "<google sheet id>";
|
|
|
|
const doc = await require("./common")(ID);
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Get file export */
|
|
|
|
// highlight-next-line
|
|
|
|
const buf = await doc.downloadAsODS();
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Parse with SheetJS */
|
|
|
|
const wb = XLSX.read(buf);
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Loop over the worksheet names */
|
|
|
|
wb.SheetNames.forEach(name => {
|
|
|
|
/* Print the name to the console */
|
|
|
|
console.log(name);
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Get the corresponding worksheet object */
|
|
|
|
const sheet = wb.Sheets[name];
|
2022-05-20 08:48:21 +00:00
|
|
|
|
2022-10-10 01:42:23 +00:00
|
|
|
/* Print a CSV export of the worksheet */
|
|
|
|
console.log(XLSX.utils.sheet_to_csv(sheet));
|
|
|
|
});
|
|
|
|
})();
|
2022-05-20 08:48:21 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
</TabItem>
|
2022-10-10 01:42:23 +00:00
|
|
|
</Tabs>
|