Founders

How to Write Variance Commentary from Your Ledger

Antonio Evans9 min read

A scene showing a laptop on a desk with a spreadsheet open, displaying columns for account, actual, plan, and variance.
Key points

Key points

  1. 1Export actual and plan figures by account for one closed period, keep only the columns a reader needs (account, label, actual, plan, variance, notes), and aggregate before you export.
  2. 2Redact customer names, employee names, vendor names and anything that identifies a person or contract, and confirm that whoever receives the draft is entitled to see what remains.
  3. 3Set a materiality threshold before prompting, ideally a blended one such as any variance above both an absolute dollar floor and a percentage of plan, and give the model only the rows that clear it.
  4. 4Ask for one paragraph per material variance that states the amount, the percentage and the likely driver drawn from your ledger notes, then check the draft against the arithmetic and the notes in about ten minutes.

Prepare the export before the model sees anything

The model is only as good as the table you hand it. A variance comment is a claim about two numbers and a cause, so the export has to make the numbers unambiguous and the cause traceable to a note a human wrote. The standard layout puts budget in one column, actual in the next, variance dollars and variance percent in two more, with commentary cells underneath, and most FP&A teams already reuse the same template every month, as described in a Xero-to-Excel variance guide. That layout is exactly what an LLM reads well, so copy it rather than inventing a new one.

Start from a closed month. A missing journal entry creates a phantom variance, and actuals and budget must sit on the same general ledger accounts or reporting groups before any comparison means anything, as the five-step variance method notes. Then aggregate: one row per reporting line, not one row per transaction. If your ledger export has 4,200 lines for the month and 38 accounts, the model should see 38 rows. Anything finer gives it room to invent a cause from a single invoice.

Include a free-text notes column. This is the single highest-leverage decision in the whole workflow. Commentary that names and quantifies drivers is what earns credibility with a board, while a line-by-line restatement of numbers gets skipped, as the commentary framework guide explains. Your notes are the only place the model can learn that the cloud bill rose because of a migration, or that two enterprise deals slipped two weeks. If the notes are empty, the draft will either say nothing useful or guess.

A workable column set:

ColumnExampleWhy the model needs it
account_code6100Stable key, keeps rows distinguishable
line_itemCloud and softwareReadable label for the narrative
actual486000The fact
plan402000The benchmark
variance_dollars84000Pre-computed, so the model cannot mis-subtract
variance_pct20.9Pre-computed, same reason
favorable_unfavorableUA positive cost variance is bad news, per step 3 of the method
period_basisMar, monthlyTells the model whether to talk in months or YTD
ledger_noteMigration of analytics cluster completed two months earlyThe only source of the why

Compute variance dollars and variance percent in the spreadsheet, not in the prompt. Xero's own guidance computes variance as actual minus budget and variance percent as (actual minus budget) divided by budget, showing a dash when the budget is zero, as documented by the same Xero guide. Do the same, and handle the zero-budget case in the sheet so the model never sees a division error.

What to redact, and what to keep

Redaction is not about hiding interesting things from the model. It is about not pasting identifiers into a system you have not cleared for them. Keep the shape of the data and drop the identities:

  • Customer names become "Customer A (enterprise, top 5 by ARR)" or simply "a customer in segment 2."
  • Employee names become "a support hire in month 2" or "role 14, engineering."
  • Vendor names become "vendor in category 3" or, if concentration matters, "a vendor that accounts for 22% of this line."
  • Contract numbers, bank details, card numbers and personal email addresses are removed entirely.
  • Anything with a named individual attached, including bonus accruals and severance, is either aggregated or left out.

Investor communication guidance already points the same way for sensitive content, recommending that founders anonymize customer names when discussing sensitive contracts or proprietary matters, as this investor update guide advises. Finance teams follow a similar discipline when they delegate variance work: a platform that runs root-cause analysis on every material variance still ties each explanation back to specific GL transactions with cell-level access control deciding who sees what, per Cube's description of its variance workflow. The lesson for a ledger export is that the mapping from "Customer A" back to the real account can live in your workbook, not in the prompt.

Two rules of thumb. First, if you could not paste the row into a room full of investors, redact it. Second, keep the numeric detail even when you drop the identity, because "the top five enterprise accounts renewed on time" is a fact the model can use, while "Acme and four others renewed" adds only risk.

Pick a materiality threshold and let the model work on the few rows that matter

