Moving a table from Excel into a README looks like a copy-and-paste task. It usually stops being simple as soon as the workbook contains more than one sheet, blank border rows, merged cells, dates, identifiers with leading zeros, or text containing a pipe character.
I wanted a workflow that produces reviewable Markdown without sending a workbook to a conversion server. This post explains the conversion rules that mattered most and a practical checklist for checking the result.
Why ordinary copy and paste breaks
A Markdown table needs a rectangular grid, a header row, and a separator row. A spreadsheet is much less strict. It can contain title blocks above the data, notes below it, formatting-only cells, hidden or helper sheets, merged ranges, formulas, and cells whose displayed value differs from the stored value.
The fragile approach is to copy every visible cell and join each row with |. It fails in several predictable ways:
- a literal
|inside a cell creates an extra Markdown column; - a line break splits one record across multiple Markdown lines;
- backslashes can change how later characters are interpreted;
- empty leading or trailing rows make the output noisy;
- numeric IDs such as
00124may be treated as numbers and lose information; - converting every worksheet produces irrelevant cover or notes tables;
- styling, charts, macros, and workbook interactions have no Markdown equivalent.
A safer browser-local pipeline
The conversion can run entirely in the browser. At a high level, the pipeline is:
- Read the selected
.xlsx,.xls, or.csvfile as anArrayBuffer. - Parse the workbook locally and build a matrix for each worksheet.
- Let the user choose the relevant sheet or sheets.
- Trim empty rows and columns from the outer edges, while preserving empty cells inside the table.
- Decide whether the first row is a header and choose column alignment.
- Escape Markdown-sensitive cell content.
- Render the table, preview it, and copy or download the result.
The escaping step is small but essential:
function escapeMarkdownCell(value: unknown) {
return String(value ?? '')
.replace(/\\/g, '\\\\')
.replace(/\|/g, '\\|')
.replace(/\r\n?|\n/g, '<br>')
.trim();
}
This keeps a pipe inside the cell instead of turning it into a column boundary, preserves backslashes, and represents an in-cell line break without breaking the table row.
Sheet selection matters
Workbooks often contain a cover sheet, instructions, a data dictionary, and one or more actual data sheets. Automatically dumping all of them into one document creates confusing output.
A better default is to recommend a visible, data-rich worksheet while still showing the full sheet list. When several sheets are selected, each table can be preceded by a level-two heading derived from the sheet name. The user remains in control, and the resulting Markdown has a predictable structure.
Preserve displayed values, not spreadsheet behavior
Markdown can represent text and table structure, but it cannot preserve the workbook as an interactive program. For documentation, the useful result is normally the value a reader sees in the cell. Formula logic, charts, macros, colors, borders, comments, and conditional formatting should not be presented as if they survived the conversion.
There are also cases where conservative text handling is important. Product codes, postal codes, and IDs with leading zeros should stay text. Dates should be checked after conversion because locale-specific display formats can be ambiguous. Merged cells need an explicit policy; expanding the anchor value across the merged range is often more understandable than silently leaving holes.
A five-minute verification checklist
Before pasting the generated table into documentation, I check:
- Row and column counts: Does the Markdown contain the same logical records as the selected range?
-
Headers: Is the first row really a header, or should generated names such as
Column 1be used? - Escaped characters: Test at least one pipe, backslash, and multiline cell.
- Identifiers and dates: Confirm leading zeros and displayed date values were not changed.
- Unsupported workbook features: Make sure no reader could mistake the Markdown for a full-fidelity Excel export.
For a small table, reading the Markdown is enough. For a large table, I also compare a few records from the start, middle, and end of the selected sheet.
The tool I use
I built Excel to Markdown around this browser-local workflow. The public converter accepts XLSX, XLS, and CSV files, lets you select worksheets and alignment, and provides copy and .md download output without requiring an account. Workbook content stays in the browser rather than being uploaded by the converter.
Disclosure: I built and operate Excel to Markdown. The implementation details above are shared because the edge cases apply to any spreadsheet-to-Markdown pipeline, whether you use this tool or write your own.
Top comments (0)