Generating 50 invoices from a spreadsheet without mail-merge

Mail-merge cannot total lines, round cents, or write 大写金额. The four decisions that make batch invoicing correct.

Word mail-merge can put a name in a letter. It cannot sum a line-item table, and it certainly cannot write 叁万零壹佰肆拾肆元整. Invoicing needs four decisions made correctly, and only one of them is about the document.

1 · Money as integer cents, not floats

Add 0.1 three times in floating point and you get 0.30000000000000004. On an invoice that becomes a total that is one cent off the sum of its lines, and the customer's AP system rejects it. Carry cents as integers and round exactly once:

unit = int(round(price * 100))          # 4500.00 -> 450000
line = int(round(qty * unit))           # keep it integer
tax  = int(round(line * rate / 100))    # once, per line
total = subtotal + tax

Never format then re-parse. "4,500.00" → float → format is how the cent disappears.

2 · Tax: per line or per invoice, never both

Mixed-rate invoices are real: 13% on goods, 6% on services, 0% on an export line. If any line carries a rate, tax each line. If none does, apply one rate to the subtotal. Doing both double-taxes; doing neither under-taxes and you find out at filing time.

3 · Grouping: what is "one invoice"?

Your export probably has one row per line item. Grouping by customer alone merges three months into one document. Grouping by row creates 24 invoices for one client. The rule that matches how billing actually works: explicit invoice number if present, otherwise customer + month.

And if you auto-number, check for collisions with explicit numbers. Generating INV-202609-0001 when the source already has one silently merges two customers onto one invoice — the totals look plausible and are wrong.

4 · 大写金额 is not a formality

Chinese invoices carry the amount in words because digits can be altered. The rule that trips people up is zero insertion: a four-digit group that lost its leading digits needs 零 in front of it.

AmountCorrectCommon wrong output
30,144.00叁万零壹佰肆拾肆元整叁万壹佰肆拾肆元整
10,001.00壹万零壹元整壹万壹元整
1,001.00壹仟零壹元整壹仟壹元整
5.05伍元零伍分伍元伍分

Also: 壹拾 not 拾, 贰 not 二, and a trailing 整 only when both 角 and 分 are zero.

5 · The index is the deliverable

Fifty .docx files are not something a finance person can check. A single invoice_index.xlsx with invoice number, customer, date, due date, line count, subtotal, tax, total and 大写金额 is — they can total it, filter it, and compare it against the bank in five minutes.

Do not build it

InvoiceGen is these five decisions already made: integer cents throughout, per-line or per-invoice tax, collision-free auto numbering, correct 大写金额 (with a test table in the README), a real Word document per invoice, and the totals index. Optional --html for a browser-printable version, --pdf if LibreOffice is installed. 29 USDT, demo data included.

InvoiceGen — batch invoicing

One spreadsheet of line items becomes a folder of finished invoices, plus an index that totals them.

Get it — 29 USDT