Without a threshold, controllers either explain every line or only flag the single largest number, and both fail the reader. A blended threshold solves it: flag any variance that is both large in dollars and large in percentage terms, so a $2,000 line that happens to be 50% of a tiny budget stays quiet while a six-figure miss in a large line gets a paragraph, per the same commentary guide. Thresholds should be agreed with the person who reads the output before the first draft lands.

A worked example makes this concrete and shows the rule in action. Take this month's operating lines (illustrative figures, built on the sample layout that Cube uses to demonstrate budget versus actual on live data):

Line itemActualPlanVarianceVar %Favorable?Clears a $25k and 10% rule?
Revenue4,820,0004,650,000170,0003.7%FNo (fails percentage)
Cost of goods sold1,210,0001,180,00030,0002.5%UNo
Payroll and benefits1,940,0001,905,00035,0001.8%UNo
Cloud and software486,000402,00084,00020.9%UYes
Travel and entertainment189,000148,00041,00027.7%UYes
EBITDA995,0001,015,00020,0002.0%UNo

Two rows out of six earn commentary, which is the point: the draft stays short enough that the reader actually reads it. Note the trap in the first row. Revenue beat plan by $170,000, the largest dollar difference on the page, yet it fails the percentage test because 3.7% is inside noise. That is a deliberate exception you should decide on rather than delegate, since a revenue beat usually belongs in the narrative even when it is proportionally small. Tell the model which rows are in scope and why, and it will not argue.

The prompt structure that produces checkable prose

Give the model four blocks in this order: role and reader, the rules, the table, and the output format. Separating them keeps the instructions from bleeding into the narrative.

ROLE: You are writing variance commentary for a founder reviewing
the month with their operating team. The reader knows the business
well and will check every number against the attached table.

RULES:
1. Write only about the rows listed as IN SCOPE. Do not mention
   other rows, totals or ratios.
2. For each in-scope row, write one paragraph of 3 to 5 sentences:
   - sentence 1: the line item, the variance in dollars and percent,
     and whether it is favorable or unfavorable;
   - sentences 2 to 4: the most likely driver, taken only from the
     ledger_note column. If the note is empty or vague, write
     "cause not yet confirmed" and state what would confirm it.
3. Do not infer a cause that is not supported by ledger_note. Do not
   describe the same driver twice.
4. Do not use the words "significantly", "impactful" or "various".
5. Do not calculate new numbers. Use only variance_dollars and
   variance_pct as given.
6. After the paragraphs, list any row where ledger_note was
   insufficient, as a bullet under the heading NEEDS CONTEXT.

TABLE:
account_code | line_item | actual | plan | variance_dollars |
variance_pct | favorable_unfavorable | period_basis | ledger_note

OUTPUT: plain paragraphs, one per in-scope row, then NEEDS CONTEXT.

Rule 5 is the one that saves you time. Subtraction errors and percentage mistakes are the most common failure in AI-drafted finance text, and forcing the model to reuse your pre-computed figures removes the class of error entirely. Rule 2's fallback phrase is the second safeguard: a model with no note to work from will otherwise produce a confident-sounding cause that nobody can source, which is worse than an honest gap.

The shape of these instructions follows published prompt patterns for variance work. An example prompt in this FP&A prompts collection gives the model context (a revenue miss with three named segment drivers), an objective (a three-paragraph board narrative), a reasoning instruction (analyse the interplay between segments) and an evaluation step (review the draft for defensiveness). That last step is worth copying: add a line asking the model to reread its own draft and flag any sentence it cannot support from the table.

The ten-minute check a founder should run

The model handles wording. You confirm causes. Work through this checklist in order and the review takes about ten minutes for a typical operating review.

CheckWhat to look forTypical fix
ArithmeticEvery dollar and percent figure matches the tableUsually none; rule 5 prevents this
ScopeNo paragraph about a row outside the scope listDelete it or move the row into scope
Cause traceabilityEvery driver appears in a ledger_noteReplace with "cause not yet confirmed"
Favorable and unfavorableCosts above plan labeled unfavorable, revenue labeled favorableCorrect the label, not the number
Timing versus structuralA one-off labeled as a trend, or a trend labeled as timingRewrite: timing resolves itself, structural belongs in the forecast
ToneDefensive phrasing, unexplained jargon, hedgesRewrite the opening sentence of the paragraph
CompletenessAny material row missing a paragraphAdd it or record why it is excluded

