CSV to ASCII Table Converter

A CSV to ASCII table converter turns a spreadsheet into a drawn text table for a terminal, a code comment, a plain-text email or a chat message. This one offers five border styles, right aligns your numeric columns so the digits line up, and measures widths in display columns, so a table with Japanese text or emoji in it still has a straight edge. Nothing is uploaded.

Need to filter to the interesting rows first? Open the app

Width is not string length

A drawn table works on exactly one condition: every line is the same number of terminal columns wide. Get one line wrong and the borders stop meeting, and the whole thing looks broken rather than slightly off.

That is trivial while the data is ASCII and stops being trivial the moment it is not. Three cases all break the naive approach:

A Japanese or Chinese character such as is one JavaScript character and takes two terminal columns. An emoji is two JavaScript characters, being a surrogate pair, and also takes two columns. A combining accent is one character and takes none, since it draws on top of the letter before it.

Measuring with .length gets all three wrong in different directions, which is why almost every generated table with CJK content has a ragged right edge. Widths here are measured in display columns, using the East Asian Wide and Fullwidth ranges, the emoji blocks and the combining-mark ranges. A table of Tokyo, 東京 and Reykjavík all lines up.

Five borders, and when each is right

Unicode box drawing is the default and looks best:

┌───────┬────────────────┬───────┐
│ sku   │ name           │ price │
├───────┼────────────────┼───────┤
│ 00412 │ Bracket 40mm   │  4.25 │
│ 04510 │ Spur gear      │ 31.50 │
└───────┴────────────────┴───────┘

It needs a UTF-8 terminal and a font that has the characters, which is nearly everywhere now and not quite everywhere. There is a rounded-corner variant of the same set.

Pure ASCII works on anything that has ever existed:

+-------+----------------+-------+
| sku   | name           | price |
+=======+================+=======+
| 00412 | Bracket 40mm   |  4.25 |
+-------+----------------+-------+

Use it for a legacy system, a code page that is not UTF-8, or anywhere the text will pass through something you do not control.

MySQL client style reproduces what mysql and psql print. If you are writing a bug report or documentation and want the output to look like it came from the client, this is the one.

Compact drops the borders entirely and separates columns with two spaces, which is right for a code comment where a box of line-drawing characters is noise.

Alignment, width limits and where it stops working

Numeric columns are right aligned. That is the whole reason a drawn table beats a list: the digits line up on the units place, a column can be scanned down, and an order-of-magnitude error is visible instantly. Text stays left.

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 column of SKUs that happen to be digits stays text too, because a leading zero means an identifier. You can force one alignment for the whole table when the automatic choice is wrong.

The header row is always left aligned, even over a numeric column. A right-aligned heading over a column of two-digit numbers floats in the middle of nothing, and a heading is a label rather than a value.

A long cell widens its column by default. Set a maximum column width and anything longer is cut with an ellipsis, with the count of truncated cells reported so the loss is a choice. You also get a warning when the whole table crosses 120 characters, because that is where it begins wrapping in a normal terminal and a wrapped drawn table is worse than no table.

Row separators between every row are available and off by default. They roughly triple the height, and they are the right call when cells are long enough that rows blur into each other.

A line break inside a cell becomes a space, with a count. A drawn table is built from fixed-width lines and a newline mid-cell would produce two lines of different widths with borders that no longer meet.

Questions

Why does my table look ragged in other tools when it has Japanese text in it?

Because they measure width with string length. A Japanese or Chinese character is one JavaScript character and occupies two terminal columns; an emoji is two JavaScript characters and also occupies two; a combining accent is one character and occupies none. All three are measured in display columns here, so the right edge stays straight whatever is in the cells.

Which border style should I pick?

Unicode box drawing looks best and needs a UTF-8 terminal with a font that has the characters. Pure ASCII with plus and hyphen works everywhere forever, including legacy code pages and systems that mangle non-ASCII. MySQL style is what the mysql and psql clients print, which is what a lot of people are actually trying to reproduce for a bug report. There is also a borderless compact style.

Are numbers right aligned?

Yes, when the column types as numeric, so the digits line up on the units place and the column can be read down. Text stays left. The header row is always left aligned even over a numeric column, because a right-aligned heading over a column of two-digit numbers ends up floating in the middle of nothing, and a heading is a label rather than a value.

What happens if a cell is very long?

By default the column widens to fit it, which can push the table past a terminal's width. Set a maximum column width and longer values are cut with an ellipsis, and the count of truncated cells is reported so the loss is a decision rather than a surprise. You also get a warning when the whole table exceeds 120 characters, since that is where it starts wrapping in a normal terminal.

Can I put a rule between every row?

Yes, with the row separators option. It roughly triples the height of the table, which is why it is off by default, but it is the right choice when cells are long enough that rows blur together. Without it you get one rule under the header and borders around the outside.

What happens to a line break inside a cell?

It becomes a space, and the count is reported. A drawn table is built from lines of fixed width; a raw newline inside a cell would break the row into two lines of different widths and the borders would stop lining up. Wrapping the cell across several lines is possible in principle and produces a table that is much harder to read as plain text.

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 result into a terminal, a code comment, a plain-text email or a chat message.

Convert your CSV to an ASCII table

No sign-up, no upload, no row cap. Five border styles, numbers aligned, and a straight edge whatever the alphabet.

Back to the converter