<Tally> has Export CSV and Import CSV. Both are built on functions in tally-core you can call yourself.
Export
Export CSV writes every row that matches the view, not only the loaded page. It uses the visible columns in view order, column labels as headers and raw values. The file is named after the grid’slabel, through the exportFileName label.
Remote pages are fetched through the source with grid.fetchAll(max?). It stops at 100,000 rows by default. A source without pagination returns the rows it already loaded.
export.ts
toTsv takes the same options with a tab delimiter, no header and formatted values. Cells that start like a spreadsheet formula are escaped in both.
CSV export writes raw values, such as
4200 and 2026-11-02. Copy writes the clipboard with
toTsv, so it carries the formatted text, such as $4,200 and Nov 2, 2026.Import
Import CSV is shown when the source can mutate. It reads the file withimportRows(text, schema):
- Headers match columns by id, label or alias, then by the slug of the header.
- Headers that match no column are ignored. A file where no header matches throws
unknown_column. - Each cell is parsed with the column type. An empty cell becomes
null. - A cell the type cannot parse is left out of the row and reported as an issue with its row, column, value and message.
newRow.
import.ts
importRows takes a delimiter option. Without one, the delimiter is detected.
A schema from a file
importCsv from tally-core/import reads a file you have no schema for. It detects a type for every column, builds enum options from the distinct values and picks a key. It lives in its own entry point so the detection code loads only where it is used.
infer.ts
The result has
columns, each with the column, the detection, sample values and the count of invalid values, plus rows, issues, keyField and the delimiter used. A value the detected type cannot parse is kept as text and reported as an issue.
detectColumnType(values, registry, options) runs the detection for one list of values.