Sheet to PDF
Blog · Patterns

5 production patterns for personalized PDFs from spreadsheets

Anyone can generate 10 PDFs. Generating 10,000 reliably, repeatedly, without quality drift — that's a different problem. Here are 5 patterns from teams doing it at scale.

Pattern 1: One sheet, one source of truth

Don't spread data across multiple sheets ("clients" sheet + "invoices" sheet + "payments" sheet). At generation time, joining them is brittle.

Do have one master sheet where each row is one PDF. Use formulas to pull data from other sheets if needed. VLOOKUP + QUERY are your friends.

Pattern 2: Validation column

Before generating, validate each row. Add a column:

=IF(AND(B2<>"", C2<>"", D2>0), "✓", "missing fields")

Filter your sheet to only "✓" rows before generation. Catches typos and missing data before you spam 500 clients with broken invoices.

Pattern 3: Idempotent generation

Add a GeneratedAt column. Use a smart template that only generates new rows:

{% if GeneratedAt == "" %}
... full template content ...
{% endif %}

Wait, that doesn't work — the template still runs. Better pattern: filter your sheet to rows where GeneratedAt is empty, generate them, then fill in the timestamp. Next run only picks up new rows.

Pattern 4: Versioned templates

Save templates with version numbers in the name:

In your sheet, add a TemplateVersion column referencing which version each row was generated with. When auditors come asking, you can reproduce the exact PDF.

Pattern 5: Output naming convention

Don't just use {{Client}}.pdf — duplicates collide. Use a unique suffix:

{{Client}}_{{InvoiceNumber}}_{{Date}}.pdf
→ Acme_INV-1001_2026-05-30.pdf
→ Acme_INV-1002_2026-06-30.pdf

Or include the row number for absolute uniqueness:

{{Client}}_{{rowNumber}}.pdf
→ Acme_2.pdf

Bonus: error handling

For each row, Sheet to PDF returns success or failure individually. Capture failed rows in a separate sheet by copy-pasting the result list — rerun just those after fixing the data issue.

Scale checklist

  1. Sheet with >10k rows? Split into monthly sub-sheets for performance.
  2. Template >5 pages? Optimize images (Insert → Image → Compress).
  3. Generation takes >6 minutes? Split into 100-row batches.
  4. Need to send via email? Use Pro plan, watch the bounce rate.
  5. Want share links? Use Pro+, recipients don't need Google accounts.

Install Sheet to PDF