Sample dataset · CC0

Expense claims, with the awkward bits left in.

Ten columns of expense claim across two years. The claim id is zero padded so a spreadsheet will destroy it, the amounts are in four currencies in one column with no conversion, and the approver is blank while the claim is still waiting.

10 columns · 100 or 1,000 rows as a file · up to 1,000,000 rows generated here · CSV, JSON, JSONL, Excel, Parquet

Take a file

Open the CSV in a spreadsheet and look at expense_id. The leading zeros will be gone. That is not a flaw in the file, it is the demonstration.

A bigger book of claims

Larger sizes keep the same two-year window and the same currency mix. A hundred thousand claims is a large company's year, and it is a fair test of whether a tool can group by currency before it sums.

The first eight rows

The first eight rows of the 1,000-row file. Note the quoted merchant name and the padded currency code.

expense_idexpense_dateemployeedepartmentcategorymerchantamountcurrencystatusapproved_by
EXP-0000012025-01-01Christine ScottLegalHardwareNorthwind Air2270.35USDreimbursedChristopher Khan
EXP-0000022025-01-02Stephen TorresOperationsMealsThe Corner Cafe203.08USDreimbursedGregory Richardson
EXP-0000032025-01-02Kathleen LewisOperationsSoftwareFabrikam Hardware12.65USDreimbursedDorothy Morales
EXP-0000042025-01-03Cynthia ReedMarketingTrainingSunrise Diner82.53USDrejectedWei Ward
EXP-0000052025-01-04Katherine GomezEngineeringHardwareBlue Yonder Airlines233.90USDrejectedDorothy Martinez
EXP-0000062025-01-05Steven ClarkPeopleHardwareFabrikam Hardware1341.96USDreimbursedDeborah Richardson
EXP-0000072025-01-05Richard RobinsonFinanceClient entertainmentNorthwind Air91.52USDapprovedSharon Harris
EXP-0000082025-01-06Emma AndersonMarketingOfficeThe Corner Cafe245.38EURreimbursedRobert Martin

Ten columns, and what each one holds

Column Type What it holds Example
expense_id text EXP-000001 upward. Zero padded, which is exactly the kind of key a spreadsheet destroys. EXP-000001
expense_date date Date the money was spent, ascending through the file. 2025-01-01
employee text Claimant name. Christine Scott
department text Cost centre the claim lands in. Legal
category text Travel, Meals, Software, Hardware, Training, Office or Client entertainment. Hardware
merchant text Where it was spent. Some names contain a comma, so the field is quoted. Northwind Air
amount decimal Claim amount in the row's currency, two decimals. 2270.35
currency text USD, EUR, GBP or INR. USD
status text submitted, approved, reimbursed or rejected. reimbursed
approved_by text Approver name, blank while the claim is still submitted. A deliberate null column. Christopher Khan

What it models

An expense system export: who spent what, where, on what budget, and how far through approval the claim is. It is a finance file rather than an analytics file, which means it is shaped by workflow states rather than by measures, and the interesting questions are about throughput and exceptions rather than about totals.

Categories drive the amounts. Travel and hardware draw from a range that reaches into the thousands; meals and office supplies stay in the tens and low hundreds. Both are squared draws, so small claims dominate and the occasional large one stands out, which is the shape that makes an outlier review worth doing.

Three things in it will break something

expense_id is EXP-000001 with six digits of zero padding. Because it carries a prefix it survives most imports, which makes it the gentle version of the leading-zero problem. The harsh version lives in the messy data pack, where the ids are bare digits and every spreadsheet eats them.

currency mixes USD, EUR, GBP and INR in a single column with no exchange rate anywhere in the file. Summing the amount column without grouping by currency produces a number that means nothing at all, and it is a number that dashboards produce constantly. There is no conversion table on purpose: the omission is the lesson.

Several merchant names contain a comma, including one that also carries an ampersand. They are correctly quoted, so a real parser is fine and a hand-rolled split is not.

The approval workflow

status runs through submitted, approved, reimbursed and rejected, weighted so that most claims have been approved or paid. approved_by is blank exactly when the status is submitted, because nobody has approved it yet. Every other state has a name in it, including rejected, because somebody made that decision too.

That gives you a clean conditional null tied to a state machine, which is a different thing from a missing value, and a good subject for a data quality rule: approved_by must be blank if and only if status is submitted. Write that rule, run it against the file, and it should pass on every row. Then write it against a real expense export and see what happens.

What people use it for

  • Demonstrating what a spreadsheet does to a zero-padded identifier.
  • Multi-currency handling, where summing without grouping is visibly wrong.
  • Data quality rules tied to a workflow state, which this file satisfies exactly.
  • Outlier review, on squared-distribution amounts with a genuine long tail.
  • Testing quoted fields, using merchant names that contain commas.

License, and the people in it

This dataset is dedicated to the public domain under CC0 1.0. Put it in a course, a paid product, a test suite, a bug report, a screenshot, a conference talk or a book. There is nothing to ask for, nothing to sign and no attribution required. A link back is welcome and is not a condition.

Claimants and approvers are assembled from fixed name pools and no claim describes a real transaction. Merchant names are invented companies of the kind used in documentation, so there is no real vendor relationship implied anywhere in the file.

Questions people ask about this file

Why are the amounts in four currencies with no exchange rate?

Because that is how expense exports arrive, and the missing conversion table is the lesson. Summing the amount column across currencies produces a number with no meaning, and dashboards do it every day. The file gives you a small, safe place to make that mistake and see it, before you make it on something that matters.

Will Excel really break the expense id?

It depends on the version and the import path, which is exactly why it is worth testing rather than assuming. The EXP- prefix protects it in most cases, because the value is not purely numeric. The bare-digit version of this problem is in the messy data pack, where the ids are digits only and get truncated almost everywhere.

When is approved_by blank?

Exactly when status is submitted, and never otherwise. Approved, reimbursed and rejected claims all carry an approver name, because a rejection is a decision somebody made. That makes the file a clean subject for a data quality rule with a known result: the rule should pass on all 1,000 rows.

Are the merchants real companies?

No. They are the invented company names that turn up in documentation, plus a couple with commas and an ampersand in them so the quoting has something to do. No real vendor, card processor or airline appears anywhere in this file.