Loopfour
Blocks

Data Table block

Configure the Data Table block to query, insert, update and delete rows in a Loopfour table from a workflow, with the output of each one.

The Data Table block (type: "data_table") reads and writes rows in Loopfour tables, and creates and organises tables and table folders. The operation field picks what it does. For the plain-language guide, see Tables: keep working data in Loopfour.

When to use it

  • Keep a working list across runs, such as invoices already sent or payments already matched, and check it before acting.
  • Store rows from an API, CSV or report for review in Tables or a dashboard.
  • Create one table per period with ensureTable, so each run writes to the right place.

Operations

operationEditor labelWhat it doesFields it needs
insertInsertAdds one row.tableId, data
updateUpdateChanges the rows where matchKey equals matchValue.tableId, matchKey, matchValue, data
upsertUpsertUpdates the matching row, or inserts one if none matches.tableId, matchKey, matchValue, data
upsertManyUpsert manyUpserts a list of rows in one transaction, matched on matchKey.tableId, matchKey, rows
deleteDeleteDeletes the rows where matchKey equals matchValue.tableId, matchKey, matchValue
findFindReturns rows that match filter, newest first.tableId
getByIdGet by IDReturns one row by its id.tableId, rowId
createTableCreate tableGets or creates a table by name.name, columns
ensureTableEnsure tableGets or creates a table by name in a folder, and adds any missing columns.name, columns, folderId
createTableInFolderCreate table in folderGets or creates a table in a folder.name, columns, folderId
listTablesList tablesLists tables, optionally in one folder.None
listFoldersList foldersLists table folders.None
ensureFolderEnsure folderGets or creates a folder by name.folderName
assignTableToFolderAssign table to folderMoves a table to a folder, or to the root.tableId, folderId

Configuration

Field (config key)Editor labelTypeMeaning
operationOperationstringOne of the operations above. Required.
tableIdTablestringThe table's id. The editor lists your tables.
dataRow DataobjectThe row, keyed by column name, such as { "invoiceNumber": "INV-1042", "status": "sent" }. A whole template reference that resolves to an object also works.
rowsRowsarrayFor upsertMany: up to 2000 row objects, each with the matchKey field. Duplicate match values keep the last one.
matchKeyMatch KeystringThe column name to match on.
matchValueMatch ValueanyThe value to match, often a template reference.
updateFilterUpdate only when (JSON)objectFor update only. Each column must hold one of the listed values, checked in the same write: { "status": ["", "failed"] }. "" also matches an empty cell.
filterFilterobjectFor find: column name to value. Every pair must match exactly. Operator objects such as $gt are not supported yet and fail the step.
limitLimitnumberFor find: 1 to 1000, default 50.
offsetOffsetnumberFor find: rows to skip, default 0.
rowIdRow IDstringFor getById.
nameTable NamestringFor the create and ensure operations. Up to 255 characters. Accepts template references, such as AR aging {{input.period}}.
descriptionTable DescriptionstringOptional description for a new table.
columnsColumnsarrayFor the create and ensure operations: up to 100 { "name", "type" } entries. type is text (default), number, boolean, date, select, url, email or json. Names must be unique, ignoring case.
maxRowsMax RowsnumberRow limit for a new table: 1 to 100000, default 10000.
folderIdFolder IDstring or nullThe table folder. null (or the text null in the editor) means the root. For listTables, omit it to list every table.
folderNameFolder NamestringFor ensureFolder: 1 to 255 characters.

ensureTable adds columns that the table lacks. It does not change or remove a column, and it fails if a column with the same name has a different type, letter case or surrounding spaces.

Output

The output depends on the operation:

OperationFields
insert, getById, upsert (when it inserted)The row: id, tableId, data, fields, createdAt, updatedAt.
update, upsert (when it matched)updated: rows changed.
upsertManytotal, updated, inserted.
deletedeleted: rows removed.
findrows (each with id, data and fields) and pagination: limit, offset, returned, nextOffset, hasMore.
createTable, ensureTable, createTableInFoldertableId, name, folderId, created, columns; ensureTable also returns addedColumns.
listTablestables, count.
listFoldersfolders, count.
ensureFolderfolderId, folder, created.
assignTableToFoldertableId, folderId, previousFolderId, changed.

A row's data is keyed by internal column id (col_…). Read cells by column name from fields: {{steps.find_invoice.rows[0].fields.status}}. When a table has two columns with the same name, those names are left out of fields and listed in ambiguousFieldNames.

The editor's output list also shows result and success; the executor does not return those fields.

Example

This step records that an invoice reminder was sent, and only if it was not already sent or failed before.

{
  "id": "mark_reminded",
  "type": "data_table",
  "name": "Mark reminder sent",
  "config": {
    "operation": "update",
    "tableId": "8c1f0f5e-2a4b-4c55-9a64-0d2f3e6b7a10",
    "matchKey": "invoiceNumber",
    "matchValue": "{{variables.invoice.number}}",
    "updateFilter": { "reminderStatus": ["", "failed"] },
    "data": { "reminderStatus": "sent", "reminderRunId": "{{run.id}}" }
  }
}

If updated is 0, another run already marked the row.

Errors and limits

  • A config that misses a field its operation needs fails the step with Invalid data_table config, naming the field.
  • insert fails with Data table row limit reached when the table is at maxRows.
  • getById fails with Row not found when no row has that id.
  • data that does not resolve to an object fails the step.
  • update and delete act on every row that matches. Use a column with unique values as matchKey.
  • Most operations are also available as AI Agent tools, such as data_table.find; upsertMany and createTable are not. See AI Agent block.

On this page