Markdown tables: from Excel or CSV to a clean PDF
By Fazt ·
A table is often the reason a document exists: a price list for a client, a training schedule, the data appendix of a report. The numbers usually live in a spreadsheet, and the result has to be a PDF. Markdown sits comfortably in between: its tables are plain text you can edit and keep under version control, and they print as clean, bordered tables. This guide covers the syntax, the trip from Excel or CSV, how tables behave on paper and what to do when one refuses to render.
Table syntax in one minute
The Markdown editor follows the GitHub Flavored Markdown rules for tables: rows of cells separated by pipes.
| Plan | Users | Price per month |
| :------- | :---: | --------------: |
| Starter | 1 | $9.00 |
| Team | 10 | $49.00 |
| Business | 50 | $199.00 |
- The first row is the header. A table has exactly one, printed in bold on a shaded background.
- The second row is the delimiter row: at least one hyphen per column, and exactly as many columns as the header.
- Colons set the alignment:
:---left (the default),:---:centered,---:right. Right-align prices and quantities so the digits line up. - Outer pipes are optional but make mistakes easier to spot. Columns need not line up in the source; padding is only for your eyes.
- Leave a blank line before and after the table.
The complete rules are in the GitHub Flavored Markdown spec.
What fits inside a cell
Cells accept inline Markdown: bold, italics, strikethrough, `code`, links and footnote references. Three things need care:
- A literal pipe must be escaped as
\|, or it starts a new cell. That includes pipes inside backticks. - Line breaks: each row is a single line of source, so pressing Enter ends the row. Use
<br>to break a line inside a cell. - Block elements (real lists, several paragraphs, code blocks) cannot go in a cell. Fake a short list with
<br>, or move a long remark to a footnote, printed at the end of the document.
| Step | Command | Notes |
| ---- | ------- | ----- |
| 1 | `npm install` | Downloads the dependencies |
| 2 | `sort log.txt \| uniq` | Removes repeated lines[^1] |
| 3 | `npm run build` | Takes about a minute<br>Output goes to **dist/** |
[^1]: The backslash keeps the pipe inside the cell.
From Excel to a Markdown table
Open the Excel to Markdown converter and drop your workbook (.xlsx, .xlsm, .xlsb or the older .xls). It is read inside your browser, so confidential figures never leave your computer. The Markdown appears in a text box where you can edit it before you Copy it, Download .md or click Open in editor → PDF.
What the conversion does with each part of a spreadsheet:
- Sheets: each sheet becomes its own table, preceded by a
## Sheet nameheading when there is more than one. Empty and hidden sheets are skipped, as are hidden rows and columns, so hiding is a quick way to leave out helper columns. - Header row: the first row becomes the header only if it has a value in every column. With a title above the table, a merged title or a blank column name, you get an empty header row and your real headers end up in the body. Put the column names in row 1 and give every column a name.
- Empty rows between your data are kept as blank rows (
| | | |). Delete them in the spreadsheet or in the text box. - Formulas come out as their last calculated value. A file generated by another program may lack those values and show empty cells; open and save it in Excel once.
- Number formats are applied: currency symbols, percentages, thousands separators and decimal places appear as formatted (
$1,234.50,15%), always with a comma for thousands and a period for decimals, whatever your regional settings. - Dates and times are written in ISO format, such as
2026-03-01or2026-11-20 14:30:00, whatever display format the cell uses. - Merged cells keep their value in the top-left cell; the cells they covered stay empty.
- Lost on the way: bold, colors, borders and charts. Hyperlinks keep only their visible text, a line break inside a cell becomes a space, and characters like
*are escaped, so text that looks like Markdown prints literally.
Every column comes out left-aligned. Before printing, change the delimiter row to ---: under numeric columns.
From CSV
CSV is what most tools export: Google Sheets, Numbers, accounting software, databases and Notion databases. Drop the file on the CSV to Markdown converter:
- The separator is detected automatically: commas, semicolons (common where the comma is the decimal separator) and tabs all work.
- Quoted values that contain the separator stay in one cell, and pipes are escaped as
\|. - CSV is plain text, so values are kept exactly as written: dates are not reformatted and leading zeros survive (
0012). Blank lines are skipped. - The header rule is the same as for Excel: the first line must name every column.
- Files ending in
.tsvor.txtare not recognized. Rename them to.csvfirst.
Want dates as shown on screen rather than in ISO format? Save the sheet as CSV from your spreadsheet app, which usually writes values as displayed, and convert that.
Getting the table into your document
Open in editor → PDF replaces whatever is in the editor, which suits a table-only document. To add the table to an existing one, click Copy instead and paste it in, with a blank line above and below.
How tables print
In the PDF, tables span the full width of the text, with thin borders, a shaded header row and type slightly smaller than the body.
- Long tables continue across pages, and a row is never split between two pages. With Download PDF, the header row is repeated at the top of each page (in Chrome, Edge and Firefox). Quick PDF saves the pages as images and does not repeat it.
- Header shading: if it prints white, turn on Background graphics in the print dialog.
- Wide tables: columns shrink and text wraps, but a long URL, code or word without spaces cannot wrap; it pushes the table past the right margin and the PDF cuts it off. If a table sticks out in the preview, it will on paper too.
- Orientation: there is no landscape option. Pages are A4 or Letter, in portrait.
To make a wide table fit, try these in order: lower the Font size in the Style panel (9 to 14 pt; it scales the whole document), set Margins to Narrow (12 mm instead of 20), replace long URLs with short link text such as [report](https://…), abbreviate column names and explain them under the table, and, as a last resort, split the table in two or swap rows and columns. To start a big table on a fresh page, put <!-- pagebreak --> on its own line before it.
Four recipes
Comparison
Options in columns, criteria in rows: three or four options fit a portrait page.
| | Supplier A | Supplier B | Supplier C |
| --- | :---: | :---: | :---: |
| Price per unit | $4.20 | $3.95 | $4.10 |
| Delivery | 3 days | 10 days | 5 days |
| Free returns | No | No | Yes |
| **Verdict** | Fastest | Cheapest | **Best value** |
Price list
Right-align the prices, bold the total and move conditions to a footnote.
| Service | Unit | Price |
| --- | --- | ---: |
| Website audit | per site | $450.00 |
| Copywriting | per page | $120.00 |
| Maintenance[^1] | per month | $90.00 |
| **Total, first month** | | **$660.00** |
[^1]: Minimum term of three months.
Schedule
Times down the side, days across the top; <br> keeps a two-line entry in one cell.
| Time | Monday | Tuesday |
| --- | --- | --- |
| 09:00 | Kick-off | Workshop: data model |
| 11:00 | Interviews<br>Rooms 2 and 3 | Workshop, continued |
| 14:00 | Site visit | Wrap-up and next steps |
Data appendix
Keep a summary in the body and the full data at the end, after a page break, where the repeated header row pays off.
<!-- pagebreak -->
## Appendix A. Monthly sales by region
| Month | North | South | Total |
| --- | ---: | ---: | ---: |
| January | 12,400 | 9,800 | 22,200 |
| February | 11,950 | 10,300 | 22,250 |
When a table is the wrong tool
- Cells that need paragraphs or lists: give each item a
###heading with a list underneath. - A single column of values is simply a list.
- More than seven or eight columns, or thousands of rows: summarize, and share the spreadsheet separately.
- Page layout, such as text blocks side by side: tables are for data.
Troubleshooting
- The table appears as plain text with pipes. Count the columns: the delimiter row needs exactly as many cells as the header, each with at least one hyphen. Also check that the table is not indented four spaces (that makes it a code block) and not glued to a list item without a blank line, which swallows it.
- Data is missing from a row. Cells beyond the header’s column count are dropped without warning; shorter rows are padded with empty cells. An unescaped
|in the text is the usual culprit. - The table stops halfway and the rest prints as lines of pipes: there is a blank line inside the table.
- A sentence became a table row. Text on the line right after a table is read as another row. Add a blank line.
- Part of a cell looks like a formula. The editor renders LaTeX between dollar signs, so a cell like
between 5 $ and 10 $turns into math. Escape the first sign:5 \$. - The converted table has an empty header. Row 1 of the sheet was a title or had a blank cell. Fix the sheet and convert again, or delete the empty first line and the title rows, then move the real header above the
---line. - Codes changed slightly. Smart punctuation turns
--into an en dash (–) and straight quotes into curly ones. Wrap product codes and commands in backticks to keep them exactly as typed.
The Markdown guide covers everything else the editor supports.
More guides
- Markdown guide: syntax cheat sheet for great PDFs
- How to convert Markdown to PDF: 4 free ways
- Export Obsidian and Notion notes to a styled PDF
- Write your resume in Markdown and export it to PDF
- Turn a Word document into a GitHub README
- Convert PDF, Word and slides to Markdown for AI and RAG
- Mermaid diagrams in Markdown: export them to PDF
- Math in Markdown: write LaTeX equations and export to PDF
- Export a GitHub README or Markdown docs to PDF
- Write a report or proposal in Markdown and export a PDF
- Markdown vs Word: which to use and how to switch