Jet Reports Slow? Why Excel Freezes on Big Reports and How to Fix It

Jet Reports Slow? Why Excel Freezes on Big Reports and How to Fix It

Jet Reports slow or freezing Excel? Here is why cell-by-cell reports become thousands of requests, three fixes to try in Jet, and a faster approach.

Over

Thomas Werkhoven

Deel dit artikel

Over

Thomas Werkhoven

Deel dit artikel

Your month-end pack takes twenty minutes to run in Jet Reports, and while it runs, Excel is unusable. If that describes your Tuesday, this article is for you.

The short answer

Jet Reports is slow on large financial reports because every Jet function in the workbook is its own request to Business Central. A trial balance with 360 accounts across 12 periods is 4,320 requests before you add a second company. Multiply that by a handful of entities and one workbook is asking Business Central tens of thousands of questions, one at a time, while Excel waits.

You can trim that number with Jet's own tuning advice (covered below), but you cannot change the model. The fix that actually changes the experience is to pull sets rather than cells: one request returns every G/L entry in scope, and Excel does the arithmetic locally. In a recent demo, a report that ran about 20 minutes in Jet ran in about 20 seconds that way.

It is not your laptop

Earlier this month I sat in a demo with a US Business Central partner and two of their customer's controllers. Same firm, same laptops, same Business Central environment. Both of them described the same six months: Excel locking up, not crashing, just unresponsive, while a Jet report ran in the background. They had assumed it was a hardware problem and were about to ask IT for new machines.

It was not the machines. A faster processor makes each request return slightly sooner, but it does nothing about the number of requests. If your report needs 30,000 round trips to Business Central, a new laptop still needs 30,000 round trips. The wait moves from twenty minutes to eighteen and the lock stays.

Most online advice treats Jet slowness as a configuration problem, and sometimes it is; but when the report is a real monthly pack for a real group, the slowness is structural.

Why a Jet financial report becomes thousands of requests

Financial reports in Jet are built from functions. NL returns a list or table of records, NF returns a field value from a record, and GL returns a G/L balance for an account, period and set of filters. Table Builder, which is how most people start, inserts an NL("Table") function. Each of those functions, when the report runs, generally results in its own request to Business Central, which is why Jet's own performance guidance focuses on reducing the number of function calls.

A P&L or trial balance is almost always built cell by cell. Every intersection of an account and a period is a GL function with its own account filter and date filter. The workbook looks like a normal financial statement, and it behaves like a spreadsheet full of small database calls.

Jet's own "Improve Report Performance" documentation is candid about this. It states that NL(First) requests need a separate database request per call, that NL used for Rows or Columns has to scan the whole table to find unique values, and it recommends NF on cached record keys, reordering filters so the most restrictive comes first, and avoiding off-sheet references and volatile Excel functions. That advice is sound. It also confirms the model: the cost of a Jet report scales with the number of functions in it.

The arithmetic, worked

Take a mid-sized group and count. The table below is illustrative. Request counts assume one Jet function per account-and-period cell and one tab per company; real workbooks vary with layout, filters, and how many cells use NF versus GL.

[[TABLE_START]]

Report size (accounts x periods x companies) | Approximate Jet request count (one function per cell) | Exsion approach (one query per block) | Expected experience (illustrative)

120 accounts x 12 periods x 1 company | About 1,440 requests | 1 query on G/L Entry, filtered to the fiscal year | Jet: a coffee refill. Exsion: seconds.

360 accounts x 12 periods x 1 company | About 4,320 requests | 1 query | Jet: several minutes, Excel busy. Exsion: seconds, Excel responsive.

360 accounts x 12 periods x 5 companies | About 21,600 requests | 1 multi-company query (company column in the result) | Jet: the twenty-minute report. Exsion: tens of seconds.

360 accounts x 12 periods x 10 companies | About 43,200 requests | 1 multi-company query, or 1 per block if you prefer separate tabs | Jet: schedule it, walk away. Exsion: under a minute.

Add budget and prior year columns to the 5-company version | About 64,800 requests | 2 to 3 queries (actuals, budget from G/L Budget Entry, prior year) | Jet: often run overnight. Exsion: about a minute.

[[TABLE_END]]

The point is not the exact figures. The point is that the Jet column grows with every account, every period, every company, and every comparison column you add, while the Exsion column grows only with the number of logical blocks in the report. Adding a sixth company to a set-based query adds rows to the result, not requests.

Why Excel locks rather than crashes