The timing-versus-structural distinction deserves its own pass because it changes what the reader does next. The five-step method is explicit that timing differences, such as a cost that lands a month later, resolve themselves, while structural differences, such as a higher purchase price that sticks, belong in the forecast, per that guide. A model reading a note that says "invoice received in month 3 instead of month 2" will often describe the variance as a trend unless you tell it otherwise, so add the classification to your notes column: timing, structural, one-off or error.

One more check that pays for itself. Reconcile the scope list against your own threshold run, not against the model's selection. If the model produced commentary on a row you excluded, that is a scope breach. If a row you expected is missing, it may have been filtered upstream in the export. Both are one-minute fixes, and both catch problems the narrative itself will hide.

Common failures and how to fix each

The notes are empty. The draft turns into a restatement of the table, which readers skip. Fix it upstream: require a note on any row above the threshold before the export runs, even if the note is "no explanation yet, investigating with the platform team." An honest gap is usable; an invented cause is not.

A large percentage on a tiny line dominates the draft. This is the materiality problem, and the blended threshold solves it. If your board still wants small-line commentary, put those rows in a second batch and label the section clearly so the reader knows the scale of each item.

Two paragraphs describe the same driver. This happens when, for example, a tooling migration inflates both cloud costs and contractor spend. Merge the rows into one narrative or add an explicit instruction to treat related rows as a group.

The model calls a favorable variance unfavorable. Costs above plan are unfavorable even though the arithmetic difference is positive, which is precisely why the label column exists in the method described above. If your export lacks the label, add it before prompting rather than hoping the model infers the sign convention from context.

Revenue misses are described without splitting price and volume. A single revenue variance only means something once it is split, for example a plan of 10,000 units at $50 actual against a different mix of price and volume, per the worked example in this method. If your ledger notes do not carry that split, the model cannot produce it, and the paragraph should say so.

The draft reads defensively. Variance commentary is read by people scanning for signal, and hedging wastes their attention. Ask for the cause first and the action second, with no adjectives about how the team performed.

Where this fits in a monthly rhythm

The workflow is a loop, not a one-off. Close the month, export the accounts, write the notes, run the threshold, prompt, check, publish. Each pass improves the next because the notes column accumulates the institutional memory the model draws on. After a few cycles most drafts need edits to two or three paragraphs rather than all of them.

If the export itself is the bottleneck, a specialist can build the pipeline once and hand you a workbook that refreshes on open. Describe the site, app, document or plan you need at Quanta and a specialist picks it up and builds it with you. If your team runs several models side by side for drafting, summarizing and checking, Quanta Inference puts text, image, video, audio and embedding models behind one OpenAI-compatible API key, prepaid and priced in US dollars.

FAQ

FAQ

How much of the ledger should I send to the model?

Send one row per reporting line for a single closed period, with actual, plan, variance dollars, variance percent, a favorable or unfavorable label, and a notes column. Aggregate at the account or reporting-group level rather than by transaction, and filter to rows that clear your materiality threshold. A typical operating review needs fewer than fifty rows.

What if my ledger notes are thin or missing?

Do not prompt yet. The model's only legitimate source for a cause is your notes, and without them the draft either restates numbers or invents an explanation. Require a note on every row above threshold, even if it reads "under investigation, owner chasing invoice." Then instruct the model, as in the prompt above, to write "cause not yet confirmed" wherever the note does not support a driver.

Can I skip redaction if the model runs inside my own environment?

Redact anyway, and treat the export as a document that may travel. Removing names costs you almost nothing analytically because segment, size and timing carry the signal, while keeping names adds risk you cannot audit later. Keep the identity mapping in your workbook so a reviewer can trace "Customer A" if needed.

How do I know the draft is right?

Check three things: every figure matches the table, every cause appears in a note, and every in-scope row has a paragraph. Add the timing-versus-structural classification, because it changes what the reader does next. If all four pass, the draft is ready for the meeting, and the review usually takes ten minutes.

Does this replace the finance review meeting?

No, it replaces the writing. The model drafts paragraphs; you decide what is material, confirm the causes, and choose any actions. The meeting still happens, but it starts from a written draft that the reader has already skimmed, which is the main reason the conversation moves faster.

Sources

Sources

  1. Xero Budget vs Actual in Excel: Variance Reports
  2. Variance analysis: budget vs actual in 5 steps
  3. How to Write Variance Analysis Commentary Boards Read
  4. Startup Investor Update: Monthly Founder Guide
  5. Variance Analysis: Every Why, Traced to the Transaction
  6. 20 Practical AI Prompts Every FP&A Professional Should Use
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles