ReportExtensions, it was supposed to be so good?

We all joined the choir praising ReportExtensions when we finally got that feature, but after a few versions with ReportExtension, many have realized that it’s not all rainbows and unicorns. There’s an issue when extending a lot of reports. Check out the video:

https://youtu.be/0TlsTVro84M

Report extensions in AL were supposed to make extending Business Central reports straightforward. In this video, Erik walks through a real-world scenario that reveals a frustrating truth: many existing reports — including those shipped by Microsoft — were never designed with extensibility in mind. What should be a simple task of adding a column to a sales invoice report turns into a dead end, forcing developers back to the old approach of copying entire reports.

The Promise vs. The Reality

Report extensions were introduced as a way to modify existing reports without copying them — a clean, upgrade-safe approach that fits the extension model of Business Central. In theory, if you need to add a field to a sales invoice report, you should be able to create a report extension, anchor to the appropriate data item, add your column, and update the layout. Simple.

But as Erik demonstrates, the reality is far more complicated. The root cause isn’t the report extension feature itself — it’s that too many reports still in circulation were designed decades ago, long before report extensions existed, and have never been redesigned to support them.

Walking Through the Problem

Erik sets up a straightforward task: add a new column to the sales lines on the Sales Invoice North America report. Let’s follow his attempt step by step.

Step 1: Create a Report Extension

The first step is natural — create a report extension and try to anchor to the sales invoice line data item:

reportextension 50100 "My Invoice" extends "Standard Sales - Invoice"
{
    dataset
    {
        // Try to add a column to the sales invoice line...
    }
}

You look for a data item to anchor to, and you find Sales Invoice Line — that looks like the right candidate.

Step 2: Discover the Data Item Is Useless

But when you press F12 to inspect the base report’s source code, you discover the problem. The Sales Invoice Line data item doesn’t directly feed the report layout. Instead, it runs through an OnAfterGetRecord trigger that populates a temporary tableTempSalesInvoiceLine. The actual data item is only used to build up this temporary buffer.

So adding a column to this data item via a report extension is meaningless — it will never appear in the output because the layout doesn’t consume data from this data item directly.

Step 3: Look for Alternatives

There’s another data item that actually feeds the layout, but it runs on the Integer table. It steps through the temporary table using the integer as a counter. The only field available on the Integer table is Number. There’s no way to add your custom field here.

The temporary record variable that holds the actual data (TempSalesInvoiceLine) is a local variable in the report — it is not accessible from a report extension. You simply cannot reach it.

Step 4: The Dead End

The only theoretical workaround using a report extension would be to create a mirror data structure — essentially rebuilding the temporary table population logic in parallel within your extension. This is absurd for what should be a trivial task.

The practical result? Developers end up doing exactly what they did before report extensions existed: copying the entire report and modifying the copy. At that point, adding the column is trivial — you have full access to the temp table variable and can add columns freely. But you’ve lost all the benefits of the extension model.

Why This Happens

The core issue is a design pattern that’s common in older Business Central reports:

  1. A data item reads from a real table (e.g., Sales Invoice Line)
  2. In the OnAfterGetRecord trigger, data is copied into a temporary table (which may also include assembly lines, comments, and other mixed content)
  3. A separate data item running on the Integer table iterates through the temporary table to produce the actual output

This pattern makes the original data item non-extendable because:

  • The temporary table variable is not exposed (not protected)
  • The Integer-based data item has no real record to anchor columns to
  • The actual data source used by the layout is completely hidden from extensions

What Should Change

Erik outlines several things that would fix this situation:

Expose Data Sources Used in Layouts

Any data source that is used in the column section of a report should be accessible from a report extension — either at creation time (for the report author to expose) or at consumption time (for the extension developer to use). If a temporary record variable drives the layout, it should be declared as protected so that report extensions can access it:

// In the base report, change from:
var
    TempSalesInvoiceLine: Record "Sales Invoice Line" temporary;

// To:
protected var
    TempSalesInvoiceLine: Record "Sales Invoice Line" temporary;

Simplify Report Data Structures

Instead of using the Integer table pattern, reports could run directly on the temporary record using the UseTemporary property on the data item. This would make the data item itself extendable while preserving the temporary table functionality.

Community Contributions to the Base App

Now that Microsoft allows community contributions to the base application source code, Erik suggests a collaborative effort: create static analysis tooling to identify all reports that use hidden temporary variables in their layouts, and systematically update them to be extension-friendly. This isn’t limited to Microsoft’s reports — it applies to ISV apps as well, especially those that predate report extensions.

The Impact on End Users

Erik mentions his Simple Object Designer tool, which allows end users to make basic report modifications. He maintains a list of “dirty” data items — ones that are simply not extendable. When a support request comes in asking to add a field to one of these reports, the answer is frustrating: “That report is not extendable. There’s nothing I can do.”

Shipping copies of other people’s reports is not a sustainable solution, and it defeats the entire purpose of the extension model.

Conclusion

Report extensions are a great feature in concept, but they’re only as useful as the reports they extend. When base reports use hidden temporary tables and Integer-based data items, the extension model breaks down completely. What should be a five-minute task — adding a single column to a sales invoice — becomes either impossible or requires copying the entire report.

The call to action is clear: report authors (Microsoft, ISVs, and the community alike) need to revisit their report designs and ensure that data sources used in layouts are accessible to extensions. Until that happens, report extensions will remain a promise that too often fails to deliver.