The lock the two controllers described is the natural consequence of the model, not a bug. While an add-in is doing its work on the workbook, Excel is busy, and busy Excel does not paint the screen, accept clicks, or let you open another file. Nothing is broken. It is doing what it was asked to do, one request after another, and it comes back when it is finished. That is why the symptom is so consistent across machines.

Before you switch tools: three things to try in Jet

If you are on Jet and the report is slow, try these first. They come from InsightSoftware's own performance guidance for Jet Reports, and they help.

Use NF on cached record keys rather than repeated lookups. Where you already have a record key from an NL function, Jet's documentation recommends using NF against that key rather than issuing a fresh lookup. NL(First) calls are singled out as needing a database request per call, so replacing a column of them with NF on a key you already hold removes a share of the round trips.

Put the most restrictive filter first. Jet's guidance is to order filters so that the one eliminating the most records is evaluated first. On G/L Entry (table 17), that usually means the posting date range before the account range, because one fiscal year is a much smaller slice of a ten-year ledger than one account across all years. Reordering filters costs nothing.

Avoid volatile functions and off-sheet references. Volatile Excel functions such as NOW, TODAY, OFFSET and INDIRECT recalculate on every change, and Jet's documentation warns against them, along with references to cells on other sheets inside Jet function arguments. Replace a volatile date with a parameter cell, and keep the arguments a Jet function reads on the same sheet. Jet's documentation also notes that NL used for Rows or Columns has to scan the whole table for unique values, so if you use it to list every G/L account, consider a filtered NL(Table) or a static account list instead.

Applied together, these can cut run time noticeably. What they do not do is change the fact that a 360-account, 12-period, 5-company pack is still tens of thousands of requests. If that is the shape of your report, read on.

A different way to run the same report: pull sets, not cells

Exsion Reporting takes the opposite approach. Instead of asking Business Central for one balance per cell, a single query returns every G/L entry in scope, for example all of table 17 (G/L Entry) filtered to the fiscal year and the companies you care about. Excel does the arithmetic from there. A trial balance becomes a pivot or a SUMIFS over a result set that is already on your machine.

The request count collapses. A 5-company trial balance is one request, not 21,600. Adding budget is a second request against G/L Budget Entry. Adding prior year is a wider date filter on the first one, or a third request if you want it separate. The workbook grows by rows, not by round trips.

Two numbers from recent demos give a feel for the difference. A report that ran about 20 minutes in Jet Reports ran in about 20 seconds in Exsion (that is a specific case; the improvement will vary with the report, so read it as "up to" rather than "always"). And a plain pull of 700,000 rows from the G/L Entry table completed in under five seconds.

During both, Excel stayed responsive. You can keep typing in another sheet while the refresh runs. The coffee break is gone.

If the result set is large, the query can be sent straight into a PivotTable data model rather than onto a worksheet, which sidesteps Excel's 1,048,576-row worksheet limit entirely and keeps the file small. That is a separate topic and we covered it in detail in Business Central reporting past the Excel row limit.

What the same reports look like in Exsion

Read the third column of the table above again. The Jet column counts cells; the Exsion column counts blocks. A monthly pack for a group typically has three to six logical blocks (actuals, budget, prior year, perhaps a cash flow set and a dimension analysis), so the whole pack is three to six requests regardless of how many accounts or companies it covers.

Because the query definition is written into the workbook as a readable grid (table, companies, fields, filters, joins, and flowfield calculations), the person who receives the pack can see exactly what was pulled and, with a licence, change it. We wrote about why that matters in a Business Central Excel report should explain itself.

When you still want a formula in a cell

Set-based queries are the right tool for volume. They are not always the right tool for presentation. Sometimes you want a single account balance in a specific cell on a board-ready page, and you want it live.

Exsion has 16 built-in financial functions for that: account balance, account name, customer balance, dimension name and so on, each returning a single value live from Business Central. They use Business Central's own filter syntax, so a date range is written with two dots (01-01-26..31-03-26), wildcards use an asterisk, and a pipe means OR, exactly as you would type it in a Business Central filter field. Microsoft's reference for that syntax is here. Show Details on any of those cells opens Business Central filtered to precisely the account and posting date range the cell used.

Now the honest limit. Live cell formulas have a cost too, and performance starts to fall off at around 40,000 to 50,000 formula calculations in one workbook. A 360-account by 12-period trial balance is about 4,320 formulas, so a single-company statement is comfortably inside that. Ten companies on separate tabs, each built cell by cell, is not.

