Help Center Document Generation Generate from Reports

How to Generate Documents from Salesforce Reports with Dochly

Updated July 2026 8 min read Document Generation
Salesforce reports are one of the best ways to see exactly which records should receive a document — combining multiple filters, cross-object conditions, and date-range logic. Dochly doesn't have a "Generate from Report" screen or a report-picker inside the app — instead, you build a Flow that queries the same records the report shows (using a Get Records element with equivalent filters) and feeds that record set into the Dochly Generate Document action. This guide covers how to go from "I have a report that shows the right records" to "Dochly generates a document for every one of them."

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.

Record-level generation

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.

Report-based generation (via Flow)

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.

Easy to translate

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.

Easy to translate

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.

Harder to translate

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.

Needs care

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.

Easy to translate

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.

Not applicable

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:

A

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.

B

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
C

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.

D

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

1

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.

2

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.

3

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.

4

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.

5

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.

6

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:

Monthly invoice run

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.

Renewal notices (60-day window)

Contract Status = "Active" AND End Date within the next 60 days. In Get Records, compare End Date to TODAY() and TODAY() + 60.

Onboarding packets (new customers)

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.

Compliance documentation (quarterly)

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.

Payment reminders (overdue)

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.

Annual account statements

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

Always verify the record count before running

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.

Use "prevention" fields in your Get Records filters

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 reference report up to date

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.

Test with a narrow filter first

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

Identify which report block represents the primary object your template is based on, and rebuild only that block's filter logic as your main Get Records element. If the document also needs data from the other block's object, add a second Get Records (or a relationship traversal) inside the loop to pull in that related data per record — Flow doesn't have a direct equivalent of a joined report's cross-block view.
Two likely causes: either the Get Records filters don't exactly match the report's filters (double-check every condition, especially relative-date formulas), or ten records failed generation inside the loop. Check Setup → Paused and Failed Flow Interviews and the fault path output for the specific error on each failed record — common causes include empty required merge fields or missing related records.
Yes. Build a formula resource in the Flow using 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.
No. Get Records only needs to return the record ID (which it always includes) — Dochly's Generate Document action looks up the full record data directly from Salesforce using that ID when generating each document. The Get Records fields are used for filtering and identifying records, not for populating the document. All merge fields are resolved directly from the Salesforce record at generation time.

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.

Dochly
Get Early Access Contact Us to Get Started with Dochly

Not on AppExchange yet — contact us and we'll set you up