forked from sheetjs/docs.sheetjs.com
gsheet-api
This commit is contained in:
parent
4438bd86cd
commit
8914e8f714
@ -9,12 +9,11 @@ import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last tested on 2023 April 18 with `react-data-grid 7.0.0-beta.28`,
|
||||
`create-react-app` 5.0.1 and React 18.2.0.
|
||||
This demo was last tested on 2023 September 17 with `react-data-grid` version
|
||||
`7.0.0-beta.39` and React 18.2.0.
|
||||
|
||||
:::
|
||||
|
||||
|
||||
The demo creates a site that looks like the screenshot below:
|
||||
|
||||
![react-data-grid screenshot](pathname:///rdg/rdg1.png)
|
||||
@ -117,7 +116,7 @@ cd sheetjs-rdg
|
||||
2) Install dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz react-data-grid`}
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz react-data-grid@7.0.0-beta.39`}
|
||||
</CodeBlock>
|
||||
|
||||
3) Download [`App.tsx`](pathname:///rdg/App.tsx) and replace `src/App.tsx`.
|
||||
@ -126,5 +125,15 @@ npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz react-data-
|
||||
curl -L -o src/App.tsx https://docs.sheetjs.com/rdg/App.tsx
|
||||
```
|
||||
|
||||
4) run `npm start`. When you load the page in the browser, it will attempt to
|
||||
fetch <https://sheetjs.com/pres.numbers> and load the data.
|
||||
4) Start the development server:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
#### Testing
|
||||
|
||||
5) When the page loads, it will fetch <https://sheetjs.com/pres.numbers>, parse
|
||||
with SheetJS, and load the data in the data grid.
|
||||
|
||||
6) Click one of the "export" buttons to export the grid data to file.
|
||||
|
@ -1,5 +1,7 @@
|
||||
---
|
||||
title: Quasar
|
||||
title: Data in Quasar Apps
|
||||
sidebar_label: Quasar
|
||||
description: Build data-intensive mobile apps with Quasar and Cordova. Seamlessly integrate spreadsheets into your app using SheetJS. Let data in your Excel spreadsheets shine.
|
||||
pagination_prev: demos/static/index
|
||||
pagination_next: demos/desktop/index
|
||||
sidebar_position: 3
|
||||
@ -10,10 +12,17 @@ sidebar_custom_props:
|
||||
import current from '/version.js';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
|
||||
from the main entrypoint or any script in the project.
|
||||
[Quasar](https://quasar.dev/) is a VueJS framework for building iOS and Android
|
||||
apps with the Cordova platform.
|
||||
|
||||
The "Complete Example" creates an app that looks like the screenshots below:
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
data from spreadsheets.
|
||||
|
||||
This demo uses Quasar and SheetJS to process data and generate spreadsheets.
|
||||
We'll explore how to load SheetJS in an Quasar app and use Quasar and Cordova
|
||||
features to extract data from, and write data to, spreadsheets on the device.
|
||||
|
||||
The ["Demo"](#demo) creates an app that looks like the screenshots below:
|
||||
|
||||
<table><thead><tr>
|
||||
<th><a href="#demo">iOS</a></th>
|
||||
@ -30,10 +39,14 @@ The "Complete Example" creates an app that looks like the screenshots below:
|
||||
|
||||
### Integration Details
|
||||
|
||||
The [NodeJS Module](/docs/getting-started/installation/nodejs) can be imported
|
||||
from the main entrypoint or any script in the project.
|
||||
|
||||
This demo will use the Quasar ViteJS starter project with VueJS and Cordova.
|
||||
The starter places the backing Cordova project in the `src-cordova` folder.
|
||||
|
||||
The complete solution uses `cordova-plugin-file` for file operations. It can
|
||||
be installed like any other Cordova plugin:
|
||||
be installed from the Cordova folder:
|
||||
|
||||
```bash
|
||||
cd src-cordova
|
||||
@ -41,15 +54,21 @@ cordova plugin add cordova-plugin-file
|
||||
cd ..
|
||||
```
|
||||
|
||||
#### Reading data
|
||||
### Reading data
|
||||
|
||||
The `q-file` component presents an API reminiscent of File Input elements:
|
||||
The QFile[^1] component presents an API reminiscent of File Input elements:
|
||||
|
||||
```html
|
||||
<q-file label="Load File" filled label-color="orange" @input="updateFile"/>
|
||||
```
|
||||
|
||||
When binding to the `input` element, the callback receives an `Event` object:
|
||||
When binding to the `input` element, the callback receives an `Event` object.
|
||||
Using standard DOM operations, the file data can be pulled into an `ArrayBuffer`
|
||||
and parsed using the SheetJS `read` method[^2]. `read` returns a workbook[^3]
|
||||
object that holds data and metadata for each worksheet.
|
||||
|
||||
This snippet reads a workbook, pulls the first worksheet, generates an array of
|
||||
objects using the SheetJS `sheet_to_json`[^4] method, and updates state:
|
||||
|
||||
```ts
|
||||
import { read } from 'xlsx';
|
||||
@ -74,14 +93,33 @@ async function updateFile(v) { try {
|
||||
|
||||
#### Writing data
|
||||
|
||||
The API is shaped like the File and Directory Entries API. For clarity, since
|
||||
the code is a "pyramid of doom", the error handlers are omitted:
|
||||
Starting from an array of objects, the SheetJS `json_to_sheet` method[^5]
|
||||
generates a SheetJS worksheet object. The `book_append_sheet` and `book_new`
|
||||
helper functions[^6] create a SheetJS workbook object that can be exported:
|
||||
|
||||
```ts
|
||||
```js
|
||||
import { utils } from 'xlsx';
|
||||
|
||||
// assuming `todos` is a VueJS ref whose value is an array of objects
|
||||
const ws = utils.json_to_sheet(todos.value);
|
||||
const wb = utils.book_new();
|
||||
utils.book_append_sheet(wb, ws, "SheetJSQuasar");
|
||||
```
|
||||
|
||||
The SheetJS `write` function[^7] with the option `type: "buffer"` will generate
|
||||
`Uint8Array` objects that can be converted to blobs and exported:
|
||||
|
||||
```js
|
||||
import { write } from 'xlsx';
|
||||
|
||||
// on iOS and android, `XLSX.write` with type "buffer" returns a `Uint8Array`
|
||||
const u8: Uint8Array = write(wb, {bookType: "xlsx", type: "buffer"});
|
||||
```
|
||||
|
||||
The `cordova-plugin-file` API writes the data to the filesystem. The code uses
|
||||
the File and Directory Entries API[^8]:
|
||||
|
||||
```ts
|
||||
// Request filesystem access for persistent storage
|
||||
window.requestFileSystem(window.PERSISTENT, 0, function(fs) {
|
||||
// Request a handle to "SheetJSQuasar.xlsx", making a new file if necessary
|
||||
@ -107,12 +145,11 @@ window.requestFileSystem(window.PERSISTENT, 0, function(fs) {
|
||||
|
||||
:::note
|
||||
|
||||
This demo was tested on an Intel Mac on 2023 April 08. `create-quasar@1.1.2`
|
||||
was installed during app creation. The app used Quasar version `2.11.10`.
|
||||
The Android demo was last tested on 2023 September 18 with Quasar `2.12.7` on an
|
||||
emulated Pixel 3 + Android 13 ("Tiramisu") API 33.
|
||||
|
||||
The iOS simulator runs iOS 16.2 on an iPhone 14 Pro Max.
|
||||
|
||||
The Android simulator runs Android 12.0 (S) API 31 on a Pixel 3.
|
||||
The iOS demo was last tested on 2023 September 18 with Quasar `2.12.7` on an
|
||||
emulated iPhone SE (3rd generation) + iOS 16.4.
|
||||
|
||||
:::
|
||||
|
||||
@ -196,20 +233,38 @@ Return to the project directory:
|
||||
cd ..
|
||||
```
|
||||
|
||||
4) Start the development server:
|
||||
11) Enable file sharing and make the documents folder visible in the iOS app.
|
||||
The following lines must be added to `src-cordova/platforms/ios/SheetJSQuasar/SheetJSQuasar-Info.plist`:
|
||||
|
||||
```xml title="src-cordova/platforms/ios/SheetJSQuasar/SheetJSQuasar-Info.plist (add to file)"
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- highlight-start -->
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<true/>
|
||||
<!-- highlight-end -->
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
```
|
||||
|
||||
(The root element of the document is `plist` and it contains one `dict` child)
|
||||
|
||||
|
||||
5) Start the development server:
|
||||
|
||||
```bash
|
||||
quasar dev -m ios
|
||||
```
|
||||
|
||||
:::caution
|
||||
:::caution pass
|
||||
|
||||
If the app is blank or not refreshing, delete the app and close the simulator,
|
||||
then restart the development process.
|
||||
|
||||
:::
|
||||
|
||||
5) Add the Dialog plugin to `quasar.config.js`:
|
||||
6) Add the Dialog plugin to `quasar.config.js`:
|
||||
|
||||
```js title="quasar.config.js"
|
||||
framework: {
|
||||
@ -221,7 +276,7 @@ then restart the development process.
|
||||
},
|
||||
```
|
||||
|
||||
6) In the template section of `src/pages/IndexPage.vue`, replace the example
|
||||
7) In the template section of `src/pages/IndexPage.vue`, replace the example
|
||||
with a Table, Save button and Load file picker component:
|
||||
|
||||
```html title="src/pages/IndexPage.vue"
|
||||
@ -266,7 +321,7 @@ then restart the development process.
|
||||
|
||||
:::
|
||||
|
||||
7) Wire up the `updateFile` function:
|
||||
8) Wire up the `updateFile` function:
|
||||
|
||||
```ts title="src/pages/IndexPage.vue"
|
||||
import { defineComponent, ref } from 'vue';
|
||||
@ -315,7 +370,7 @@ To test that reading works:
|
||||
|
||||
Once selected, the screen should refresh with new contents.
|
||||
|
||||
8) Wire up the `saveFile` function:
|
||||
9) Wire up the `saveFile` function:
|
||||
|
||||
```ts title="src/pages/IndexPage.vue"
|
||||
function saveFile() {
|
||||
@ -401,7 +456,7 @@ id,content
|
||||
|
||||
**Android**
|
||||
|
||||
9) Create the Android project:
|
||||
10) Create the Android project:
|
||||
|
||||
```bash
|
||||
cd src-cordova
|
||||
@ -409,24 +464,12 @@ cordova platform add android
|
||||
cd ..
|
||||
```
|
||||
|
||||
10) Start the simulator:
|
||||
11) Start the simulator:
|
||||
|
||||
```bash
|
||||
quasar dev -m android
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
In local testing, the Quasar build process threw an error:
|
||||
|
||||
```
|
||||
java.lang.IllegalArgumentException: Unsupported class file major version 63
|
||||
```
|
||||
|
||||
This was resolved by rolling back to Java 1.8
|
||||
|
||||
:::
|
||||
|
||||
To test that reading works:
|
||||
|
||||
- Click and drag `pres.numbers` from a Finder window into the simulator.
|
||||
@ -442,3 +485,12 @@ To test that writing works:
|
||||
adb exec-out run-as org.sheetjs.quasar cat files/files/SheetJSQuasar.xlsx > /tmp/SheetJSQuasar.xlsx
|
||||
npx xlsx-cli /tmp/SheetJSQuasar.xlsx
|
||||
```
|
||||
|
||||
[^1]: See ["File Picker"](https://quasar.dev/vue-components/file-picker) in the Quasar documentation.
|
||||
[^2]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^3]: See ["SheetJS Data Model"](/docs/csf/) for more details on workbooks, worksheets, and other concepts.
|
||||
[^4]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^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 [`write` in "Writing Files"](/docs/api/write-options)
|
||||
[^8]: See [`requestFileSystem`](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestFileSystem) in the MDN Web Docs for more details.
|
@ -183,7 +183,9 @@ The following Web APIs are featured in separate demos:
|
||||
<a href={item.href}>{item.label}</a>{item.customProps?.summary && (" - " + item.customProps.summary)}
|
||||
</li>);
|
||||
})}
|
||||
<li><a href="/docs/demos/local/indexeddb">IndexedDB API</a></li></ul>
|
||||
<li><a href="/docs/demos/local/storageapi">Local Storage API</a></li>
|
||||
<li><a href="/docs/demos/local/indexeddb">IndexedDB API</a></li>
|
||||
</ul>
|
||||
|
||||
### SQL Databases
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
---
|
||||
title: Local Storage API
|
||||
pagination_prev: demos/desktop/index
|
||||
pagination_next: demos/local/index
|
||||
pagination_prev: demos/data/index
|
||||
pagination_next: demos/cloud/index
|
||||
sidebar_custom_props:
|
||||
type: web
|
||||
summary: Reading and writing data in an in-browser Key-Value store
|
||||
---
|
||||
|
||||
The Storage API, encompassing `localStorage` and `sessionStorage`, describes
|
||||
@ -14,6 +14,17 @@ This demo covers two common use patterns:
|
||||
- "Row Objects" shows a simple convention for loading and storing row objects
|
||||
- "Simple Strings" discusses how to persist and recover a raw Storage
|
||||
|
||||
:::note
|
||||
|
||||
Each browser demo was tested in the following environments:
|
||||
|
||||
| Browser | Date |
|
||||
|:------------|:-----------|
|
||||
| Chrome 116 | 2023-09-17 |
|
||||
| Safari 16.6 | 2023-09-17 |
|
||||
|
||||
:::
|
||||
|
||||
## Row Objects
|
||||
|
||||
Consider the following array of objects of data:
|
||||
@ -70,12 +81,6 @@ function localStorage_to_sheet() {
|
||||
|
||||
### Live Demo
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last tested on 2023 April 09.
|
||||
|
||||
:::
|
||||
|
||||
This example will fetch <https://sheetjs.com/pres.numbers>, fill `localStorage`
|
||||
with rows, then generate a worksheet from the rows and write to a new file.
|
||||
|
||||
@ -84,13 +89,15 @@ After saving the exported file, the Local Storage can be inspected in the
|
||||
|
||||
![Local Storage view in Developer Tools](pathname:///storageapi/lstorage.png)
|
||||
|
||||
:::caution
|
||||
:::caution pass
|
||||
|
||||
This example is for illustration purposes. If array of objects is available, it
|
||||
is strongly recommended to convert that array to a worksheet directly.
|
||||
|
||||
:::
|
||||
|
||||
<details><summary><b>Live Demo</b> (click to show)</summary>
|
||||
|
||||
```jsx live
|
||||
function SheetJStorage() {
|
||||
const [url, setUrl] = React.useState("https://sheetjs.com/pres.numbers");
|
||||
@ -129,6 +136,8 @@ function SheetJStorage() {
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Simple Strings
|
||||
|
||||
The ["Row Objects" approach](#row-objects) is strongly recommended when trying
|
||||
@ -155,7 +164,7 @@ The natural representation is an array of arrays:
|
||||
|
||||
#### Exporting Storage
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
Web Storage iteration order is not defined. By using indices as keys, the row
|
||||
objects approach has an ordering. That does not apply to the general case.
|
||||
@ -187,15 +196,11 @@ function ws_to_localStorage(ws) {
|
||||
|
||||
### Live Demo
|
||||
|
||||
:::note
|
||||
|
||||
This demo was last tested on 2023 April 09.
|
||||
|
||||
:::
|
||||
|
||||
This example fills `localStorage` with 10 random keys and 10 random values,
|
||||
generates a worksheet from the data and writes to a new file.
|
||||
|
||||
<details><summary><b>Live Demo</b> (click to show)</summary>
|
||||
|
||||
```jsx live
|
||||
function SheetJSRandomStorage() {
|
||||
const [out, setOut] = React.useState("");
|
||||
@ -231,3 +236,5 @@ function SheetJSRandomStorage() {
|
||||
</> );
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
@ -3,7 +3,7 @@ title: IndexedDB API
|
||||
pagination_prev: demos/desktop/index
|
||||
pagination_next: demos/local/index
|
||||
sidebar_custom_props:
|
||||
summary: Reading and writing data in browser storage
|
||||
summary: Reading and writing data in an in-browser NoSQL database
|
||||
---
|
||||
|
||||
<head>
|
||||
|
@ -9,16 +9,7 @@ import Tabs from '@theme/Tabs';
|
||||
import TabItem from '@theme/TabItem';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
This demo uses `node-google-spreadsheet` to interact with Google Sheets v4 API.
|
||||
|
||||
:::caution
|
||||
|
||||
Google Sheets deprecates APIs quickly and there is no guarantee that the
|
||||
referenced API version will be available in the future.
|
||||
|
||||
:::
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
This demo focuses on external data processing. For Google Apps Script custom
|
||||
functions, [the "Google Sheets" extension demo](/docs/demos/extensions/gsheet)
|
||||
@ -26,127 +17,123 @@ covers Apps Script integration.
|
||||
|
||||
:::
|
||||
|
||||
## Initial Configuration
|
||||
[Google Sheets](https://google.com/sheets/about/) is a collaborative spreadsheet
|
||||
service with powerful external APIs for automation.
|
||||
|
||||
Install the dependencies:
|
||||
[SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing
|
||||
data from spreadsheets.
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz google-spreadsheet@3.3.0`}
|
||||
</CodeBlock>
|
||||
This demo uses SheetJS to properly exchange data with spreadsheet files. We'll
|
||||
explore how to use NodeJS integration libraries and SheetJS in three data flows:
|
||||
|
||||
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`.
|
||||
- "Importing data": Data in a NUMBERS spreadsheet will be parsed using SheetJS
|
||||
libraries and written to a Google Sheets Document
|
||||
|
||||
The following helper function attempts to authenticate and access the specified
|
||||
sheet by ID. The code should be copied and saved to `common.js`:
|
||||
- "Exporting data": Data in Google Sheets will be pulled into arrays of objects.
|
||||
A workbook will be assembled and exported to Excel Binary workbooks (XLSB).
|
||||
|
||||
<details><summary><b>Code</b> (click to show)</summary>
|
||||
- "Exporting files": SheetJS libraries will read XLSX and ODS files exported by
|
||||
Google Sheets and generate CSV rows from every worksheet.
|
||||
|
||||
```js title=common.js
|
||||
const fs = require("fs");
|
||||
const { GoogleSpreadsheet } = require('google-spreadsheet');
|
||||
:::warning pass
|
||||
|
||||
module.exports = async(ID) => {
|
||||
/* get credentials */
|
||||
const creds = JSON.parse(fs.readFileSync('key.json'));
|
||||
It is strongly recommended to create a new Google account for testing.
|
||||
|
||||
/* initialize sheet and authenticate */
|
||||
const doc = new GoogleSpreadsheet(ID);
|
||||
await doc.useServiceAccountAuth(creds);
|
||||
await doc.loadInfo();
|
||||
return doc;
|
||||
}
|
||||
**One small mistake could result in a block or ban from Google services.**
|
||||
|
||||
:::
|
||||
|
||||
:::caution pass
|
||||
|
||||
Google Sheets deprecates APIs quickly and there is no guarantee that the
|
||||
referenced APIs will be available in the future.
|
||||
|
||||
:::
|
||||
|
||||
## Integration Details
|
||||
|
||||
This demo uses the following NodeJS modules:
|
||||
|
||||
- `google-auth-library`[^1] to authenticate with Google APIs
|
||||
- `node-google-spreadsheet`[^2] to interact with Google Sheets v4 API
|
||||
|
||||
:::info Initial Setup
|
||||
|
||||
There are a number of steps to enable the Google Sheets API and Google Drive API
|
||||
for an account. The [Complete Example](#complete-example) covers the process.
|
||||
|
||||
:::
|
||||
|
||||
### Authentication
|
||||
|
||||
It is strongly recommended to use a service account for Google API operations.
|
||||
The ["Service Account Setup" section](#service-account-setup) covers how to
|
||||
create a service account and generate a JSON key file.
|
||||
|
||||
```js title="Authenticate using a JSON key file"
|
||||
import { JWT } from 'google-auth-library'
|
||||
import { GoogleSpreadsheet } from 'google-spreadsheet';
|
||||
|
||||
// adjust the path to the actual key file.
|
||||
// highlight-next-line
|
||||
import creds from './sheetjs-test-726272627262.json' assert { type: "json" };
|
||||
|
||||
const jwt = new JWT({
|
||||
email: creds.client_email,
|
||||
key: creds.private_key,
|
||||
scopes: [
|
||||
'https://www.googleapis.com/auth/spreadsheets',
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
]
|
||||
});
|
||||
```
|
||||
|
||||
</details>
|
||||
### Connecting to Documents
|
||||
|
||||
To connect to existing documents, the document ID must be specified. This ID can
|
||||
be found from the edit URL.
|
||||
|
||||
The edit URL starts with `https://docs.google.com/spreadsheets/d/` and includes
|
||||
`/edit`. The ID is the string of characters between the slashes. For example:
|
||||
|
||||
```
|
||||
https://docs.google.com/spreadsheets/d/a_long_string_of_characters/edit#gid=0
|
||||
---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^--- ID
|
||||
```
|
||||
|
||||
The `GoogleSpreadsheet` constructor accepts a document ID and auth object:
|
||||
|
||||
```js title="Connect to a document"
|
||||
const doc = new GoogleSpreadsheet('DOCUMENT_ID', jwt);
|
||||
await doc.loadInfo();
|
||||
```
|
||||
|
||||
### Creating New Documents
|
||||
|
||||
The `createNewSpreadsheetDocument` makes a request to create a new document. It
|
||||
is strongly recommended to create a blank sheet.
|
||||
|
||||
```js title="Create a new document with blank sheet"
|
||||
const doc = await GoogleSpreadsheet.createNewSpreadsheetDocument(jwt, { title: 'Document Title' });
|
||||
const newSheet = await doc.addSheet({ title: 'Sheet Title' });
|
||||
```
|
||||
|
||||
### Array of Arrays
|
||||
|
||||
["Arrays of Arrays"](/docs/api/utilities/array#array-of-arrays) are the main
|
||||
data format for interchange with Google Sheets. The outer array object includes
|
||||
row arrays, and each row array includes data.
|
||||
|
||||
SheetJS provides methods for working with Arrays of Arrays:
|
||||
|
||||
- `aoa_to_sheet`[^3] creates SheetJS worksheet objects from arrays of arrays
|
||||
- `sheet_to_json`[^4] can generate arrays of arrays from SheetJS worksheets
|
||||
|
||||
## Export Document Data
|
||||
|
||||
The goal is to create an XLSB export from a Google Sheet. Google Sheets does
|
||||
not natively support the XLSB format. SheetJS fills the gap.
|
||||
|
||||
<details><summary><b>How to run locally</b> (click to show)</summary>
|
||||
|
||||
0) Follow the [Initial Configuration](#initial-configuration).
|
||||
|
||||
1) Create a new Google Sheet and share with the generated service account. It
|
||||
should be granted the "Editor" role
|
||||
|
||||
2) Install the dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz google-spreadsheet@3.3.0`}
|
||||
</CodeBlock>
|
||||
|
||||
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>
|
||||
|
||||
### Convert a Single Sheet
|
||||
|
||||
The idea is to extract the raw data from the Google Sheet headers and combine
|
||||
@ -196,115 +183,8 @@ async function doc_to_wb(doc) {
|
||||
|
||||
## Update Document Data
|
||||
|
||||
The goal is to refresh a Google Sheet based on a local file.
|
||||
|
||||
<details><summary><b>How to run locally</b> (click to show)</summary>
|
||||
|
||||
0) Follow the [Initial Configuration](#initial-configuration).
|
||||
|
||||
1) Create a new Google Sheet and share with the generated service account. It
|
||||
should be granted the "Editor" role
|
||||
|
||||
2) Install the dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i -S https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz google-spreadsheet@3.3.0`}
|
||||
</CodeBlock>
|
||||
|
||||
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>
|
||||
The goal is to import data from a NUMBERS file to Google Sheets. Google Sheets
|
||||
does not natively support the NUMBERS format. SheetJS fills the gap.
|
||||
|
||||
### Clear the Document
|
||||
|
||||
@ -428,75 +308,476 @@ async function sheet_load_from_ws(sheet, ws) {
|
||||
|
||||
## Raw File Exports
|
||||
|
||||
`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.
|
||||
In the web interface, Google Sheets can export documents to `XLSX` or `ODS`. The
|
||||
NodeJS library includes similar methods to perform the download[^5]:
|
||||
|
||||
This example prints the worksheet names and CSV exports of each sheet.
|
||||
| Format | Google Sheets Description | Method |
|
||||
|:-------|:--------------------------|:-----------------|
|
||||
| XLSX | Microsoft Excel (.xlsx) | `downloadAsXLSX` |
|
||||
| ODS | OpenDocument (.ods) | `downloadAsODS` |
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="xlsx" label="XLSX">
|
||||
The functions resolve to `Buffer` data. The `Buffer` objects can be parsed using
|
||||
the SheetJS `read`[^6] method:
|
||||
|
||||
```js
|
||||
const XLSX = require("xlsx");
|
||||
/* download XLSX */
|
||||
const ab = await doc.downloadAsXLSX();
|
||||
|
||||
(async() => {
|
||||
/* Connect to Google Sheet */
|
||||
const ID = "<google sheet id>";
|
||||
const doc = await require("./common")(ID);
|
||||
|
||||
/* Get file export */
|
||||
// highlight-next-line
|
||||
const buf = await doc.downloadAsXLSX();
|
||||
|
||||
/* Parse with SheetJS */
|
||||
const wb = XLSX.read(buf);
|
||||
|
||||
/* Loop over the worksheet names */
|
||||
wb.SheetNames.forEach(name => {
|
||||
/* Print the name to the console */
|
||||
console.log(name);
|
||||
|
||||
/* Get the corresponding worksheet object */
|
||||
const sheet = wb.Sheets[name];
|
||||
|
||||
/* Print a CSV export of the worksheet */
|
||||
console.log(XLSX.utils.sheet_to_csv(sheet));
|
||||
});
|
||||
})();
|
||||
/* parse */
|
||||
const wb = XLSX.read(buf);
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
At this point `wb` is a SheetJS workbook object[^7].
|
||||
|
||||
<TabItem value="ods" label="ODS">
|
||||
## Complete Example
|
||||
|
||||
```js
|
||||
const XLSX = require("xlsx");
|
||||
:::note
|
||||
|
||||
(async() => {
|
||||
/* Connect to Google Sheet */
|
||||
const ID = "<google sheet id>";
|
||||
const doc = await require("./common")(ID);
|
||||
This demo was last tested on 2023 September 17 using `google-auth-library` for
|
||||
authentication (`v8.9.0`) and `google-spreadsheet` for API access (`v4.1.0`).
|
||||
|
||||
/* Get file export */
|
||||
// highlight-next-line
|
||||
const buf = await doc.downloadAsODS();
|
||||
:::
|
||||
|
||||
/* Parse with SheetJS */
|
||||
const wb = XLSX.read(buf);
|
||||
### Account Setup
|
||||
|
||||
/* Loop over the worksheet names */
|
||||
wb.SheetNames.forEach(name => {
|
||||
/* Print the name to the console */
|
||||
console.log(name);
|
||||
0) Create a new Google account or log into an existing account.
|
||||
|
||||
/* Get the corresponding worksheet object */
|
||||
const sheet = wb.Sheets[name];
|
||||
:::caution pass
|
||||
|
||||
/* Print a CSV export of the worksheet */
|
||||
console.log(XLSX.utils.sheet_to_csv(sheet));
|
||||
});
|
||||
})();
|
||||
A valid phone number (for SMS verification) may be required.
|
||||
|
||||
:::
|
||||
|
||||
1) Open <https://console.cloud.google.com> in a web browser. Review the Google
|
||||
Cloud Platform Terms of Service.
|
||||
|
||||
:::warning pass
|
||||
|
||||
You must agree to the Google Cloud Platform Terms of Service to use the APIs.
|
||||
|
||||
:::
|
||||
|
||||
### Project Setup
|
||||
|
||||
2) Create a new Project.
|
||||
|
||||
If the account does not have an existing project, click "CREATE PROJECT"
|
||||
|
||||
If the account has an existing project, click the project selector (`:·` icon)
|
||||
and click "NEW PROJECT" in the modal.
|
||||
|
||||
3) In the New Project screen, enter "SheetJS Test" in the Project name textbox
|
||||
and select "No organization" in the Location box. Click "CREATE"
|
||||
|
||||
### API Setup
|
||||
|
||||
:::info pass
|
||||
|
||||
The goal of this section is to enable Google Sheets API and Google Drive API.
|
||||
|
||||
:::
|
||||
|
||||
4) Click the Project Selector (`:·` icon) and select "SheetJS Test"
|
||||
|
||||
5) In the left sidebar, click "Enabled APIs and services".
|
||||
|
||||
6) Near the top of the page, click "+ ENABLE APIS AND SERVICES".
|
||||
|
||||
7) In the search bar near the middle of the page, type "Sheets" and look for
|
||||
"Google Sheets API". Click the card
|
||||
|
||||
8) In the Product Details screen, click the blue "ENABLE" button.
|
||||
|
||||
9) Click the left arrow (`<-`) next to API/Service details.
|
||||
|
||||
10) In the search bar near the middle of the page, type "Drive" and look for
|
||||
"Google Drive API". Click the card.
|
||||
|
||||
11) In the Product Details screen, click the blue "ENABLE" button.
|
||||
|
||||
### Service Account Setup
|
||||
|
||||
:::info pass
|
||||
|
||||
The goal of this section is to create a service account and generate a JSON key.
|
||||
|
||||
:::
|
||||
|
||||
#### Create Service Account
|
||||
|
||||
12) Go to <https://console.cloud.google.com>.
|
||||
|
||||
13) Click the Project Selector (`:·` icon) and select "SheetJS Test".
|
||||
|
||||
14) Click "Dashboard".
|
||||
|
||||
15) In the left sidebar, hover over "APIs and Services" and select "Credentials"
|
||||
|
||||
16) Click "+ CREATE CREDENTIALS". In the dropdown, select "Service Account"
|
||||
|
||||
17) Enter "SheetJService" for Service account name. Click "CREATE AND CONTINUE"
|
||||
|
||||
:::note pass
|
||||
|
||||
The Service account ID is generated automatically.
|
||||
|
||||
:::
|
||||
|
||||
18) In Step 2 "Grant this service account access to project", click CONTINUE
|
||||
|
||||
19) In Step 3 click "DONE". You will be taken back to the credentials screen
|
||||
|
||||
#### Create JSON Key
|
||||
|
||||
20) Look for "SheetJService" in the "Service Accounts" table and click the email
|
||||
address in the row
|
||||
|
||||
21) Click the email address of the account in the "Service Accounts" table.
|
||||
|
||||
22) Click "KEYS" in the horizontal bar near the top of the page.
|
||||
|
||||
23) Click "ADD KEY" and select "Create new key" in the dropdown.
|
||||
|
||||
24) In the popup, select the "JSON" radio button and click "CREATE". The page
|
||||
will download a JSON file.
|
||||
|
||||
25) Click "CLOSE"
|
||||
|
||||
### Create Document
|
||||
|
||||
:::info pass
|
||||
|
||||
The goal of this section is to create a document from the service account and
|
||||
share with the main account.
|
||||
|
||||
:::
|
||||
|
||||
26) Create a `SheetJSGS` folder and initialize:
|
||||
|
||||
```bash
|
||||
mkdir SheetJSGS
|
||||
cd SheetJSGS
|
||||
npm init -y
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
27) Copy the JSON file from step 24 into the project folder.
|
||||
|
||||
28) Install dependencies:
|
||||
|
||||
<CodeBlock language="bash">{`\
|
||||
npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz google-spreadsheet google-auth-library`}
|
||||
</CodeBlock>
|
||||
|
||||
29) Save the following script to `init.mjs`:
|
||||
|
||||
```js title="init.mjs"
|
||||
import { JWT } from 'google-auth-library'
|
||||
import { GoogleSpreadsheet } from 'google-spreadsheet';
|
||||
|
||||
// highlight-next-line
|
||||
import creds from './sheetjs-test-726272627262.json' assert { type: "json" };
|
||||
|
||||
const jwt = new JWT({
|
||||
email: creds.client_email,
|
||||
key: creds.private_key,
|
||||
scopes: [
|
||||
'https://www.googleapis.com/auth/spreadsheets',
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
]
|
||||
});
|
||||
|
||||
const doc = await GoogleSpreadsheet.createNewSpreadsheetDocument(jwt, { title: 'test from NodeJS' });
|
||||
const newSheet = await doc.addSheet({ title: 'SheetJSTest' });
|
||||
// highlight-next-line
|
||||
await doc.share('YOUR_ADDRESS@gmail.com');
|
||||
```
|
||||
|
||||
Edit the highlighted lines as follows:
|
||||
|
||||
- `'./sheetjs-test-726272627262.json'` should be replaced with the name of the
|
||||
JSON file in step 27. The `./` prefix is required!
|
||||
|
||||
- `'YOUR_ADDRESS@gmail.com'` should be replaced with the Google Account email
|
||||
address from step 0.
|
||||
|
||||
30) Run the script:
|
||||
|
||||
```bash
|
||||
node init.mjs
|
||||
```
|
||||
|
||||
31) Sign into Google Sheets. A shared document "test from NodeJS" should be
|
||||
displayed in the table. It will be owned by the service account.
|
||||
|
||||
32) Open the shared document from step 31.
|
||||
|
||||
33) Copy the URL and extract the document ID.
|
||||
|
||||
The URL of the document will look like
|
||||
|
||||
```
|
||||
https://docs.google.com/spreadsheets/d/a_long_string_of_characters/edit#gid=0
|
||||
---------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^--- ID
|
||||
```
|
||||
|
||||
The ID is a long string of letters and numbers and underscore characters (`_`)
|
||||
just before the `/edit` part of the URL.
|
||||
|
||||
### Load Data from NUMBERS
|
||||
|
||||
:::info pass
|
||||
|
||||
The goal of this section is to update the new document with data from a sample
|
||||
NUMBERS file.
|
||||
|
||||
:::
|
||||
|
||||
34) Download the [test file `pres.numbers`](https://sheetjs.com/pres.numbers):
|
||||
|
||||
```bash
|
||||
curl -LO https://sheetjs.com/pres.numbers
|
||||
```
|
||||
|
||||
35) Save the following script to `load.mjs`:
|
||||
|
||||
```js title="load.mjs"
|
||||
import { JWT } from 'google-auth-library'
|
||||
import { GoogleSpreadsheet } from 'google-spreadsheet';
|
||||
|
||||
import { set_fs, readFile, utils } from 'xlsx';
|
||||
import * as fs from 'fs';
|
||||
set_fs(fs);
|
||||
|
||||
// highlight-next-line
|
||||
import creds from './sheetjs-test-726272627262.json' assert { type: "json" };
|
||||
|
||||
const jwt = new JWT({
|
||||
email: creds.client_email,
|
||||
key: creds.private_key,
|
||||
scopes: [
|
||||
'https://www.googleapis.com/auth/spreadsheets',
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
]
|
||||
});
|
||||
|
||||
// highlight-next-line
|
||||
const doc = new GoogleSpreadsheet('DOCUMENT_ID', jwt);
|
||||
await doc.loadInfo();
|
||||
|
||||
const wb = readFile("pres.numbers");
|
||||
|
||||
/* 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 = 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 = utils.sheet_to_json(ws, {header: 1});
|
||||
await sheet.setHeaderRow(aoa[0])
|
||||
await sheet.addRows(aoa.slice(1));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Edit the highlighted lines as follows:
|
||||
|
||||
- `'./sheetjs-test-726272627262.json'` should be replaced with the name of the
|
||||
JSON file in step 27. The `./` prefix is required!
|
||||
|
||||
- `'DOCUMENT_ID'` should be replaced with the Document ID from step 33.
|
||||
|
||||
36) Run the script:
|
||||
|
||||
```bash
|
||||
node load.mjs
|
||||
```
|
||||
|
||||
37) Sign into Google Sheets and open the "test from NodeJS" shared document. It
|
||||
should show a list of Presidents, matching the contents of the test file.
|
||||
|
||||
### Export Data to XLSB
|
||||
|
||||
:::info pass
|
||||
|
||||
The goal of this section is to export the raw data from Google Sheets to XLSB.
|
||||
|
||||
:::
|
||||
|
||||
38) Save the following script to `dump.mjs`:
|
||||
|
||||
```js title="dump.mjs"
|
||||
import { JWT } from 'google-auth-library'
|
||||
import { GoogleSpreadsheet } from 'google-spreadsheet';
|
||||
|
||||
import { set_fs, writeFile, utils } from 'xlsx';
|
||||
import * as fs from 'fs';
|
||||
set_fs(fs);
|
||||
|
||||
// highlight-next-line
|
||||
import creds from './sheetjs-test-726272627262.json' assert { type: "json" };
|
||||
|
||||
const jwt = new JWT({
|
||||
email: creds.client_email,
|
||||
key: creds.private_key,
|
||||
scopes: [
|
||||
'https://www.googleapis.com/auth/spreadsheets',
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
]
|
||||
});
|
||||
|
||||
// highlight-next-line
|
||||
const doc = new GoogleSpreadsheet('DOCUMENT_ID', jwt);
|
||||
await doc.loadInfo();
|
||||
|
||||
const wb = utils.book_new();
|
||||
|
||||
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 = utils.aoa_to_sheet(aoa);
|
||||
|
||||
/* add to workbook */
|
||||
utils.book_append_sheet(wb, ws, name);
|
||||
}
|
||||
|
||||
/* write to SheetJS.xlsb */
|
||||
writeFile(wb, "SheetJS.xlsb");
|
||||
```
|
||||
|
||||
Edit the highlighted lines as follows:
|
||||
|
||||
- `'./sheetjs-test-726272627262.json'` should be replaced with the name of the
|
||||
JSON file in step 27. The `./` prefix is required!
|
||||
|
||||
- `'DOCUMENT_ID'` should be replaced with the Document ID from step 33.
|
||||
|
||||
39) Run the script:
|
||||
|
||||
```bash
|
||||
node load.mjs
|
||||
```
|
||||
|
||||
The script should create a file `SheetJS.xlsb` in the project folder. This file
|
||||
can be opened in Excel
|
||||
|
||||
40) Sign into Google Sheets and open the "test from NodeJS" shared document. It
|
||||
should show a list of Presidents, matching the contents of the test file.
|
||||
|
||||
### Export Raw Files
|
||||
|
||||
:::info pass
|
||||
|
||||
The goal of this section is to parse the Google Sheets XLSX export and generate
|
||||
CSV files for each worksheet.
|
||||
|
||||
:::
|
||||
|
||||
41) Sign into Google Sheets and open the "test from NodeJS" shared document.
|
||||
|
||||
42) Click the Plus (`+`) icon in the lower left corner to create a new worksheet.
|
||||
|
||||
43) In the new worksheet, set cell A1 to the formula `=SEQUENCE(3,5)`. This will
|
||||
assign a grid of values
|
||||
|
||||
44) Save the following script to `raw.mjs`:
|
||||
|
||||
```js title="raw.mjs"
|
||||
import { JWT } from 'google-auth-library'
|
||||
import { GoogleSpreadsheet } from 'google-spreadsheet';
|
||||
|
||||
import { read, utils } from 'xlsx';
|
||||
|
||||
// highlight-next-line
|
||||
import creds from './sheetjs-test-726272627262.json' assert { type: "json" };
|
||||
|
||||
const jwt = new JWT({
|
||||
email: creds.client_email,
|
||||
key: creds.private_key,
|
||||
scopes: [
|
||||
'https://www.googleapis.com/auth/spreadsheets',
|
||||
'https://www.googleapis.com/auth/drive.file',
|
||||
]
|
||||
});
|
||||
|
||||
// highlight-next-line
|
||||
const doc = new GoogleSpreadsheet('DOCUMENT_ID', jwt);
|
||||
await doc.loadInfo();
|
||||
|
||||
const buf = await doc.downloadAsXLSX();
|
||||
|
||||
/* Parse with SheetJS */
|
||||
const wb = read(buf);
|
||||
|
||||
/* Loop over the worksheet names */
|
||||
wb.SheetNames.forEach(name => {
|
||||
/* Print the name to the console */
|
||||
console.log(name);
|
||||
|
||||
/* Get the corresponding worksheet object */
|
||||
const sheet = wb.Sheets[name];
|
||||
|
||||
/* Print a CSV export of the worksheet */
|
||||
console.log(utils.sheet_to_csv(sheet));
|
||||
});
|
||||
```
|
||||
|
||||
Edit the highlighted lines as follows:
|
||||
|
||||
- `'./sheetjs-test-726272627262.json'` should be replaced with the name of the
|
||||
JSON file in step 27. The `./` prefix is required!
|
||||
|
||||
- `'DOCUMENT_ID'` should be replaced with the Document ID from step 33.
|
||||
|
||||
45) Run the script:
|
||||
|
||||
```bash
|
||||
node raw.mjs
|
||||
```
|
||||
|
||||
The script will display the sheet names and CSV rows from both worksheets.
|
||||
|
||||
[^1]: The package name is [`google-auth-library`](https://www.npmjs.com/package/google-auth-library)
|
||||
[^2]: The project name is [`node-google-spreadsheet`](https://github.com/theoephraim/node-google-spreadsheet) but the module name is `google-spreadsheet`.
|
||||
[^3]: See [`aoa_to_sheet` in "Utilities"](/docs/api/utilities/array#array-of-arrays-input)
|
||||
[^4]: See [`sheet_to_json` in "Utilities"](/docs/api/utilities/array#array-output)
|
||||
[^5]: See ["Exporting Data"](https://theoephraim.github.io/node-google-spreadsheet/#/guides/exports) in the `node-google-spreadsheet` documentation
|
||||
[^6]: See [`read` in "Reading Files"](/docs/api/parse-options)
|
||||
[^7]: See ["Workbook Object"](/docs/csf/book) for a description of the workbook object or ["API Reference"](/docs/api) for various methods to work with workbook and sheet objects.
|
||||
|
@ -7,7 +7,7 @@ pagination_next: demos/bigdata/index
|
||||
import current from '/version.js';
|
||||
import CodeBlock from '@theme/CodeBlock';
|
||||
|
||||
:::note
|
||||
:::note pass
|
||||
|
||||
This demo focuses on Google Apps Script custom functions. For external data
|
||||
processing, [the "Google Sheets" cloud data demo](/docs/demos/cloud/gsheet)
|
||||
@ -150,7 +150,7 @@ curl -LO https://cdn.sheetjs.com/xlsx-${current}/package/dist/xlsx.full.min.js`}
|
||||
npx @google/clasp push
|
||||
```
|
||||
|
||||
:::caution
|
||||
:::caution pass
|
||||
|
||||
If the Google Apps Script API is not enabled, the command will display an object
|
||||
with `code: 403` and an error message about the Apps Script API:
|
||||
|
@ -59,7 +59,7 @@ NodeJS push streams were introduced in 2012. The text streaming methods `to_csv`
|
||||
and `to_html` are supported in NodeJS v0.10 and later while the object streaming
|
||||
method `to_json` is supported in NodeJS v0.12 and later.
|
||||
|
||||
The first streaming write function, `to_csv`, was introduced in April 2017. It
|
||||
The first streaming write function, `to_csv`, was introduced in early 2017. It
|
||||
used and still uses the same NodeJS streaming API.
|
||||
|
||||
Years later, browser vendors are settling on a different stream API.
|
||||
|
@ -214,6 +214,7 @@ const config = {
|
||||
{ from: '/docs/demos/clipboard', to: '/docs/demos/local/clipboard/' },
|
||||
{ from: '/docs/demos/localfile', to: '/docs/demos/local/file/' },
|
||||
{ from: '/docs/demos/data/indexeddb', to: '/docs/demos/local/indexeddb/' },
|
||||
{ from: '/docs/demos/data/storageapi', to: '/docs/demos/local/storageapi/' },
|
||||
/* desktop */
|
||||
{ from: '/docs/demos/cli', to: '/docs/demos/desktop/cli/' },
|
||||
{ from: '/docs/getting-started/demos/cli', to: '/docs/demos/desktop/cli/' },
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 86 KiB After Width: | Height: | Size: 103 KiB |
Binary file not shown.
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 72 KiB |
Loading…
Reference in New Issue
Block a user