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:
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:
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.txtitself, 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-27Write or append custom text to a file
Apache NiFi (1)
FreeFormTextRecordSetWriterread 2026-09-27Write each record as free-form text built with Expression Language
EasyMorph (1)
Export as plain textread 2026-09-27Write one column to a text file, one value per line, unformatted
RapidMiner Studio (4)
Write Documentread 2026-09-27Write a document to a text file
Write Messageread 2026-09-27Write a given text message to a file
Write Special Formatread 2026-09-27Write rows to a text file using a user-defined line template
Write as Textread 2026-09-27Write the text form of any result objects to a file
Talend (1)
tFileOutputRawread 2026-09-27Write a single column of incoming data to a file
VisiData (3)
save-colread 2026-09-23Save current column to a file
save-col-keysread 2026-09-23Save key columns plus current column to a file
txt (saver)read 2026-09-23Save 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]
Sources
- [1]FreeFormTextRecordSetWriter - Apache NiFidocumentation
- [2]Template processor - Wikipediasecondary source
- [3]EXPORT AS PLAIN TEXT [EasyMorph Help]documentation
- [4]Exporting your work | OpenRefinedocumentation
- [5]Write to File | Apache Hopdocumentation