When a block approaches the limit, switch that block to a query and let a pivot or SUMIFS do the presentation. The rule of thumb we give customers is simple: sets for volume, formulas for presentation.

What changes in a normal month

The practical difference is not the headline number, it is what people do when a refresh takes seconds instead of minutes.

Excel stops locking, so the controller who used to start the pack and go to a meeting now refreshes it just before the meeting. Packs get refreshed before every review rather than once at close, because the cost of refreshing is nothing. When a finance director asks in the meeting why marketing is 8 percent over in company three, someone changes a dimension filter in the grid, refreshes, and answers while the question is still on the table. Nobody says "I will get back to you."

One of the customers at the September demo, a consulting firm logging about 1,500 time entries a week across its team, said that its resource, customer, project and ticket report was among the slowest it runs in Jet. That report is a join across four tables. In a set-based query it is one request with three joins, and the arithmetic (hours by resource by customer by week) happens in a pivot. We cover joins properly in the next post in this series, joining Business Central tables in Excel.

Nothing to install on a server

It is worth saying what this speed does not depend on. Exsion connects directly to Business Central through the API. There is no data warehouse, no Azure SQL replica, no virtual machine, no gateway and no scheduled load to keep running. The data you see is the data in Business Central at the moment you pressed refresh.

Permissions come along for free. Exsion inherits the Business Central user's permissions, so a controller who cannot see company five in Business Central cannot see it in Excel either, with no user setup on the Business Central side. Install is from AppSource via Extension Management, then the Excel add-in, a connection URL and a sign-in, about five minutes in timed demos.

Two steps may need an administrator: installing the add-in on a locked-down laptop, and first-time consent for the connection to Business Central. How the direct connection compares with copy-based architectures is the subject of the series pillar, Jet Reports alternatives for Business Central in 2026.

See your slowest report run

Take your single slowest Jet report and rebuild it. Install Exsion Reporting from AppSource, start the 30-day trial (the licence arrives by email within about a minute), and time it.

For teams coming from Jet Reports, we build the first report together at no charge. Exsion uses AI to extract the list of tables and fields the Jet workbook touches and rebuilds it as an Exsion grid, so you are comparing like with like rather than starting from a blank sheet. Pricing is on the pricing page, with no enterprise sales cycle in front of it.

If the twenty-minute report becomes a twenty-second one, you will know within the hour. If it does not, you have lost an afternoon and gained a benchmark.

Frequently asked questions

[[FAQ_START]]

Why is Jet Reports so slow on my financial reports? | Every Jet function in a workbook (GL, NL, NF) is its own request to Business Central, so a report built cell by cell scales with the number of cells. A 360-account by 12-period trial balance is about 4,320 requests for one company, and a five-company pack is over 20,000. The wait is a property of the report design rather than the laptop.

Why does Excel freeze while a Jet report runs? | Excel is busy while an add-in is working on the workbook, and busy Excel does not repaint or accept input. The report is not crashing; it is processing requests one after another and will return when it has finished. A faster machine shortens each request slightly but does not reduce the number of them.

How can I make Jet Reports faster without changing tools? | InsightSoftware's own performance guidance recommends using NF on cached record keys instead of repeated NL(First) lookups, ordering filters so the most restrictive comes first, and avoiding volatile Excel functions and off-sheet references inside Jet arguments. These changes can cut run time meaningfully. They do not change the fact that a large multi-company pack remains tens of thousands of requests.

How does Exsion avoid the same slowdown? | Exsion pulls sets rather than cells. One query returns every G/L entry in scope, for example the full fiscal year of table 17 for five companies, and Excel does the arithmetic locally in a pivot or SUMIFS. In a recent demo a report that ran about 20 minutes in Jet ran in about 20 seconds, and a 700,000-row pull from G/L Entry completed in under five seconds.

Does Exsion have a performance limit of its own? | Yes. Live cell formulas (Exsion's 16 financial functions) start to slow down at around 40,000 to 50,000 formula calculations in one workbook. When a block approaches that, switch it to a query and keep formulas for presentation cells only.

Can I build a Business Central trial balance in Excel without a data warehouse? | Yes. Exsion connects directly to Business Central through the API with no data warehouse, Azure SQL replica, VM or gateway, and inherits Business Central user permissions. The trial balance is a query on G/L Entry filtered to the period and companies you need, presented in a pivot or with SUMIFS.

[[FAQ_END]]