Tables: formulas, import and export

How to compute with formulas in a Table, bring rows in from CSV or Excel, and take them out again, with the limits and rules that apply.

A Table is a channel type: one grid of typed columns and rows, with the channel's chat beside it. This guide is for people automating or migrating data. Everyday editing is in the app.

Before you start

Formulas

A formula starts with = and is worked out on the server, so every viewer sees the same result. There are two kinds:

References

You write It means
[Hours]@row This row's Hours (the common case; the editor adds @row for you)
Hours@row The same, for a column name without spaces
[Hours]3 Hours in row 3. It follows the row if it moves, and shows #REF! if it's deleted.
[Hours]:[Hours] The whole Hours column
[Hours]1:[Hours]5 Rows 1 to 5 of Hours. [Hours]$1:[Hours]@row is a running total.
[Task]:[Rate] Every column from Task to Rate, as a table for VLOOKUP or INDEX
[Hours]@row:[Rate]@row This row, Hours through Rate
@cell Inside a condition, the cell being tested: COUNTIF([Hours]:[Hours], @cell > 8)

Formulas are stored by column and row identity, not by name, so renaming a column or moving a row never breaks one: the formula's text is shown with the new names.

Operators and values

Operators, lowest precedence first: comparisons = <> != < <= > >=, text join &, + -, * /, ^, % (50% is 0.5), and unary minus (-2^2 is 4, as in Excel). Text goes in "double quotes" ("" for a quote inside). TRUE, FALSE and error values such as #N/A can be written too.

Functions

The formula editor lists and autocompletes every function with its syntax. AVG is another name for AVERAGE, and RANK.EQ for RANKEQ.

Group Functions
Sums and counts SUM, PRODUCT, AVERAGE, MEDIAN, MIN, MAX, LARGE, SMALL, RANKEQ, COUNT, COUNTA, COUNTBLANK, COUNTM
Conditional COUNTIF, COUNTIFS, SUMIF, SUMIFS, AVERAGEIF, AVERAGEIFS
Rounding and maths ROUND, ROUNDUP, ROUNDDOWN, MROUND, INT, TRUNC, CEILING, FLOOR, MOD, ABS, SIGN, SQRT, POWER, EXP, LN, LOG, LOG10, PI, ISEVEN, ISODD
Logic IF, IFS, SWITCH, AND, OR, XOR, NOT, IFERROR
Checks ISBLANK, ISNUMBER, ISTEXT, ISDATE, ISBOOLEAN, ISERROR, ISNA, NA
Text CONCATENATE, CONCAT, JOIN, LEFT, RIGHT, MID, LEN, LOWER, UPPER, PROPER, TRIM, SUBSTITUTE, REPLACE, FIND, SEARCH, TEXT, VALUE, REPT, CHAR, UNICHAR, EXACT
Dates TODAY, NOW, DATE, DATEONLY, YEAR, MONTH, DAY, WEEKDAY, WEEKNUMBER, YEARDAY, HOUR, MINUTE, DAYS, DATEDIF, EDATE, EOMONTH, NETDAYS, NETWORKDAYS, WORKDAY
Lookup VLOOKUP, HLOOKUP, INDEX, MATCH, XLOOKUP, COLLECT, DISTINCT, CONTAINS, HAS
The Table ROWNUMBER

A few that are easy to miss:

=IF([Due]@row < TODAY(), "Late", "")
=SUMIFS([Hours]:[Hours], [Owner]:[Owner], "Dana", [Status]:[Status], "Done")
=JOIN(COLLECT([Task]:[Task], [Status]:[Status], "Blocked"), ", ")
=NETWORKDAYS([Start]@row, [Due]@row)

Errors

Shows Means
#DIV/0! Divided by zero or an empty cell
#VALUE! The wrong kind of value (text where a number belongs, a range where one cell belongs)
#REF! A column or row that doesn't exist (was it deleted?)
#NAME? A function Tables doesn't have
#N/A A lookup didn't find the value
#NUM! A number out of range
#CIRCULAR! The cell depends on itself through other formulas
#BUDGET! The formula needs more work than one cell may use
#ERROR! The text can't be read as a formula (the editor says where)

When formulas recalculate

After every change, the formulas that read what changed are worked out again, and their new results arrive with the edit. In a very large Table, the first 5,000 formula cells are done at once and the rest follow within about 15 seconds.

Import from CSV or Excel

Choose Import CSV / XLSX on the Table's toolbar (on a computer or a phone). Rows are added at the end of the Table.

  1. Choose a .csv, .tsv or .xlsx file, or paste rows (copying from a spreadsheet works). For an Excel file, pick the Worksheet.
  2. Say whether The first line is a header row.
  3. Check the preview. For each file column it shows what it Looks like (text, number, currency, percent, date, checkbox, dropdown, link or person) and where it Goes into: the column with the same name, a new column (if you manage the channel), or Don't import. People are matched by a member's email address, never by name.
  4. The first 50 rows are shown with every problem marked, and every row is checked, along with the size against your Table's cell limit. Problems block the import unless you tick Leave out rows with problems.
  5. Choose Import.

Undo

An import is one change. Undo import on the result screen, or Undo it next to "Last import" when you open the dialog again, removes its rows and any columns it added. The rows go to the Table's deleted rows for 30 days. The person who imported, or anyone who manages the channel, may undo.

Excel files

Only values are imported:

Moving from Smartsheet: in Smartsheet, File → Export → Export to Microsoft Excel, then import the .xlsx and choose the data tab (not the comments or summary tabs).

Export

Export CSV and Export XLSX are on the same toolbar, for anyone who can see the Table. An export holds exactly the rows and columns you can see on the server. Your own sorting, filtering, hidden columns and widths in the browser are not applied; for a restricted export, publish a shared view.

