Acumatica Report Designer is a desktop Windows application that produces the .rpx files behind every printable document in the system — invoices, statements, pick lists, financial reports. It's showing its age in places, but it remains the right tool whenever output has to be pixel-accurate, printable, or emailed as PDF. This is the full tour: schema, structure, expressions, deployment, and the sharp edges I've hit shipping dozens of these for clients.
When Report Designer is the right tool
My triage on any "we need a report" request: if it's a grid of data someone will filter and export, it's a Generic Inquiry, not a report. If it's an analytical financial statement built on account structures, it's ARM (Analytical Report Manager). Report Designer is for documents — anything with a header/detail layout, a company logo, page breaks in defined places, and a PDF destiny. Getting this triage right saves more time than any technique below.
The schema: DACs, not tables
When you build a report you load the schema from your instance (File > Build Schema), sign in, and pick DACs — not raw SQL tables. Joins are declared in the Relationships tab and filters in... well, the report's own filter expressions and parameters. Because you're going through DACs, the same attribute logic and tenant isolation apply as everywhere else. Two habits worth forming:
- Join as little as possible. Every DAC you add is joined into a single query. Reports that need data from unrelated sources are better served by a subreport than a five-way join that fans out.
- Use the report parameters to push filtering into the query. A parameter bound into a filter condition becomes a WHERE clause. A visibility expression that hides rows client-side still paid the cost of fetching them.
Anatomy of a report
A report is a stack of bands: Page Header, Report Header, Group Headers, Detail, Group Footers, Report Footer, Page Footer. The engine walks the joined result set row by row, firing group breaks when the group-by expression changes value. Almost every layout question resolves to "which band does this element belong in":
- Invoice totals go in a group footer keyed on the document, not the report footer.
- "Page X of Y" lives in the page footer using
[PageOf]. - Repeated column captions belong in the group header with "Repeat on each page" enabled, not the page header, if groups can span pages.
Expressions and formatting
Every text box takes an expression in a VB-flavored syntax. The functions you'll actually use: IIf(condition, a, b), Format(), Sum()/Count() with a running scope, and string concatenation with +. A representative example — showing a line discount only when present:
=IIf([ARTran.DiscPct] <> 0,
Format('{0:0.##}% discount applied', [ARTran.DiscPct]),
'')
For numbers and dates, prefer setting the element's Format property over baking formatting into the expression — the Format property respects the locale, which matters when the same invoice template serves entities in different countries. And use VisibleExpr on elements and whole sections for conditional layouts; it's cleaner than duplicating near-identical reports per scenario.
Variables and running totals
Report variables (defined on the report or group, with a ValueExpr) evaluate per row and can accumulate: a variable with ValueExpr = $V1 + [ARTran.CuryTranAmt] is a running total you control, useful when the built-in Sum scope doesn't match your grouping. Variables are also the standard trick for "carry forward" balances on statements — accumulate in the detail band, print in the group footer, reset on the group break.
Subreports
A subreport is a full report embedded by name, receiving parameter values from the parent row. Use them for genuinely separate datasets (remittance advice attached to a check run, serial numbers under a shipment line). Don't use them as a join substitute inside the detail band of a big report — each detail row spawns a subreport execution with its own query, and a 2,000-row report becomes 2,001 queries. That's the single most common cause of the slow reports I'm asked to fix.
If the subreport's data could have been a join or an additional grouped section in the parent, make it one. Reserve subreports for header/footer-level content or low-row-count sections.
Versioning and deployment
Reports upload through Site Map or the Report Definitions screen, but for anything client-facing I package the .rpx in a customization project so it deploys with everything else and is versioned in git alongside the code. One operational note: when you modify a stock report (say AR641000 invoice), copy it to a new number in the customer's range instead of editing in place — upgrades can overwrite stock reports, and your six hours of layout work with them.
Printing, emailing, and automation
Reports plug into notification templates (invoice emailed on release), into processing screens (print pick lists in batch), and into the REST API via the report endpoints for generating PDFs programmatically. If a document must be produced by an external system trigger, the pattern I use is a Business Event or API call that invokes the report and attaches the PDF to the record — keeping Acumatica the single source of the rendered document.
Wrapping up
Report Designer rewards respecting its model: pick it only for true documents, keep the join set small, put elements in the right band, push filters into parameters, and treat subreports as a scalpel rather than a join workaround. Package everything in a customization project, never edit stock reports in place, and the reporting layer becomes one of the most stable parts of your instance.
Independent software engineer in Nairobi specialising in Acumatica customisations, Laravel backends, and tax fiscalisation integrations across East and Southern Africa.