--- title: Airtable pagination_prev: demos/local/index pagination_next: demos/extensions/index --- import current from '/version.js'; import CodeBlock from '@theme/CodeBlock'; Airtable recommends Personal Access Tokens for interacting with their API. When fetching data from the API, the result will include an array of row objects that can be converted to a worksheet with `XLSX.utils.json_to_sheet`. The API methods to write data will accept row objects generated by `XLSX.utils.sheet_to_json`. ## NodeJS Integration The main module is `airtable` and can be installed with `npm`: {`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.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 :::note This demo was last tested on 2023 February 15. At the time, it was possible to create a free account with API access. ::: 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 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)