CSV to Org Mode Table Converter

A CSV to org-mode converter turns a spreadsheet into a table for an Emacs .org file. This one writes the rule the way org writes it, so Emacs does not silently rewrite your file the first time you open it, escapes pipes with the macro org actually has, sets alignment with cookies rather than a Markdown separator row, and can name the table so a source block can use it. Nothing is uploaded.

Need to trim or reorder columns first? Open the app

Three ways an org table is not a Markdown table

They look identical. Pipes at the edges, pipes between cells, a rule under the header. The differences are all in the details, and all three bite.

The rule uses plus signs. Org writes |---+---+---|, with a plus at each column boundary, not |---|---|---|. Org will accept the sloppy version and quietly rewrite it the next time the table is realigned, which happens as soon as anybody edits a cell. The practical effect: you commit a table, a colleague opens it in Emacs, and their next commit reformats the whole thing. Writing the correct rule means the file is already in the shape Emacs would leave it.

A pipe is escaped as a macro. Org has no \|. The Markdown reflex does nothing at all, and the raw pipe still starts a new column. The correct form is \vert{}, which renders as a pipe in the HTML, LaTeX and plain-text export backends alike.

Alignment is not in the rule. Markdown puts colons in the separator row. Org uses a row of cookies above the header, | <r> | <l> |, which Emacs keeps in the buffer and leaves out of the export.

A worked example

Four rows, one containing a pipe:

task,owner,hours,note
write spec,ada,3.5,draft
review,grace,1,"blocked | waiting"
deploy,alan,0.5,scheduled

Named tasks, the output is:

#+CAPTION: Sprint tasks
#+NAME: tasks
| <l>        | <l>   | <r>   | <l>                       |
| task       | owner | hours | note                      |
|------------+-------+-------+---------------------------|
| write spec | ada   |   3.5 | draft                     |
| review     | grace |     1 | blocked \vert{} waiting   |
| deploy     | alan  |   0.5 | scheduled                 |

The rule has plus signs. The hours column carries a right cookie and its values are right aligned in the padding. The pipe in the note is the \vert{} macro, so the row still has four cells.

Because it has a #+NAME, a source block below can take it as input:

#+BEGIN_SRC python :var rows=tasks :results output
  print(sum(float(r[2]) for r in rows))
#+END_SRC

That is the reason to keep the data in org rather than in a CSV next to it, and it only works if the table has a name.

Padding, cookies and formulas

Cells are padded to a common width by default, because that is what Emacs does the moment the table is realigned. Producing an unpadded table means the first person to open the file gets a diff they did not make. Padding it here means the file arrives in its settled state.

The argument the other way is version control. A padded table shifts a whole column's spacing when one value gets longer, so a one-cell change can touch every row in the diff. If your table lives in a repository and gets reviewed, turning padding off gives you minimal diffs at the cost of a table Emacs will reformat. Both are defensible, which is why it is a switch.

Widths are measured in display columns rather than string length, so a table with Japanese text or emoji in it still lines up. That matters more in org than in most formats, because you are usually looking at the raw table in a buffer rather than at rendered output.

Alignment cookies are added only for columns that need one, so a table of nothing but text gets no cookie row at all rather than a row of empty markers. Types are decided once per column, so a price column mixing 4.25 and 6.80 stays text and left aligned rather than half one way.

A #+TBLFM line is written exactly as you type it, and nothing here evaluates it. Org formulas are computed by Emacs when you press C-c C-c on the table. The warning says so, because an unevaluated formula line looks exactly like one that has failed.

Questions

Why does the rule use plus signs rather than pipes?

Because that is what org-mode writes at the column boundaries. Org accepts a sloppy rule and rewrites it on the next realign, which sounds harmless and is not: the file changes the moment anybody opens it in Emacs, so a commit that touched one cell shows up in the diff as the whole table. Writing the correct rule means the file is already in the shape Emacs would leave it.

How do I escape a pipe in an org table?

With the vert macro, written as a backslash followed by vert and empty braces. Org has no backslash-pipe escape, so the Markdown reflex does nothing and the raw pipe still starts a new column. The vert form renders as a pipe character in every export backend, HTML, LaTeX and plain text alike, and it is applied for you here.

What is the row of angle brackets above the header?

Alignment cookies. Org has no alignment column in the rule the way Markdown does; instead a row of markers such as <r> and <l> above the header sets each column's alignment. Numeric columns get a right cookie automatically, and Emacs keeps the row in place and does not export it as data. You can turn them off if you would rather not have the extra row.

What does the NAME line do?

It makes the table addressable. A named table can be passed to a source block as input, referenced from a noweb template, or targeted by a call line, which is most of the reason to keep tabular data in org at all rather than in a CSV beside it. The name is written with spaces turned into hyphens, since org names cannot contain spaces.

Are the cells padded?

By default yes, to the width Emacs would use, so the table looks the same before and after its first realign and the file does not change under you. Turning padding off gives a minimal-diff table where a one-cell edit touches one cell rather than shifting a whole column's spacing, which some people prefer in a version-controlled file.

Can I add a formula?

You can add a TBLFM line and it is written exactly as you type it. Nothing here evaluates it; org formulas are computed by Emacs when you press the recalculate binding on the table. The warning says so, because a formula line that has not been evaluated yet looks identical to one that has failed.

Is anything uploaded?

No. The conversion runs in your browser tab, with nothing sent to a server, nothing kept between visits and no row cap. Copy the table straight into your .org file.

Convert your CSV to an org table

No sign-up, no upload, no row cap. The rule Emacs would write, cookies for alignment, and pipes that survive.

Back to the converter