CSV to Templated Text

Write one block of text with {{column}} placeholders and get one copy per row. It is mail merge without the mail: four hundred SQL statements, four hundred Terraform blocks, four hundred personalised paragraphs, from a template you write once. Probably the most useful converter here and the one nobody knows exists. Nothing is uploaded.

Need to filter or sort the rows first? Open the app

What it is actually for

Every other converter here turns a table into a named format. This one turns a table into whatever you type, which sounds vague until you have needed it, and then it is the only thing that does the job.

The pattern is always the same: you have a spreadsheet, and you need N copies of something with the values swapped in. Some real cases:

A colleague sends forty new feature flags in a spreadsheet and your config format is a Terraform block. A migration needs an UPDATE per row because the values differ. You have 200 redirects as old and new paths and your server wants nginx rewrite lines. Somebody wants a personalised paragraph per customer for an email tool that takes plain text. A test fixture needs one function call per row.

None of those has a converter, and all of them take twenty minutes of careful spreadsheet formula work or a throwaway script you will not keep. Here it is a template and a click.

A worked example

Three feature flags:

key,enabled,rollout,owner
fast_checkout,true,25,payments
new_invoices,false,0,billing
dark_mode,true,100,platform

With this template:

resource "flag" "{{key}}" {
  enabled = {{enabled}}
  rollout = {{rollout}}
  owner   = "{{owner}}"
}

and a blank line as the separator, you get:

resource "flag" "fast_checkout" {
  enabled = true
  rollout = 25
  owner   = "payments"
}

resource "flag" "new_invoices" {
  enabled = false
  rollout = 0
  owner   = "billing"
}

resource "flag" "dark_mode" {
  enabled = true
  rollout = 100
  owner   = "platform"
}

Note where the quotes are: in the template, not in the tool. You decide that key and owner are quoted strings and enabled and rollout are bare, because you know what the target format wants and the converter does not.

Add a header and a footer and the result is a complete file rather than a fragment. A BEGIN; and COMMIT; around generated SQL, an opening and closing bracket around a hand-built JSON array, or the boilerplate at the top of a generated source file.

The typo you would otherwise never find

Here is the design decision worth explaining. What should happen when a template says {{onwer}} and there is no such column?

The obvious answer is to substitute nothing. It is what most template engines do and it is the wrong default here, because the output is four hundred blocks and a missing value looks exactly like an empty cell. You find out when the config deploys with no owner set.

So the default is to leave the placeholder in the output, untouched:

  owner   = "{{onwer}}"

which is impossible to miss and immediately says what is wrong. The warning names it too, and lists the columns that do exist:

This placeholder is not a column in this file: {{onwer}}. They were left in
the output as they are, so the typo is visible rather than hidden. Columns
available: key, enabled, rollout, owner.

The two other behaviours are there when you want them: blank the unknown placeholders, or refuse to convert at all until the template is right, which is the one to use when this is a step in something automated.

Placeholder names are matched case-insensitively and spaces inside the braces are ignored, so {{ Owner }} finds the owner column. Leave the template box blank and one is generated with every column on its own labelled line, which is the quickest way to see the exact names you can use.

Two built-ins are always available: {{_index}} for the row number starting at one, and {{_count}} for the total. A column of your own with the same name wins.

Nothing is escaped for you. The tool has no idea whether it is producing SQL, YAML, HTML or prose, so values go in exactly as they appear in the CSV. If you are generating SQL from data you do not control, use CSV to SQL, which quotes properly for a database.

Questions

How do I refer to a column?

By its heading in double curly braces: {{name}}, {{price}}, {{region code}}. Matching is case-insensitive, so {{NAME}} and {{name}} both work, and spaces inside the braces are ignored. Leave the template blank and one is built for you with every column on its own labelled line, which is a useful starting point to edit.

What happens if I misspell a column name?

By default the placeholder is left in the output exactly as written, so you can see the typo in the result rather than hunting for a blank. The warning also names it and lists the columns that do exist. There are two other behaviours if you prefer: replace unknown placeholders with nothing, or refuse to convert at all until the template is right.

Are there any built-in placeholders?

Two. {{_index}} is the row number starting at one, and {{_count}} is the total number of rows. They are useful for numbered output, for a progress comment in generated code, or for writing something like item 3 of 40 into each block. A column of your own with the same name takes precedence.

What separates the blocks?

A single newline by default, which is right for one-line output such as SQL statements. Set it to anything else for multi-line blocks: a blank line, a row of dashes, a comma for building a JSON array by hand. Backslash-n and backslash-t in the separator are read as a real newline and tab so you can type them.

Can I add something before and after the whole thing?

Yes, a header and a footer, written once each. That is what turns a list of blocks into a complete file: an opening bracket and a closing one, a BEGIN and a COMMIT around generated SQL, a terraform block wrapper, or the boilerplate at the top of a generated source file.

Does it escape anything for me?

No, and that is deliberate. The tool has no idea whether the output is SQL, YAML, HTML or prose, so it substitutes values exactly as they appear in the CSV. If you are generating SQL from untrusted data, escape it in the app first or use the CSV to SQL converter, which quotes properly for a database.

Is anything uploaded?

No. Everything runs in your browser tab, with nothing sent to a server, nothing kept between visits and no row cap. The template you type stays in the page too.

Generate text from your CSV

No sign-up, no upload, no row cap. One template, one block per row, and typos you can actually see.

Back to the converter