How to Generate Documents from Salesforce Reports with Dochly
Report-based generation vs record generation
Dochly supports two primary ways to identify which records to generate documents from — directly from a single record, or from a set of records that matches a Salesforce report's criteria. Understanding the difference helps you choose the right approach for each use case.
Generate from a single Salesforce record — click the button on the record page, or trigger via a Flow when a specific record changes. Best for on-demand, one-at-a-time generation tied to a specific event.
Use a Salesforce report to work out the right filter logic, then rebuild that logic in a Flow's Get Records element to generate one document per matching record. Best when the records to generate for are defined by complex multi-field filters that span multiple objects or date ranges.
The report itself is not the generation source — it's a design tool. You use the report to confirm the filter logic and see the exact record set, then translate that logic into Get Records conditions inside a Flow, which is what actually drives generation.
Report types that work well as a design reference
Since the report itself isn't queried directly by Dochly, any report type can help you plan filters — but some report formats make it easier to translate the logic into a Flow's Get Records conditions than others.
Tabular reports
A simple flat list with one row per record and one filter set. The filter logic maps directly onto a single Get Records element with the same conditions.
Summary reports
Grouped data with subtotals. The detail-row filters translate the same way as a tabular report — the grouping itself isn't relevant to Get Records.
Matrix reports
Two-dimensional grouping with row and column headers. The underlying record-level filters can still be rebuilt in Get Records, but the matrix layout itself has no Flow equivalent.
Joined reports
Multiple report blocks in one report. Identify which block represents your primary object and rebuild only that block's filter logic in Get Records.
Custom report types
Reports built on custom report types with custom objects. The filter conditions translate directly to a Get Records element on the same custom object.
Analytic snapshots
Scheduled historical data snapshots. Build your Get Records filters against the live object data instead — a snapshot's point-in-time data isn't something a Flow queries live.
Reading the report you want to match
Before building the Flow, use the Salesforce report to nail down exactly which records should get a document. These are the key things to capture from the report:
Confirm the object (must match your template's primary object)
The report's underlying object determines what your Flow's Get Records element should query. An Opportunity report → Opportunity Get Records → Opportunity template. An Account report → Account Get Records → Account template.
If your template is based on a custom object, make sure you're reading the report's custom report type correctly so you query the right object in the Flow.
Write down every filter condition, exactly as configured
Open the report in Report Builder and list every filter condition, including cross-object filters and any relative date logic (e.g. "this month", "next 60 days"). You'll rebuild each one as a Get Records filter condition in the Flow:
- Field value filters (e.g. Stage = "Closed Won")
- Date range filters (e.g. Close Date = current month)
- Cross-object filters (e.g. Account Type = "Customer")
- Any formula filters used for more complex conditions
Run the report and note the exact row count
Run the report and record the row count — this is the number of documents your Flow should generate once its Get Records filters are configured to match. You'll use this number in Step 5 below to confirm the Flow's Get Records query returns the same record set.
Keep the report around for future reference
Save the report in a shared folder so you (and anyone else who maintains this Flow) can re-run it later to sanity-check that the Flow's Get Records filters still return the expected record set after any changes to fields, page layouts, or business logic.
Step-by-step: generating documents for a report's record set
Identify the report's filter logic
Using the report you prepared above, write out the complete filter logic in plain language — for example "Stage = Closed Won AND Close Date = this month AND Invoice_Sent__c = FALSE." This is the specification you'll implement in the Flow.
Create a Flow and add a Get Records element
Go to Setup → Flows → New Flow. Choose a trigger type appropriate to how you want generation to run — a Screen Flow for on-demand runs, an Autolaunched Flow if it's called from a button, or a Scheduled-Trigger Flow for recurring runs (see Schedule automatic document generation). Add a Get Records element and set the object to match your report's primary object.
Rebuild the report's filters as Get Records conditions
Add one filter condition to the Get Records element for every filter you documented from the report. For relative date filters, build the equivalent using a formula resource based on TODAY() — Get Records doesn't have literal keywords like "this month" the way reports do.
Store the Get Records result as a record collection variable. Double-check every condition against your notes from Step 1 — a missing or loosely-configured filter is the most common cause of the Flow processing the wrong records.
Add a Loop and the Generate Document action
Add a Loop element that iterates over the record collection from Get Records. Inside the loop, add the Dochly: Generate Document action — set Record ID to the current loop item's ID and choose the template to use. Add a fault path so one record's failure doesn't stop the rest from processing.
Verify the record count matches the report
Before running the Flow for real, use Flow Builder's Debug feature and check how many records the Get Records element returns. Compare this against the row count you recorded from the report in the preparation steps above — if the numbers don't match, review your Get Records conditions for a missing or incorrect filter.
Activate or run the Flow
Once the record count matches, save and activate the Flow. If it's an Autolaunched or Screen Flow meant for on-demand runs, trigger it manually (via its button or Debug run). If it's a Scheduled Flow, it will run automatically at the next occurrence of the schedule you configured. Monitor the results in Dochly → Documents and in Setup → Paused and Failed Flow Interviews for any errors.
Filter strategies for common document workflows
Here are common report filter patterns and how to rebuild each one as Get Records conditions in a Flow:
Stage = "Closed Won" AND Close Date = this month AND Invoice_Status__c = "Pending". In Get Records, build "this month" with a formula resource comparing Close Date against the first and last day of the current month.
Contract Status = "Active" AND End Date within the next 60 days. In Get Records, compare End Date to TODAY() and TODAY() + 60.
Account Type = "Customer" AND Account Created Date = this week AND Onboarding_Sent__c = FALSE. Build the "this week" range the same way, using a formula resource.
Case Status = "Closed" AND Case Closed Date = this quarter AND Case Type = "Regulatory". Quarterly ranges typically need two formula resources — one for the start date, one for the end date.
Invoice_Due_Date__c < TODAY() AND Payment_Status__c = "Unpaid" AND Days_Overdue__c > 7. Custom formula fields on the Opportunity translate directly into Get Records conditions.
Account Type = "Customer" AND Account Status = "Active" AND Annual_Statement_Sent__c = FALSE. A checkbox field prevents the same account from receiving duplicate statements if the Flow runs more than once.
Flow-based generation vs batch jobs — which to use?
There are two related but distinct approaches for generating documents against a set of records defined by report-style filters: a Flow with Get Records (this guide) and a one-time Batch Document Job. Both end up generating one document per matching record, but they serve different needs:
| Feature | Flow with Get Records | Batch Document Job |
|---|---|---|
| Primary use case | Ad hoc or recurring generation defined by Flow logic | One-time or occasional bulk generation directly from a report |
| Scheduling | Can run on-demand or on a schedule (via a Scheduled Flow) | Manual trigger only |
| Record source | Get Records conditions you build to match your report | The Salesforce report directly |
| Additional automation | Can chain other Flow actions before/after generation | Generation only |
| Best for | Workflows where generation is one step among several | Large one-off runs (500+ records) straight from a report |
For a very large, one-time run straight off a report — with no other automation needed — a Batch Document Job is usually simpler to set up. For recurring workflows, or when generation needs to happen alongside other automation steps, build it as a Flow using the approach in this guide.
Best practices
Compare the Get Records count in Flow Builder's Debug view against the report's row count before letting the Flow run for real. A misconfigured filter can lead to hundreds of unintended documents.
Add a checkbox field (e.g. Invoice_Sent__c) to your Get Records filter — retrieve only where the field is FALSE, then update it to TRUE after generation. This prevents duplicate document generation on re-runs.
Keep the Salesforce report you used to design the filters in a dedicated "Dochly Document Flows" report folder. When business rules change, update both the report and the Flow's Get Records conditions together so they don't drift apart.
Before running against the full record set, temporarily narrow the Get Records filter to 3–5 specific test records (e.g. by Record ID). Debug the Flow, verify the output, then widen the filter back to the full criteria for the real run.
Frequently asked questions
TODAY() and date-math (e.g. TODAY() - 30) and compare your date field against it in the Get Records filter. The formula re-evaluates every time the Flow runs, so a "contracts expiring in 60 days" condition automatically reflects the correct contracts each run without manual updates — the same behavior a report's relative date filter gives you, just built explicitly in the Flow.You can now turn any Salesforce report's filter logic into an automated Flow that generates documents for exactly the right records. Next in this series: How to generate a document from any Salesforce record with Dochly — how generation works across all standard and custom objects.
Not on AppExchange yet — contact us and we'll set you up