DocForgeDocForge
TemplatesUse casesGlossaryHow-toPricingDevelopers
Sign inStart free
DocForgeDocForge© 2026
PricingAboutTemplatesUse casesGlossaryHow-toDevelopersTermsPrivacyRefundsContact

DocForge is a product of Rev Vision Ltd, registered in England & Wales (Company No. 14368830). Registered office: 86–90 Paul Street, London, England, United Kingdom, EC2A 4NE.

How-to guides

How-to guide

How to generate invoices from a CSV

Turn a spreadsheet of customer, line item, and payment data into branded invoice PDFs with DocForge.

15 minute guide

What you'll need

Supplies

  • CSV with customer and invoice data
  • Invoice copy, payment terms, and tax details
  • Brand assets or layout notes

Tools

  • DocForge template builder
  • Spreadsheet app

Steps

  1. 1

    Prepare the invoice CSV

    Start with one row per invoice, not one row per line item, unless your template is already designed to accept flattened line-item fields. A clean export should include headers like `invoice_number,customer_name,billing_address,issue_date,due_date,line_item_1_description,line_item_1_amount,tax,total,payment_terms`. Remove formulas before upload, especially totals copied from spreadsheets. If `total` contains `=SUM(H2:J2)`, export the calculated value `1250.00`, not the formula. Normalize dates to ISO format such as `2026-06-15`; mixed values like `06/15/26` and `2026/06/15` are a common reason date filters render inconsistently. Keep currency columns numeric or pre-formatted consistently across the file. Do not mix `$1,250.00`, `1250`, and `USD 1,250.00` in the same column. Preview rows with long customer names like `Stark Industries Advanced Manufacturing Division` and multi-line addresses, because those are the rows that reveal whether the template can survive real billing data.

  2. 2

    Draft the invoice template

    Describe the invoice as a finance document, not a marketing page. Ask for a clear header, seller details, bill-to block, invoice metadata, itemized charge section, tax summary, total due, payment instructions, and any required footer language. Use Liquid variables that match the CSV structure you expect to upload: `{{ row.invoice_number }}`, `{{ row.customer_name }}`, `{{ row.due_date | date: '%B %-d, %Y' }}`, and `{{ row.total }}`. Stick to stock Liquid filters in the template so the same syntax works in preview and in the PDF rendering pipeline. If amounts are already formatted upstream as `USD 1,250.00`, print `{{ row.total }}` directly instead of trying to rebuild currency formatting in the template. Add conditional blocks for optional fields, for example `{% if row.purchase_order != blank %}PO: {{ row.purchase_order }}{% endif %}`. That prevents blank labels from appearing on invoices where procurement did not provide a purchase order number.

  3. 3

    Map CSV columns to template fields

    After upload, review every suggested mapping as if it could be wrong. The risky fields are usually similar-looking headers such as `subtotal`, `tax`, `total`, `amount_due`, and `balance_due`. Make sure `invoice_number` maps to the invoice identifier shown in the header, while `customer_id` stays internal unless the customer expects to see it. If the template uses `{{ row.due_date | date: '%B %-d, %Y' }}`, map it to `due_date`, not `issue_date`; swapping those creates invoices that look valid but carry the wrong payment deadline. For line items, keep naming predictable: `line_item_1_description`, `line_item_1_quantity`, `line_item_1_unit_price`, `line_item_1_amount`. If a customer has fewer line items than the template supports, leave the extra fields blank and wrap those rows with Liquid conditionals like `{% if row.line_item_3_description != blank %}...{% endif %}`. This keeps partially filled invoices from showing empty table rows.

  4. 4

    Preview sample invoices

    Preview deliberately, not randomly. Pick a normal invoice like `INV-2026-0482` for `Stark Industries`, a high-value invoice such as `48250.00`, an invoice with a long billing address, one with no purchase order, and one with a negative adjustment or credit line. Compare the PDF against the source row field by field: `invoice_number`, `due_date`, `subtotal`, `tax`, `total`, and `payment_terms`. Date issues show up here quickly. If `due_date` arrives as `2026/06/15` instead of `2026-06-15`, a Liquid expression like `{{ row.due_date | date: '%B %-d, %Y' }}` may render blank or incorrectly depending on parsing. Fix the CSV export rather than patching one row in the template. Check wrapping in the billing block and item descriptions. Long values such as `Annual compliance reporting package for North America finance operations` should wrap inside the table without pushing totals onto a new page.

  5. 5

    Generate and download the batch

    Run the full batch only after the preview set has passed finance review. Use a source CSV filename that can be traced later, such as `invoices_2026-06-15_approved.csv`, and keep it with the ZIP output. During generation, watch row-level failures instead of rerunning the whole file immediately. A single bad value like an empty `invoice_number`, malformed `due_date`, or text in a numeric `tax` column should be fixed in the CSV and regenerated as a small correction batch. When the ZIP is ready, spot-check the first, last, and any failed-then-fixed documents before sending. Confirm file names are usable for downstream storage, ideally containing `invoice_number` and `customer_name` rather than only a row index. Archive the template version with the output. If a customer questions `INV-2026-0482` three months later, finance needs to know exactly which CSV row, template, and generation run produced that PDF.

Related templates

Invoice PDF template