Skip to content

What an LLM Can and Cannot Do With a Spreadsheet

10 min read · updated August 11, 2026

“Can I just paste the spreadsheet in?” has a precise answer, and it is set by two independent constraints: how many tokens the sheet becomes, and the fact that a spreadsheet is a program whose export discards the program.

Two limits, not a spectrum

People discuss this as if capability degrades gradually with sheet size. It does not. There are two distinct walls and they are hit for unrelated reasons.

The first is representational: the sheet has to fit in the context window, and the arithmetic of that is unforgiving and easy to do in advance. The second is semantic: a cell containing =SUMIFS(D:D, A:A, $A2, B:B, "paid") is a computation over the whole sheet, and every common export format hands the model the number that formula produced rather than the formula. The model receives the output of a program and is asked to reason about the program. Neither wall moves when the context window grows, except the first one, and the first one is the less interesting of the two.

A 10,000-row sheet, counted

Work it out rather than guessing. Take a sales sheet with 10,000 rows and 12 columns: a date, an order id, a customer name, a product name, a region, a channel, a quantity, a unit price, a discount, a tax amount, a total, and a status flag. Serialise it as CSV.

A representative row looks like 2026-03-14,ORD-0084213,Acme Logistics Ltd,Industrial Widget 2000,EMEA,paid_search,4,129.50,0.10,97.85,563.15,fulfilled, which is about 120 characters including the commas and the newline. English prose runs near four characters per token for most tokenisers, but this is not prose: it is punctuation-dense, id-heavy and full of digits, and digit sequences and delimiters tokenise far less efficiently. Three characters per token is a reasonable working assumption for CSV of this shape, which puts one row at roughly 40 tokens.

rows                      10,000
tokens per row (est.)         40
                          ------
body                     400,000 tokens
header + instructions        ~200
                          ------
total                    ~400,200 tokens

Same sheet as JSON records (keys repeated per row):
tokens per row (est.)         85  →  ~850,000 tokens

Same sheet as Markdown table (pipes and padding):
tokens per row (est.)         55  →  ~550,000 tokens

Three conclusions fall out immediately. A 10,000-row sheet is a six-figure token count in the best serialisation available. JSON records are roughly twice CSV for the same data purely because the keys repeat on every row, so the format choice is worth more than any prompt engineering. And at typical per-million-token input prices, 400,000 tokens is a real per-request cost that recurs on every follow-up question, because there is no state between calls.

The 40-tokens-per-row figure is an estimate derived on this page from an assumed 120-character row and three characters per token; it is not a measurement, and it varies by tokeniser and by how id-heavy your columns are. Count your own file with the tokeniser your provider documents before budgeting against it. Context-window limits and prices also move; treat any specific cap as current-as-of-reading.

Why the arithmetic fails before the context does

Suppose the whole sheet does fit. The interesting failure is that fitting does not make the answer right, because “what is the total revenue for EMEA in March” is a reduction over thousands of values and the model computes it by generating tokens, not by adding. It has no accumulator. Each output token is a prediction conditioned on everything so far, which is a reasonable way to produce a plausible number and a poor way to produce a correct one.

The failure is also silent in the worst way: the answer will be formatted correctly, be of the right order of magnitude, and be wrong in the third significant figure. There is no exception, no NaN, nothing that fails a test. Aggregations over more than a handful of rows should be executed as code, which is the entire argument for the approach in turning a question into a pandas query: let the model write the reduction and let an interpreter run it.

The corollary is a useful rule of thumb. Questions whose answer is located in the sheet — “which row has the highest discount”, “find the order for Acme placed in March” — are retrieval and models are good at them. Questions whose answer must be computed from many rows are arithmetic and should not be asked of the model directly at all.

The dependency graph the export throws away

This is the limit that does not get discussed and is the more fundamental of the two. A spreadsheet is not a table; it is a directed acyclic graph of cell dependencies with a table-shaped presentation. Column K is =I2*J2, column L is =K2*(1-M2), and the summary tab pivots over all of it. That graph is the model the business actually runs on.

Export to CSV and the graph is gone. You get the values as of the last recalculation, with no record of which cells are inputs and which are derived. Three consequences follow, and each of them is a real bug somebody has shipped:

  • Derived columns leak into models. If you train on that export to predict total, and total is algebraically determined by quantity, unit_price and discount, you have built a model that reproduces a multiplication and validates perfectly. The export gave you no way to know those columns were derived. This is the most common form of target leakage in spreadsheet-sourced data.
  • “What if we raise the discount to 15%” cannot be answered. In the sheet it propagates through the graph. In the export it is a column of numbers with no downstream edges, so the model will confidently adjust the discount column and leave every dependent total inconsistent with it.
  • Formatting is data that gets lost. A cell displaying 1,234.57 may hold 1234.5678901, and dates are the classic disaster — a column that looks like 03/04/2026 is ambiguous between two continents, and spreadsheets are notorious for silently converting identifiers such as gene symbols and part numbers into dates on import.

If the formulas matter, read the workbook as a workbook. The openpyxl documentation describes loading a file with formulas preserved rather than with cached values substituted, which is what lets you extract the dependency structure and hand the model the program instead of its output.

What the model is genuinely good at

The boundary is not discouraging once it is drawn, because the tasks on the good side of it are the tedious ones. Describing what a sheet contains from a sample of it, and proposing types — the subject of LLM schema inference from a CSV. Writing the query, the formula or the script that computes the answer, which an interpreter then executes exactly. Explaining a formula somebody else wrote in 2018. Normalising an inconsistent category column by proposing a mapping you review once and then apply deterministically. Spotting that two columns are near-duplicates and asking which is authoritative.

Every one of those has the same shape: the model produces something small, reviewable and deterministic, and a real execution engine does the work over the rows. Anything where the model itself is the execution engine over thousands of rows is on the wrong side of the line no matter how large the context window gets.