--- title: Airtable pagination_prev: demos/local/index pagination_next: demos/extensions/index --- import current from '/version.js'; import CodeBlock from '@theme/CodeBlock'; [Airtable](https://airtable.com/) is a collaborative dataset hosting service. [SheetJS](https://sheetjs.com) is a JavaScript library for reading and writing data from spreadsheets. This demo uses SheetJS to properly exchange data with spreadsheet files. We'll explore how to use the `airtable` NodeJS library and SheetJS in two data flows: - "Exporting data": Data in Airtable will be pulled into an array of objects and exported to XLSB spreadsheets using SheetJS libraries. - "Importing data": Data in an XLSX spreadsheet will be parsed using SheetJS libraries and appended to a dataset in Airtable ## NodeJS Integration 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`. 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 pass 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 September 03. At the time, free accounts included limited API access. ::: 0) Create a free Airtable account and verify the email address. ### Personal Access Token :::note pass 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 `SheetJSAirtableRead.js`: ```js title="SheetJSAirtableRead.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) Install dependencies: {`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz airtable`} 11) Run the script: ```bash node SheetJSAirtableRead.js ``` The script should write `SheetJSAirtable.xlsb`. The file can be opened in Excel. ### Importing Data 12) 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 ``` 13) Save the following to `SheetJSAirtableWrite.js`: ```js title="SheetJSAirtableWrite.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 }))); })(); ``` 14) Replace the values in the highlighted lines with the PAT and workspace name. 15) Install dependencies: {`\ npm i --save https://cdn.sheetjs.com/xlsx-${current}/xlsx-${current}.tgz airtable`} 16) Run the script: ```bash node SheetJSAirtableWrite.js ``` Open Airtable and verify the new row was added: ![Final Result in Airtable](pathname:///airtable/post.png)