Skip to content

What's inside 4,759 RDLC reports

RDLC reports print the invoices, statements and lists of a great many .NET applications, and ReportViewer, which renders them, stays on .NET Framework. Anyone moving such an application to .NET 8, 9 or 10 has to ask what their reports are made of, and what it takes to move them. To answer that with more than guesses, we collected RDLC files from public GitHub repositories: 4,759 reports from 1,415 .NET projects, looked inside every one, and ran each through our converter. This is what they contain. (We also collected 1,230 reports from Business Central extensions, which we leave aside here.)

Most reports are the documents you would expect: a table of rows, grouped, with totals, a header on every page and a logo.

In the report Share of reports
A table, list or tablix 86%
Report parameters 56%
A page header 55%
Rows grouped, with group headers or totals 44%
An image (a logo, mostly: 29% embed one) 35%
More than one dataset 26%
A chart 13%
A subreport 11%
A matrix (a cross-tab, with column groups) 5%
Custom code (Visual Basic in the report) 6%

Three in five use a report definition schema from before 2016: half are written in the RDL 2008 schema that Visual Studio 2010 introduced, 4% in RDL 2010, and 7% are still RDL 2005 files. The other 39% use the 2016 schema of today’s RDLC designer, so they were created or saved recently: these applications are maintained, not abandoned.

Expressions are simple, and a few are hard

Section titled “Expressions are simple, and a few are hard”

A report has a median of 15 expressions, and nine in ten have fewer than 45. The same few functions carry most of them:

  • Sum in 44% of reports, and page numbers (Globals!PageNumber) in 34%;
  • IIf, for a colour or a blank instead of zero, in 31%;
  • Format and its family (FormatNumber, FormatCurrency…) in 25%.

What is hard to move is rare: calls into custom code (3.5% of reports), the user’s name (User!UserID, 3%), references to other text boxes (ReportItems!, 1.4%), RunningValue (1.3%), Previous (0.6%) and Lookup (0.1%). Plan for them, but don’t let them decide the migration: they are a handful of reports in a hundred.

PDF has three standard font families built in, which match Arial, Times New Roman and Courier New. 44% of the reports name another font somewhere, which must then be embedded, or text measured with another font’s widths wraps differently:

Font Share of reports
Verdana 11%
Tahoma 9%
Calibri 5%
Segoe UI 3%
Arial Narrow 2%

Calibri, Cambria and Segoe UI have free fonts with the same metrics (Carlito, Caladea and Selawik), so text wraps as in the original. Verdana and Tahoma need their own files, if their licence allows embedding, or a substitute and a look at the layout.

In 31% of the reports, the body (the report’s content area) is wider than the page’s printable width: the page’s width less its margins. ReportViewer spreads such a report over extra pages when it exports to PDF, which is where the common complaint about blank pages in RDLC PDFs comes from. A migration is a good moment to fix it: narrow the body, or the margins.

We converted each report with tagua import, filled it with sample rows, laid it out and rendered it to PDF:

.NET reports
Convert and render without an error 4,757 of 4,759
Nothing to review 71%
One item to review, or none 85%
Five items or fewer 96%

“Nothing to review” means the converter left no placeholder, and its notes are only about fonts, layout and values the application passes in. The most common items left are tablixes with column groups that do not fit a cross-tab, subreports to convert along with the report, tables in a group that list all their dataset’s rows, and styles computed rather than chosen.

  • Most of the work is ordinary. Most reports are tables, groups, totals, page headers and logos, and those convert as they are.

  • Check the fonts early. Nearly half the reports need a font decision: embed it, or use a free one with the same metrics.

  • Find the hard reports first. Custom code, ReportItems!, Lookup and Previous sit in a few reports; list them before estimating the rest.

  • Measure your own. Your reports are the only sample that counts:

    Terminal window
    dotnet tool install --global Tagua.Cli
    tagua import Reports --out converted

    It converts every report in the folder and writes tagua-import-summary.md: how many need nothing reviewed, and what the others need, report by report.