Bulk generation#
Mass-generate documents for many records in one background job: a filter, a template, an output mode, optionally a sort order and duplex padding. Progress is tracked in the app and every failure is logged per record.
Running a bulk job#
- Command Hub → Bulk Generation.
- Pick a template.
- Supply a filter — a SOQL
WHEREclause (StageName = 'Closed Won' AND CloseDate = THIS_QUARTER) or a saved query. - Choose an output mode: Combined PDF (every record merged into one PDF), Individual Files (one file per record, saved to that record), or Both.
- Optionally set Sort By and a direction.
- Adjust the batch size if needed (1–200; default 1 — one record per batch execution is safest for heavy templates; raise it for small, simple ones).
- Submit.
Preview one record first. Pick a record under Preview Sample Record and click Preview Sample PDF: the bulk runner produces one real PDF so you can sanity-check the output before launching a big job.
The template's Record Filter (if set) is ANDed onto your job filter, so a job never produces documents for records the template excludes. A filter that excludes every selected record produces an empty job.
Sort order#
Sort By decides the order records are processed and therefore the page order of a Combined PDF. Without it, records come out in creation order.
- The picker lists every sortable field on the base object, plus each lookup's parent name field (
Account > Account Name), so 200 Opportunities can be ordered by Account name in one click. - Pick ascending or descending. Blank values always sort last; ties fall back to name order, so re-running a job produces the same packet.
Sorting applies to Individual Files too — it decides processing order and the order in Job History.
From a Flow, the Generate Bulk Documents action takes a Sort Order text input written as a SOQL ORDER BY clause without the keywords: Account.Name ASC, CloseDate DESC, or up to three comma-separated fields; NULLS FIRST/NULLS LAST are supported. An unsortable field fails the action with a message rather than faulting the interview. If your Flow passes a Record IDs collection, SOQL does not preserve its order — use Sort Order.
Duplex padding — every document starts on a fresh sheet#
When a Combined PDF is printed double-sided, a document with an odd page count leaves its last sheet half-used and the next document starts on its back. Duplex Padding appends one blank page to every odd-length document before the merge, so each begins on the front of a sheet.
- The toggle appears under the output mode for Combined PDF and Both (it does nothing for Individual Files).
- In Both mode only the combined bundle is padded.
- The filler page is completely blank — no header, footer, watermark or page number.
- With padding on,
{PageNumber}/{TotalPages}count per document (1 of 3,2 of 3,3 of 3, then an unnumbered blank). A plain Combined PDF numbers continuously across the bundle.
Scale. A duplex packet is assembled in memory in one job, so the ceiling depends on how large each rendered document is. Plain text documents reach the low hundreds; a branded template with a logo or non-Latin text (which embeds a font, often 60+ KB per record) can top out below 100. The pre-run analysis measures the template's Test Record and shows a Duplex Packet row with the estimated limit. If a job exceeds it at run time it ends as Failed with a message to run Individual Files instead or tighten the filter. Set a Test Record on the template so the estimate is accurate; without one it assumes about 400, which is optimistic for branded templates.
From a Flow, Duplex Padding is a checkbox input, ignored unless the job produces a Combined PDF.
Saved queries#
Save a filter as a reusable Saved Query so non-technical users get a drop-down of prebuilt filters instead of writing SOQL. Created and managed in the Bulk Generation UI. If a template's query was built from a report import (it carries a WHERE clause), the bulk runner applies that filter on selection and saves it as a From Report saved query.
Job history#
Command Hub → Job History. Every job shows its status (Draft, Harvesting, Running, Completed, Completed with Errors, Recovering, Failed), record count with success and failure counts, generated PDFs as links, start and end time, and error messages per failed record.
What bulk supports, by template type#
Bulk runs two pipelines depending on the output mode: Individual Files uses the full generation pipeline including server-side Office packaging (no browser), while Combined PDF renders each record to HTML and merges the results into one PDF.
| Template type | Individual Files | Combined PDF |
|---|---|---|
| HTML | Yes — PDF | Yes |
| Word → PDF | Yes | Yes |
| Word → native DOCX | Yes | n/a — a combined bundle is always a PDF |
| PowerPoint | Yes — one .pptx each | No — blocked with a message |
| Excel | Yes — one .xlsx each | No — blocked with a message |
| PDF (fillable) | Yes | No — blocked with a message |
| Canvas | Yes — PDF | Yes |
Charts in bulk. All chart types render in bulk jobs: hand-authored {#ChartBucket} and CSS-bar charts resolve server-side, and {Chart:…} image charts are rasterised in Apex per record (Word, HTML and PowerPoint; Excel does not embed chart images). Rasterising is CPU-intensive — keep batch size at 1 for chart-heavy templates; a handful of charts per record is comfortable, a dozen may exceed the per-batch CPU limit. In HTML → PDF output use the CSS-bar styles only (see Charts).
Governor-limit analysis#
Before a job submits, the runner estimates SOQL queries, DML operations and peak heap per batch (and for the combined merge). These are advisory estimates: they are measured synchronously but describe an asynchronous batch with a larger heap, a shared cache and an automatic retry path, so they tend to overstate the cost. A red item is a risk worth reading, not a veto — the Run button stays enabled. Submission is blocked only for an unsupported template type + output mode, or for more than 50,000 records (the platform's batch ceiling). If a job fails on heap, reduce the batch size and re-run.
Oversized records — automatic recovery#
A record with thousands of child rows can be too big for a standard batch — the same records that, generated one at a time, route through the large-dataset path. Bulk jobs recover these automatically: when a job finishes with oversized failures, its status moves to Recovering, each oversized record is dispatched one at a time through the large-dataset path (producing its own document and job entry), and the original job is marked Completed with Errors once every oversized record is dispatched. Recovery covers the first 100 oversized records per job; any overflow is reported in the error log, never silently dropped. Combined-PDF mode is the exception — an oversized record there is flagged in the error log rather than recovered, because an individually rendered giant PDF cannot be merged into a bundle.
Chart cleanup job#
Schedule the chart cleanup once per org so transient chart files from interrupted jobs do not accumulate (the daily reaper is also scheduled by the package):
System.schedule('DocGen Chart CV Reaper', '0 0 * * * ?', new welisa.DocGenChartCvReaper());