Shared views

A shared view publishes some of a Table's rows and columns as its own channel, for an outside party. Exporting from a view's channel gives only the view: its rows, its columns and its name, never the rest of the Table or any formula text. A withdrawn view can't be exported. Importing, undoing imports and row conversations belong to the Table itself, not to a view.

Row conversations

Choose 💬 on a row to open its thread. The first comment posts an anchor message in the channel's chat ("💬 Pull permits · row 14 in project-tracker") and your comment is its first reply, so mentions, notifications, search and reactions work as in any thread. The 💬 shows the reply count. Deleting the row keeps the conversation, and its card says the row was deleted.

What data moves

Nothing leaves Missived. Formulas are worked out on our servers, never by a third-party service. Imports are read on the server and the file itself isn't kept; exports go only to the person who downloads them. In an org that encrypts content, cell values, formulas and their results are encrypted at rest like messages. The org's audit log records imports, undone imports and exports with counts only, never the data.

Limits

CSV XLSX
File size 5 MB 2 MB (20 MB once unpacked), and at most 5 MB of values
Rows per import 10,000 10,000
Columns 100 100
Other 20 worksheets, 100,000 cells, 4,000 characters per cell, 15 seconds to read

An Excel file over a limit is refused, never cut short: split it, or save it as CSV and import it in parts. Your Table's cell limit (250,000 on Business) applies too.

Troubleshooting

Message What to do
"Choose an XLSX up to 2 MB; split larger workbooks or use CSV." Keep only the data tab, split the workbook, or use Save As → CSV UTF-8 in Excel.
"Workbook took too long to read." Split it or use CSV.
"Only people who manage this channel can add columns" Map every file column to an existing one, or skip it.
A column is locked Only people who manage the channel can import into it.
A person column doesn't match People are matched by the email of an org member; check the addresses.

Tables API

Read and write a Table's rows over the REST API with an API token (Settings → Developer, or an app's token). Everything below is in the API reference under Tables.

Scope Lets a token
tables:read list Tables, read columns and rows, find rows, export CSV / XLSX
tables:write add, change, upsert and delete rows

What a token reaches is what its owner reaches in the app. A person's token sees the Tables they can open (a guest's, only the Tables in their workspaces) and edits where they can edit. An app's token sees only Tables and shared views in channels the app was added to. Through a shared view a token gets the view and nothing else: its columns, its rows, its rules for adding and deleting — never the Table behind it. Columns and settings are not changed through the API.

Find a Table

GET /v1/orgs/{orgId}/tables
GET /v1/tables/{tableId}

Each Table comes with its columns: id, name, type, writable, and a select column's choices. A shared view has its own id and kind: "view"; use it like any Table id.

Read rows

GET /v1/tables/{tableId}/rows?limit=50&cursor=…
GET /v1/tables/{tableId}/rows?column=Email&[email protected]
GET /v1/tables/{tableId}/rows/{rowId}

A row carries its values twice: cells keyed by column id (stable across renames) and fields keyed by column name. Values are plain JSON — text, numbers, true / false, dates as YYYY-MM-DD, a choice's label, people as { id, name, email } (no email for an app), files as { id, file_name, download_url }, a formula's result (never its formula). column + equals finds rows the way an upsert matches its key: text ignores case and surrounding spaces, and "12" equals 12 in a number column.

Every row has a version. Send it back as If-Match: "<version>" when you change the row, and the change is refused with 409 row_changed if one of the cells you send changed in the meantime.

Write rows

POST   /v1/tables/{tableId}/rows                  { "cells": { "Name": "Paint", "Due": "2026-11-02" } }
PATCH  /v1/tables/{tableId}/rows/{rowId}          { "cells": { "Status": "Done" } }
PUT    /v1/tables/{tableId}/rows?key=Email        { "cells": { "Email": "[email protected]", "Plan": "Pro" } }
DELETE /v1/tables/{tableId}/rows/{rowId}

Name a column by id or by name. A cell you leave out is left alone; null clears it. Values can be the JSON shapes above or text the column reads — "1,250", "45%", "yes", "1h 30m", a choice's label, a person's email (people's tokens). Columns the Table fills in (formulas, created by, auto numbers) can't be written.

Upsert (PUT …?key=) finds the one row whose key column equals the value you send and sets the other cells — only those that differ — or adds the row when there is none. It runs with the Table locked, so two upserts of the same new key add one row, not two. If more than one row already has that key, the answer is 409 conflict. The answer says created: true or false (and X-Upsert: created / updated).

POST and PUT take an Idempotency-Key, so a retried request adds nothing twice. Writes go through the same path as an edit in the grid: formulas recalculate, open grids update live, change notifications go out, and the row's history says the change came through the API. They count against the same per-person editing budget as the grid (a 429 says when to try again).

Export

GET /v1/tables/{tableId}/export.csv
GET /v1/tables/{tableId}/export.xlsx

What the token sees, written as the app's exports write it. An app's export names people instead of giving their email addresses.

Events

sheet.row_created, sheet.row_updated (with changed_columns) and sheet.row_deleted go to event subscriptions, the bot gateway (intent tables) and Zapier, Make and n8n. An event carries the Table (id, name, kind, channel_id), the row's id and version and who changed it; the values (row.cells, row.fields) come along only when the org sends content in events — otherwise read the row back. A shared view's events go only to a subscription that names the view's channel, or a bot added to it, and carry only what the view shows. A batch that touches more than 200 rows (a large import) sends the first 200; read the rest back with the API.

Limits

Up to 200 rows a page. Rows, columns and cells are capped by your plan as in the app.