LLMs Can Not Read Spreadsheets
If you’re building applications that feed data to language models, you’ve hit this wall. You have tabular data — financial reports, product catalogs, extracted invoice line items — and you need to include it in a prompt. XLSX is a binary format. You can not put it in a prompt. CSV technically works, but it’s hard for both humans and models to parse visually, especially with quoted fields and escaped commas.
Consider this CSV:
Company,Region,"Revenue (USD)",Growth
"Acme Corp",North America,"1,250,000",0.15
"Globex, Ltd",Europe,"890,000",0.08
The comma in “Globex, Ltd” requires quoting. The comma in “1,250,000” requires quoting. A model can usually parse this, but it’s fragile. Add a few more columns and the visual structure disappears. Debugging a malformed prompt becomes guesswork.
Markdown tables solve this. They’re plain text, visually structured, and every major LLM handles them well.
Markdown as a First-Class Output Format
The Sheet Generation API supports Markdown as an output format alongside XLSX and CSV. The same JSON payload that generates a formatted Excel file also generates a clean Markdown table. Change "format": "xlsx" to "format": "markdown" and you get structured text instead of a binary file.
curl -X POST https://api.iterationlayer.com/sheet-generation/v1/generate \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"format": "markdown",
"sheets": [
{
"name": "Q1 Revenue",
"columns": [
{
"name": "Company"
},
{
"name": "Region"
},
{
"name": "Revenue"
},
{
"name": "Growth"
}
],
"rows": [
[
{
"value": "Acme Corp"
},
{
"value": "North America"
},
{
"value": 1250000,
"format": "currency",
"currency_code": "USD"
},
{
"value": 0.15,
"format": "percentage"
}
],
[
{
"value": "Globex Ltd"
},
{
"value": "Europe"
},
{
"value": 890000,
"format": "currency",
"currency_code": "EUR"
},
{
"value": 0.08,
"format": "percentage"
}
]
]
}
]
}'{
"success": true,
"data": {
"buffer": "## Q1 Revenue\n\n| Company | Region | Revenue | Growth |\n| --- | --- | --- | --- |\n| Acme Corp | North America | $1,250,000.00 | 15.00% |\n| Globex Ltd | Europe | €890,000.00 | 8.00% |",
"mime_type": "text/markdown"
}
}import { IterationLayer } from "iterationlayer";
const client = new IterationLayer({
apiKey: "YOUR_API_KEY",
});
const result = await client.generateSheet({
format: "markdown",
sheets: [
{
name: "Q1 Revenue",
columns: [
{
name: "Company",
},
{
name: "Region",
},
{
name: "Revenue",
},
{
name: "Growth",
},
],
rows: [
[
{
value: "Acme Corp",
},
{
value: "North America",
},
{
value: 1_250_000,
format: "currency",
currency_code: "USD",
},
{
value: 0.15,
format: "percentage",
},
],
[
{
value: "Globex Ltd",
},
{
value: "Europe",
},
{
value: 890_000,
format: "currency",
currency_code: "EUR",
},
{
value: 0.08,
format: "percentage",
},
],
],
},
],
});{
"success": true,
"data": {
"buffer": "## Q1 Revenue\n\n| Company | Region | Revenue | Growth |\n| --- | --- | --- | --- |\n| Acme Corp | North America | $1,250,000.00 | 15.00% |\n| Globex Ltd | Europe | €890,000.00 | 8.00% |",
"mime_type": "text/markdown"
}
}from iterationlayer import IterationLayer
client = IterationLayer(api_key="YOUR_API_KEY")
result = client.generate_sheet(
format="markdown",
sheets=[
{
"name": "Q1 Revenue",
"columns": [
{
"name": "Company",
},
{
"name": "Region",
},
{
"name": "Revenue",
},
{
"name": "Growth",
},
],
"rows": [
[
{
"value": "Acme Corp",
},
{
"value": "North America",
},
{
"value": 1250000,
"format": "currency",
"currency_code": "USD",
},
{
"value": 0.15,
"format": "percentage",
},
],
[
{
"value": "Globex Ltd",
},
{
"value": "Europe",
},
{
"value": 890000,
"format": "currency",
"currency_code": "EUR",
},
{
"value": 0.08,
"format": "percentage",
},
],
],
},
],
){
"success": true,
"data": {
"buffer": "## Q1 Revenue\n\n| Company | Region | Revenue | Growth |\n| --- | --- | --- | --- |\n| Acme Corp | North America | $1,250,000.00 | 15.00% |\n| Globex Ltd | Europe | €890,000.00 | 8.00% |",
"mime_type": "text/markdown"
}
}package main
import il "github.com/iterationlayer/sdk-go"
func main() {
client := il.NewClient("YOUR_API_KEY")
result, err := client.GenerateSheet(il.GenerateSheetRequest{
Format: "markdown",
Sheets: []il.Sheet{
{
Name: "Q1 Revenue",
Columns: []il.SheetColumn{
{
Name: "Company",
},
{
Name: "Region",
},
{
Name: "Revenue",
},
{
Name: "Growth",
},
},
Rows: []il.SheetRow{
{
{
Value: "Acme Corp",
},
{
Value: "North America",
},
{
Value: 1250000,
Format: "currency",
CurrencyCode: "USD",
},
{
Value: 0.15,
Format: "percentage",
},
},
{
{
Value: "Globex Ltd",
},
{
Value: "Europe",
},
{
Value: 890000,
Format: "currency",
CurrencyCode: "EUR",
},
{
Value: 0.08,
Format: "percentage",
},
},
},
},
},
})
if err != nil {
panic(err)
}
_ = result
}{
"success": true,
"data": {
"buffer": "## Q1 Revenue\n\n| Company | Region | Revenue | Growth |\n| --- | --- | --- | --- |\n| Acme Corp | North America | $1,250,000.00 | 15.00% |\n| Globex Ltd | Europe | €890,000.00 | 8.00% |",
"mime_type": "text/markdown"
}
}The response body contains the Markdown table as a string:
## Q1 Revenue
| Company | Region | Revenue | Growth |
| --- | --- | --- | --- |
| Acme Corp | North America | $1,250,000.00 | 15.00% |
| Globex Ltd | Europe | €890,000.00 | 8.00% |Readable by a human. Readable by an LLM. No quoting ambiguity, no binary encoding, no delimiter confusion.
Formatting Carries Over
The Markdown output applies the same formatting rules as XLSX and CSV. Currency values get their symbols. Percentages get the percent sign. Number styles control grouping separators.
{
"value": 1250000,
"format": "currency",
"currency_code": "JPY"
}
Renders as ¥1,250,000.00 in the Markdown table. The format metadata in your JSON payload isn’t just for Excel — it defines how the value should be displayed in any format.
Formulas work too. In XLSX, a formula like =SUM(B2:B4) is written as a native formula for Excel to evaluate. In Markdown, the API evaluates it server-side and writes the computed result into the table cell. Same payload, same values, different representation.
curl -X POST https://api.iterationlayer.com/sheet-generation/v1/generate \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"format": "markdown",
"sheets": [
{
"name": "Budget",
"columns": [
{
"name": "Category"
},
{
"name": "Amount"
}
],
"rows": [
[
{
"value": "Engineering"
},
{
"value": 45000,
"format": "currency",
"currency_code": "USD"
}
],
[
{
"value": "Design"
},
{
"value": 22000,
"format": "currency",
"currency_code": "USD"
}
],
[
{
"value": "Marketing"
},
{
"value": 18000,
"format": "currency",
"currency_code": "USD"
}
],
[
{
"value": "Total"
},
{
"value": "=SUM(B2:B4)",
"format": "currency",
"currency_code": "USD"
}
]
]
}
]
}'{
"success": true,
"data": {
"buffer": "## Budget\n\n| Category | Amount |\n| --- | --- |\n| Engineering | $45,000.00 |\n| Design | $22,000.00 |\n| Marketing | $18,000.00 |\n| Total | $85,000.00 |",
"mime_type": "text/markdown"
}
}import { IterationLayer } from "iterationlayer";
const client = new IterationLayer({
apiKey: "YOUR_API_KEY",
});
const result = await client.generateSheet({
format: "markdown",
sheets: [
{
name: "Budget",
columns: [
{
name: "Category",
},
{
name: "Amount",
},
],
rows: [
[
{
value: "Engineering",
},
{
value: 45_000,
format: "currency",
currency_code: "USD",
},
],
[
{
value: "Design",
},
{
value: 22_000,
format: "currency",
currency_code: "USD",
},
],
[
{
value: "Marketing",
},
{
value: 18_000,
format: "currency",
currency_code: "USD",
},
],
[
{
value: "Total",
},
{
value: "=SUM(B2:B4)",
format: "currency",
currency_code: "USD",
},
],
],
},
],
});{
"success": true,
"data": {
"buffer": "## Budget\n\n| Category | Amount |\n| --- | --- |\n| Engineering | $45,000.00 |\n| Design | $22,000.00 |\n| Marketing | $18,000.00 |\n| Total | $85,000.00 |",
"mime_type": "text/markdown"
}
}from iterationlayer import IterationLayer
client = IterationLayer(api_key="YOUR_API_KEY")
result = client.generate_sheet(
format="markdown",
sheets=[
{
"name": "Budget",
"columns": [
{
"name": "Category",
},
{
"name": "Amount",
},
],
"rows": [
[
{
"value": "Engineering",
},
{
"value": 45000,
"format": "currency",
"currency_code": "USD",
},
],
[
{
"value": "Design",
},
{
"value": 22000,
"format": "currency",
"currency_code": "USD",
},
],
[
{
"value": "Marketing",
},
{
"value": 18000,
"format": "currency",
"currency_code": "USD",
},
],
[
{
"value": "Total",
},
{
"value": "=SUM(B2:B4)",
"format": "currency",
"currency_code": "USD",
},
],
],
},
],
){
"success": true,
"data": {
"buffer": "## Budget\n\n| Category | Amount |\n| --- | --- |\n| Engineering | $45,000.00 |\n| Design | $22,000.00 |\n| Marketing | $18,000.00 |\n| Total | $85,000.00 |",
"mime_type": "text/markdown"
}
}package main
import il "github.com/iterationlayer/sdk-go"
func main() {
client := il.NewClient("YOUR_API_KEY")
result, err := client.GenerateSheet(il.GenerateSheetRequest{
Format: "markdown",
Sheets: []il.Sheet{
{
Name: "Budget",
Columns: []il.SheetColumn{
{
Name: "Category",
},
{
Name: "Amount",
},
},
Rows: []il.SheetRow{
{
{
Value: "Engineering",
},
{
Value: 45000,
Format: "currency",
CurrencyCode: "USD",
},
},
{
{
Value: "Design",
},
{
Value: 22000,
Format: "currency",
CurrencyCode: "USD",
},
},
{
{
Value: "Marketing",
},
{
Value: 18000,
Format: "currency",
CurrencyCode: "USD",
},
},
{
{
Value: "Total",
},
{
Value: "=SUM(B2:B4)",
Format: "currency",
CurrencyCode: "USD",
},
},
},
},
},
})
if err != nil {
panic(err)
}
_ = result
}{
"success": true,
"data": {
"buffer": "## Budget\n\n| Category | Amount |\n| --- | --- |\n| Engineering | $45,000.00 |\n| Design | $22,000.00 |\n| Marketing | $18,000.00 |\n| Total | $85,000.00 |",
"mime_type": "text/markdown"
}
}The output:
## Budget
| Category | Amount |
| --- | --- |
| Engineering | $45,000.00 |
| Design | $22,000.00 |
| Marketing | $18,000.00 |
| Total | $85,000.00 |
The Total row contains $85,000.00 — the evaluated result, not the formula string.
Multi-Sheet Support
XLSX supports multiple sheets natively — they show up as tabs. CSV doesn’t support multiple sheets at all (the API enforces a single-sheet limit for CSV). Markdown handles it with headings: each sheet becomes a ## heading followed by its table.
curl -X POST https://api.iterationlayer.com/sheet-generation/v1/generate \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"format": "markdown",
"sheets": [
{
"name": "Revenue by Region",
"columns": [
{
"name": "Region"
},
{
"name": "Q1"
},
{
"name": "Q2"
}
],
"rows": [
[
{
"value": "North America"
},
{
"value": 480000,
"format": "currency",
"currency_code": "USD"
},
{
"value": 520000,
"format": "currency",
"currency_code": "USD"
}
],
[
{
"value": "Europe"
},
{
"value": 310000,
"format": "currency",
"currency_code": "EUR"
},
{
"value": 345000,
"format": "currency",
"currency_code": "EUR"
}
]
]
},
{
"name": "Revenue by Product",
"columns": [
{
"name": "Product"
},
{
"name": "Q1"
},
{
"name": "Q2"
}
],
"rows": [
[
{
"value": "Platform"
},
{
"value": 590000,
"format": "currency",
"currency_code": "USD"
},
{
"value": 640000,
"format": "currency",
"currency_code": "USD"
}
],
[
{
"value": "Services"
},
{
"value": 200000,
"format": "currency",
"currency_code": "USD"
},
{
"value": 225000,
"format": "currency",
"currency_code": "USD"
}
]
]
}
]
}'{
"success": true,
"data": {
"buffer": "## Revenue by Region\n\n| Region | Q1 | Q2 |\n| --- | --- | --- |\n| North America | $480,000.00 | $520,000.00 |\n| Europe | €310,000.00 | €345,000.00 |\n\n## Revenue by Product\n\n| Product | Q1 | Q2 |\n| --- | --- | --- |\n| Platform | $590,000.00 | $640,000.00 |\n| Services | $200,000.00 | $225,000.00 |",
"mime_type": "text/markdown"
}
}import { IterationLayer } from "iterationlayer";
const client = new IterationLayer({
apiKey: "YOUR_API_KEY",
});
const result = await client.generateSheet({
format: "markdown",
sheets: [
{
name: "Revenue by Region",
columns: [
{
name: "Region",
},
{
name: "Q1",
},
{
name: "Q2",
},
],
rows: [
[
{
value: "North America",
},
{
value: 480_000,
format: "currency",
currency_code: "USD",
},
{
value: 520_000,
format: "currency",
currency_code: "USD",
},
],
[
{
value: "Europe",
},
{
value: 310_000,
format: "currency",
currency_code: "EUR",
},
{
value: 345_000,
format: "currency",
currency_code: "EUR",
},
],
],
},
{
name: "Revenue by Product",
columns: [
{
name: "Product",
},
{
name: "Q1",
},
{
name: "Q2",
},
],
rows: [
[
{
value: "Platform",
},
{
value: 590_000,
format: "currency",
currency_code: "USD",
},
{
value: 640_000,
format: "currency",
currency_code: "USD",
},
],
[
{
value: "Services",
},
{
value: 200_000,
format: "currency",
currency_code: "USD",
},
{
value: 225_000,
format: "currency",
currency_code: "USD",
},
],
],
},
],
});{
"success": true,
"data": {
"buffer": "## Revenue by Region\n\n| Region | Q1 | Q2 |\n| --- | --- | --- |\n| North America | $480,000.00 | $520,000.00 |\n| Europe | €310,000.00 | €345,000.00 |\n\n## Revenue by Product\n\n| Product | Q1 | Q2 |\n| --- | --- | --- |\n| Platform | $590,000.00 | $640,000.00 |\n| Services | $200,000.00 | $225,000.00 |",
"mime_type": "text/markdown"
}
}from iterationlayer import IterationLayer
client = IterationLayer(api_key="YOUR_API_KEY")
result = client.generate_sheet(
format="markdown",
sheets=[
{
"name": "Revenue by Region",
"columns": [
{
"name": "Region",
},
{
"name": "Q1",
},
{
"name": "Q2",
},
],
"rows": [
[
{
"value": "North America",
},
{
"value": 480000,
"format": "currency",
"currency_code": "USD",
},
{
"value": 520000,
"format": "currency",
"currency_code": "USD",
},
],
[
{
"value": "Europe",
},
{
"value": 310000,
"format": "currency",
"currency_code": "EUR",
},
{
"value": 345000,
"format": "currency",
"currency_code": "EUR",
},
],
],
},
{
"name": "Revenue by Product",
"columns": [
{
"name": "Product",
},
{
"name": "Q1",
},
{
"name": "Q2",
},
],
"rows": [
[
{
"value": "Platform",
},
{
"value": 590000,
"format": "currency",
"currency_code": "USD",
},
{
"value": 640000,
"format": "currency",
"currency_code": "USD",
},
],
[
{
"value": "Services",
},
{
"value": 200000,
"format": "currency",
"currency_code": "USD",
},
{
"value": 225000,
"format": "currency",
"currency_code": "USD",
},
],
],
},
],
){
"success": true,
"data": {
"buffer": "## Revenue by Region\n\n| Region | Q1 | Q2 |\n| --- | --- | --- |\n| North America | $480,000.00 | $520,000.00 |\n| Europe | €310,000.00 | €345,000.00 |\n\n## Revenue by Product\n\n| Product | Q1 | Q2 |\n| --- | --- | --- |\n| Platform | $590,000.00 | $640,000.00 |\n| Services | $200,000.00 | $225,000.00 |",
"mime_type": "text/markdown"
}
}package main
import il "github.com/iterationlayer/sdk-go"
func main() {
client := il.NewClient("YOUR_API_KEY")
result, err := client.GenerateSheet(il.GenerateSheetRequest{
Format: "markdown",
Sheets: []il.Sheet{
{
Name: "Revenue by Region",
Columns: []il.SheetColumn{
{
Name: "Region",
},
{
Name: "Q1",
},
{
Name: "Q2",
},
},
Rows: []il.SheetRow{
{
{
Value: "North America",
},
{
Value: 480000,
Format: "currency",
CurrencyCode: "USD",
},
{
Value: 520000,
Format: "currency",
CurrencyCode: "USD",
},
},
{
{
Value: "Europe",
},
{
Value: 310000,
Format: "currency",
CurrencyCode: "EUR",
},
{
Value: 345000,
Format: "currency",
CurrencyCode: "EUR",
},
},
},
},
{
Name: "Revenue by Product",
Columns: []il.SheetColumn{
{
Name: "Product",
},
{
Name: "Q1",
},
{
Name: "Q2",
},
},
Rows: []il.SheetRow{
{
{
Value: "Platform",
},
{
Value: 590000,
Format: "currency",
CurrencyCode: "USD",
},
{
Value: 640000,
Format: "currency",
CurrencyCode: "USD",
},
},
{
{
Value: "Services",
},
{
Value: 200000,
Format: "currency",
CurrencyCode: "USD",
},
{
Value: 225000,
Format: "currency",
CurrencyCode: "USD",
},
},
},
},
},
})
if err != nil {
panic(err)
}
_ = result
}{
"success": true,
"data": {
"buffer": "## Revenue by Region\n\n| Region | Q1 | Q2 |\n| --- | --- | --- |\n| North America | $480,000.00 | $520,000.00 |\n| Europe | €310,000.00 | €345,000.00 |\n\n## Revenue by Product\n\n| Product | Q1 | Q2 |\n| --- | --- | --- |\n| Platform | $590,000.00 | $640,000.00 |\n| Services | $200,000.00 | $225,000.00 |",
"mime_type": "text/markdown"
}
}The output:
## Revenue by Region
| Region | Q1 | Q2 |
| --- | --- | --- |
| North America | $480,000.00 | $520,000.00 |
| Europe | €310,000.00 | €345,000.00 |
## Revenue by Product
| Product | Q1 | Q2 |
| --- | --- | --- |
| Platform | $590,000.00 | $640,000.00 |
| Services | $200,000.00 | $225,000.00 |Two logical sheets, one Markdown document. Each section is self-contained and parseable independently.
Where This Fits
Markdown table output is useful in three scenarios.
LLM prompts. When you need to include structured data in a prompt — for analysis, summarization, or comparison — Markdown tables are the cleanest format. Models handle them better than CSV and they’re easy to inspect when debugging prompts.
Documentation and reports. If your output ends up in a Markdown-based system — GitHub READMEs, Notion, Confluence, static site generators — the Markdown output is ready to paste directly. No conversion step.
Human review. When someone needs to glance at the data without opening a spreadsheet application, Markdown renders in any text editor, any terminal, any chat message. It’s the lowest-friction way to make tabular data visible.
The same JSON payload works across all three output formats. Build your data structure once, then request XLSX for the finance team, CSV for the data pipeline, and Markdown for the LLM prompt. One definition, three outputs.
Get Started
The Sheet Generation docs cover all three output formats, including the formatting and formula behavior specific to each one. The Markdown format works with all cell types — currency, percentage, number, date — and evaluates formulas server-side so the output is always complete.
Sign up for a free account and try generating a Markdown table from your data. No credit card required.