forked from sheetjs/docs.sheetjs.com
193 lines
5.4 KiB
Markdown
193 lines
5.4 KiB
Markdown
|
---
|
||
|
title: Airtable
|
||
|
pagination_prev: demos/static/index
|
||
|
pagination_next: demos/cli
|
||
|
---
|
||
|
|
||
|
At the time of writing (2023 February 15), Airtable recommends Personal Access
|
||
|
Tokens for interacting with the official API.
|
||
|
|
||
|
## NodeJS Integration
|
||
|
|
||
|
The main module is `airtable` and can be installed with `npm`:
|
||
|
|
||
|
```bash
|
||
|
npm i --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz airtable
|
||
|
```
|
||
|
|
||
|
To obtain a reference to a table, code needs a [PAT](#personal-access-token),
|
||
|
the name of the workspace (typically starting with `app`), and the name of the
|
||
|
desired table (the Excel import typically supports the worksheet name):
|
||
|
|
||
|
```js
|
||
|
const Airtable = require("airtable"), XLSX = require("xlsx");
|
||
|
/* query all records in a table */
|
||
|
const conn = new Airtable({apiKey: "PAT...", /* and other options ... */});
|
||
|
const table = conn.base("app...").table("tablename...");
|
||
|
```
|
||
|
|
||
|
### Exporting Data
|
||
|
|
||
|
When querying data, a result set will be a simple array of Record objects. The
|
||
|
`fields` property is a simple JS object compatible with `json_to_sheet`:
|
||
|
|
||
|
```js
|
||
|
/** Create SheetJS worksheet from Airtable table */
|
||
|
async function airtable_to_worksheet(table) {
|
||
|
/* get all rows */
|
||
|
const result = await table.select().all();
|
||
|
|
||
|
/* pull raw objects from the result */
|
||
|
// highlight-next-line
|
||
|
const aoo = result.map(r => r.fields);
|
||
|
|
||
|
/* create a worksheet */
|
||
|
const worksheet = XLSX.utils.json_to_sheet(aoo);
|
||
|
return worksheet;
|
||
|
}
|
||
|
```
|
||
|
|
||
|
:::caution
|
||
|
|
||
|
The results are not guaranteed to be sorted. The official API includes options
|
||
|
for sorting by fields.
|
||
|
|
||
|
:::
|
||
|
|
||
|
### Importing Data
|
||
|
|
||
|
When inserting records, each object should be wrapped in a parent object with a
|
||
|
single `fields` property:
|
||
|
|
||
|
```js
|
||
|
/** Append records from a SheetJS worksheet to Airtable table */
|
||
|
async function airtable_load_worksheet(table, worksheet) {
|
||
|
/* suppose the field names */
|
||
|
const aoo = XLSX.utils.sheet_to_json(worksheet);
|
||
|
|
||
|
/* reshape to be compatible with Airtable API */
|
||
|
// highlight-next-line
|
||
|
const airtable_rows = aoo.map(fields => ({ fields }));
|
||
|
|
||
|
/* upload data */
|
||
|
return await table.create(airtable_rows);
|
||
|
}
|
||
|
```
|
||
|
|
||
|
## Complete Example
|
||
|
|
||
|
0) Create a free Airtable account.
|
||
|
|
||
|
### Personal Access Token
|
||
|
|
||
|
:::note
|
||
|
|
||
|
In the past, Airtable offered API keys. They are slated to deprecate API keys
|
||
|
in January 2024. They recommend "Personal Access Tokens" for operations.
|
||
|
|
||
|
:::
|
||
|
|
||
|
API actions will require a PAT, which must be created through the developer hub:
|
||
|
|
||
|
1) Click on account icon (topright area of the page) and select "Developer Hub".
|
||
|
|
||
|
2) Click "Create Token".
|
||
|
|
||
|
3) In the form, make the following selections:
|
||
|
|
||
|
- Name: enter any name (for example, "SheetJS Test")
|
||
|
- Scopes: `data.records:read` and `data.records:write` (adding 2 scopes)
|
||
|
- Access: "All current and future bases in all current and future workspaces"
|
||
|
|
||
|
The form will look like the screenshot below:
|
||
|
|
||
|
![Airtable PAT Form](pathname:///airtable/pat.png)
|
||
|
|
||
|
4) Click "Create Token" and you will see a popup. Copy the token and save it.
|
||
|
|
||
|
### Workspace
|
||
|
|
||
|
For the purposes of this demo, a sample workspace should be created:
|
||
|
|
||
|
5) Download <https://sheetjs.com/pres.xlsx>
|
||
|
|
||
|
6) Create a project in Airtable using "Quickly upload". Select "Microsoft Excel"
|
||
|
and select the downloaded file from step 1. Click "Upload", then "Import".
|
||
|
|
||
|
7) A workspace will be created. The name will be found in the URL. For example:
|
||
|
|
||
|
```
|
||
|
https://airtable.com/appblahblah/tblblahblah/blahblah
|
||
|
--------------------/^^^^^^^^^^^/ workspace name
|
||
|
```
|
||
|
|
||
|
the first part after the `.com` will be the workspace name.
|
||
|
|
||
|
### Exporting Data
|
||
|
|
||
|
8) Save the following to `read.js`:
|
||
|
|
||
|
```js title="read.js"
|
||
|
const Airtable = require("airtable"), XLSX = require("xlsx");
|
||
|
// highlight-start
|
||
|
/* replace the value with the personal access token */
|
||
|
const apiKey = "pat...";
|
||
|
/* replace the value with the workspace name */
|
||
|
const base = "app...";
|
||
|
// highlight-end
|
||
|
(async() => {
|
||
|
const conn = new Airtable({ apiKey });
|
||
|
const table = conn.base(base).table("Sheet1");
|
||
|
const result = await table.select().all();
|
||
|
const aoo = result.map(r => r.fields);
|
||
|
const ws = XLSX.utils.json_to_sheet(aoo);
|
||
|
const wb = XLSX.utils.book_new();
|
||
|
XLSX.utils.book_append_sheet(wb, ws, "Sheet1");
|
||
|
XLSX.writeFile(wb, "SheetJSAirtable.xlsb");
|
||
|
})();
|
||
|
```
|
||
|
|
||
|
9) Replace the values in the highlighted lines with the PAT and workspace name.
|
||
|
|
||
|
10) Run `node read.js`. The script should write `SheetJSAirtable.xlsb`. The file
|
||
|
can be opened in Excel.
|
||
|
|
||
|
### Importing Data
|
||
|
|
||
|
11) Create a file `SheetJSAirpend.xlsx` with some new records in sheet `Sheet1`:
|
||
|
|
||
|
![Records to append](pathname:///airtable/airpend.png)
|
||
|
|
||
|
`npx xlsx-cli SheetJSAirpend.xlsx` should print the following data:
|
||
|
|
||
|
```csv
|
||
|
Sheet1
|
||
|
Name,Index
|
||
|
Someone Else,47
|
||
|
```
|
||
|
|
||
|
12) Save the following to `write.js`:
|
||
|
|
||
|
```js title="write.js"
|
||
|
const Airtable = require("airtable"), XLSX = require("xlsx");
|
||
|
// highlight-start
|
||
|
/* replace the value with the personal access token */
|
||
|
const apiKey = "pat...";
|
||
|
/* replace the value with the workspace name */
|
||
|
const base = "app...";
|
||
|
// highlight-end
|
||
|
(async() => {
|
||
|
const conn = new Airtable({ apiKey });
|
||
|
const table = conn.base(base).table("Sheet1");
|
||
|
const wb = XLSX.readFile("SheetJSAirpend.xlsx");
|
||
|
const ws = wb.Sheets["Sheet1"];
|
||
|
const aoo = XLSX.utils.sheet_to_json(ws);
|
||
|
await table.create(aoo.map(fields => ({ fields })));
|
||
|
})();
|
||
|
```
|
||
|
|
||
|
13) Replace the values in the highlighted lines with the PAT and workspace name.
|
||
|
|
||
|
14) Run `node write.js`. Open Airtable and verify the new row:
|
||
|
|
||
|
![Final Result in Airtable](pathname:///airtable/post.png)
|