Publish / file · All operations

Write plain or templated text

A variant of Write another file format

Write values, messages or rows laid out by a template to a plain text file.

Status

In arcform

Runs as a SQL step

arcform carries it as a sql: step today.

The DuckDB step

Write rows laid out by a template to a text file

It reads the orders table the proofs share. Create it first:

SQL
CREATE TABLE orders AS SELECT * FROM (VALUES
  (1,  'Alice Ng',      'north', DATE '2026-01-03', 120.00, 'widget', 'a|b',   '{"channel":"web","items":[1,2]}'),
  (2,  'alice ng',      'north', DATE '2026-01-05',  80.50, 'gadget', 'b',     '{"channel":"shop","items":[3]}'),
  (3,  'Bob  Okafor',   'south', DATE '2026-01-05', 300.00, 'widget', 'a|c',   '{"channel":"web","items":[4,5,6]}'),
  (4,  'Carla Díaz',    'east',  DATE '2026-01-09',  NULL,  'gizmo',  NULL,    '{"channel":"web","items":[]}'),
  (5,  'Bob Okafor',    'south', DATE '2026-01-12',  45.25, 'gadget', 'c',     '{"channel":"phone","items":[7]}'),
  (6,  'Dev Patel',     'west',  DATE '2026-01-12', 510.00, 'widget', 'a',     '{"channel":"web","items":[8,9]}'),
  (7,  'Carla Diaz',    'east',  DATE '2026-01-20',  99.99, 'gizmo',  'b|c',   '{"channel":"shop","items":[10]}'),
  (8,  'Dev Patel',     'west',  DATE '2026-02-02', 510.00, 'widget', 'a',     '{"channel":"web","items":[8,9]}'),
  (9,  'Eve Larsen',    NULL,    DATE '2026-02-03',  15.00, 'gadget', NULL,    '{"channel":"web","items":[11]}'),
  (10, 'Alice Ng',      'north', DATE '2026-02-10', 220.00, 'gizmo',  'a|b|c', '{"channel":"phone","items":[12,13]}')
) t(order_id, customer, region, order_date, amount, product, tags, meta);

Then run the statement:

SQL
COPY (SELECT line FROM (
  SELECT 'ORDER REPORT' AS line, 0 AS pos
  UNION ALL SELECT format('{:>3} {:<12} {:>8} {}', order_id, customer, coalesce(format('{:.2f}', amount::DOUBLE), 'n/a'), CASE WHEN amount >= 300 THEN '*' ELSE '' END), order_id
            FROM orders WHERE order_id <= 4
  UNION ALL SELECT format('{} orders, total {:.2f}', count(*), sum(amount::DOUBLE)), 1000 FROM orders WHERE order_id <= 4
  ) ORDER BY pos) TO '<your_scratch_dir>/report.txt' (FORMAT csv, HEADER false, QUOTE '', ESCAPE '', DELIMITER '~');
SELECT CASE WHEN ((SELECT content FROM read_text('<your_scratch_dir>/report.txt')) = 'ORDER REPORT' || chr(10) || '  1 Alice Ng       120.00 ' || chr(10) || '  2 alice ng        80.50 ' || chr(10) || '  3 Bob  Okafor    300.00 *' || chr(10) || '  4 Carla Díaz        n/a ' || chr(10) || '4 orders, total 500.50' || chr(10)) THEN 'as expected' ELSE error('the report was not a title, four laid-out order lines with a star on the 300 order and n/a for the missing amount, and a total') END AS verdict;

Replace <your_scratch_dir> with a directory of your own that you can write to before running the statement.

  • The statement writes report.txt itself, in <your_scratch_dir>.
  • It needs nothing installed beyond DuckDB itself.
  • The statement checks its own result and raises an error when it is wrong: “the report was not a title, four laid-out order lines with a star on the 300 order and n/a for the missing amount, and a total”.
  • It passed on DuckDB v2.0.0 (Cyanoptera) d54cbbe3df.

What other tools call it

Meridian's classification; an independent blind rating agreed on 95.7% of 324 rows (variant, version 3).

Apache Hop (1)
  • Write to fileread 2026-09-27

    Write or append custom text to a file

Apache NiFi (1)
EasyMorph (1)
RapidMiner Studio (4)
Talend (1)
  • tFileOutputRawread 2026-09-27

    Write a single column of incoming data to a file

VisiData (3)
  • save-colread 2026-09-23

    Save current column to a file

  • save-col-keysread 2026-09-23

    Save key columns plus current column to a file

  • txt (saver)read 2026-09-23

    Save as plain text of the visible column(s)

Background

In Apache NiFi, FreeFormTextRecordSetWriter writes each record as free-form text that can reference the record's fields through the Expression Language.[1] A template processor is software designed to combine templates with data to produce resulting documents or programs.[2] In EasyMorph, Export as Plain Text writes the contents of a column into a text file as is, one value per line.[3]

When to use it

EasyMorph's Export as Plain Text is most frequently used to create text files in a format EasyMorph does not support natively.[3] OpenRefine's templating exporter lets a user roll their own exporter, which is useful for formats OpenRefine does not support natively.[4]

In Apache NiFi's FreeFormTextRecordSetWriter, each record is separated by a single newline character.[1] In OpenRefine's templating exporter, a forward slash or a closing curly brace must be escaped with a backslash, while other characters need no escaping.[4] Escape or strip line breaks and separators in values before they reach a template, unless the reader of the file expects them. (Meridian's view)

The method

Template engines typically include variables and functions, text replacement and file inclusion.[2] In OpenRefine's templating exporter, anything inside doubled curly braces is evaluated as an expression, and anything outside is generated as straight text.[4]

Apache Hop's Write to file action writes custom text from a field to a file, and can append to the previous file instead of overwriting it.[5] EasyMorph's Export as Plain Text can write the column name as the first line, and can leave out the byte order mark.[3]