Select Page
Business Central Reports Made Simple: A Beginner’s Guide to Report Properties

January 21, 2026

If you’re new to Microsoft Dynamics 365 Business Central development, reports might seem confusing at first. Don’t worry! This guide will explain everything in simple terms, with easy-to-follow examples. By the end, you’ll understand how to work with report fields and how to customize existing reports.

What is a Report?

Think of a report as a document that shows business data – like an invoice, a customer list, or a sales summary. In Business Central, reports pull data from your database and display it in a nice format that users can read, print, or save.

Part 1: Understanding Report Fields

What Are Report Fields?

Report fields are like blank spaces on a form that get filled in with data. For example:

  • Customer Name (gets filled with “John Smith”)
  • Invoice Number (gets filled with “INV-001”)
  • Total Amount (gets filled with “$1,500.00”)

Creating a Simple Report Field

Here’s what a basic report field looks like:

Al
Column (CustomerName; Customer.Name)
{
}

Let’s break this down:

  • column = We’re creating a field
  • CustomerName = The name we give to this field
  • Customer.Name = Where the data comes from (the Customer table, Name field)

Important Field Properties (The Easy Ones)

1. Caption – Giving Your Field a Label

The Caption is like a label that tells users what the field shows.

Al
column (CustomerName; Customer.Name)
{
    Caption = 'Customer Name';
}

Simple rule: Always give your fields clear, easy-to-read captions.

2. DecimalPlaces – Controlling Decimal Numbers

This controls how many numbers appear after the decimal point.

Al
Column (Price; Item."Unit Price")
{
    DecimalPlaces = 2:2; // Shows exactly 2 decimals (like $10.50)
}

When to use:

  • Money amounts: Use 2:2 (shows $10.50, not $10.5)
  • Quantities: Use 0:2 (shows 5 or 5.25, but not 5.0000)

3. BlankZero – Hiding Zero Values

Sometimes you don’t want to show zero. This property hides zeros and shows blank instead.

Al
column (Discount; SalesLine."Discount %")
{
    BlankZero = true;  // If discount is 0%, shows nothing
}

Example:

  • Without BlankZero: Shows “0%” even when there’s no discount
  • With BlankZero: Shows nothing when there’s no discount (looks cleaner!)

Real Example: A Simple Invoice Report

Let’s create fields for a simple invoice:

Al
dataitem(SalesInvoice; "Sales Invoice Header")
{
    // Invoice Number
    column(InvoiceNo; "No.")
    {
        Caption = 'Invoice Number';
    }
    // Customer Name
    column(CustomerName; "Sell-to Customer Name")
    {
        Caption = 'Customer';
    }
    // Invoice Date
    column(InvoiceDate; "Posting Date")
    {
        Caption = 'Date';
    }
    // Total Amount
    Column (TotalAmount; "Amount Including VAT")
    {
        Caption = 'Total';
        DecimalPlaces = 2:2;
    }
}

What this does:

  1. Gets invoice data from the Sales Invoice table
  2. Shows the invoice number, customer name, date, and total
  3. Formats the total amount with 2 decimal places

Adding Calculations

You can also create fields that calculate values. Here’s a simple example:

Al
{
column(DiscountAmount; GetDiscountAmount())
    Caption = 'Discount';
    DecimalPlaces = 2:2;
}
// This function does the calculation
local procedure GetDiscountAmount(): Decimal
begin
    exit(SalesInvoice.Amount * SalesInvoice."Discount %" / 100);
end;

What this does:

  • Creates a field called DiscountAmount
  • Calculates the discount by multiplying Amount × Discount %
  • Shows the result with 2 decimal places

Part 2: Report Extensions (Customizing Existing Reports)

What Are Report Extensions?

Sometimes you need to add information to a report that already exists in Business Central. Instead of changing the original report (which could cause problems), you create an “extension” – think of it as adding extra pages to a book without changing the original pages.

Why Use Extensions?

The Problem:

  • Business Central comes with standard reports (like invoices)
  • You want to add your own fields (like “Account Manager”)
  • You can’t change Microsoft’s reports directly

The Solution:

  • Create a report extension
  • Add your custom fields
  • The original report stays safe, and you can upgrade Business Central without losing your changes

Creating Your First Report Extension

Here’s a simple example that adds a field to the Customer List report:

Al
reportextension 50100 "My Customer List Extension" extends "Customer - List"
{
    dataset
    {
        add(Customer)
        {
            column(AccountManager; Customer."Salesperson Code")
            {
                Caption = 'Account Manager';
            }
        }
    }
}

Let’s understand this step by step:

  1. reportextension 50100 = Creating an extension with ID 50100
  2. “My Customer List Extension” = Naming our extension
  3. extends “Customer – List” = Adding to the existing Customer List report
  4. add(Customer) = Adding to the Customer section
  5. column(AccountManager…) = Adding our new field

Result: The Customer List now shows an Account Manager column!

Adding Multiple Fields

Let’s add more information to a Sales Invoice:

Al
reportextension 50101 "Sales Invoice Extra Info" extends "Sales Invoice"
{
    dataset
    {
        add(Header)
        {
            // Add shipping method
            column(ShippingMethod; Header."Shipping Agent Code")
            {
                Caption = 'Shipping Method';
            }
            // Add payment terms
            column(PaymentTerms; Header."Payment Terms Code")
            {
                Caption = 'Payment Terms';
            }
            // Add a custom field
            column(ProjectCode; Header."Project Code")
            {
                Caption = 'Project';
            }
        }
    }
}

What this does:

  • Adds Shipping Method to the invoice
  • Adds Payment Terms to the invoice
  • Adds a Project Code field
  • All without touching the original Sales Invoice report!

Adding Options to Reports

Sometimes you want to give users choices before running a report. Here’s how:

Al
reportextension 50102 "Customer List Options" extends "Customer - List"
{
    requestpage
    {
        layout
        {
            addafter(Options)
            {
                // Add a checkbox
                field(ShowInactive; ShowInactive)
                {
                    ApplicationArea = All;
                    Caption = 'Show Inactive Customers';
                }
                // Add a number field
                field(MinimumBalance; MinimumBalance)
                {
                    ApplicationArea = All;
                    Caption = 'Minimum Balance to Show';
                }
            }
        }
    }
    var
        ShowInactive: Boolean;
        MinimumBalance: Decimal;
}

What this does:

  • Adds a checkbox: “Show Inactive Customers”
  • Adds a number field: “Minimum Balance to Show”
  • Users can check/uncheck or enter amounts before running the report

Calculating Values in Extensions

You can add calculated fields to existing reports:

Al
reportextension 50103 "Sales Order Calculations" extends "Sales Order"
{
    dataset
    {
        add(Header)
        {
            // Add calculated field
            column(DaysUntilDelivery; CalculateDaysUntilDelivery())
            {
                Caption = 'Days Until Delivery';
            }
        }
    }
    // The calculation
    local procedure CalculateDaysUntilDelivery(): Integer
    begin
        if Header."Requested Delivery Date" <> 0D then
            exit(Header."Requested Delivery Date" - Today)
        else
            exit(0);
    end;
}

What this does:

  • Adds a field showing days until delivery
  • Calculates: Delivery Date minus Today’s Date
  • Shows 0 if no delivery date is set

Simple Examples for Common Tasks

Example 1: Adding a Custom Message to an Invoice

Al
reportextension 50104 "Invoice Custom Message" extends "Sales Invoice"
{
    dataset
    {
        add(Header)
        {
            column(ThankYouMessage; GetThankYouMessage())
            {
                Caption = 'Thank You Message';
            }
        }
    }
    local procedure GetThankYouMessage(): Text
    begin
        exit('Thank you for your business! We appreciate your order.');
    end;
}

Example 2: Showing Customer’s Total Orders

al
reportextension 50105 "Customer Total Orders" extends "Customer - List"
{
    dataset
    {
        add(Customer)
        {
            column(TotalOrders; CalculateTotalOrders())
            {
                Caption = 'Total Orders';
                DecimalPlaces = 2:2;
            }
        }
    }
    local procedure CalculateTotalOrders(): Decimal
    var
        SalesInvoiceHeader: Record "Sales Invoice Header";
        Total: Decimal;
    begin
        Total := 0;
        SalesInvoiceHeader.SetRange("Sell-to Customer No.", Customer."No.");
        if SalesInvoiceHeader.FindSet() then
            repeat
                Total := Total + SalesInvoiceHeader."Amount Including VAT";
            until SalesInvoiceHeader.Next() = 0;
        exit(Total);
    end;
}

What this does:

  • Finds all invoices for the customer
  • Adds up all the invoice amounts
  • Shows the total

Example 3: Color-Coding Based on Values

Al
reportextension 50106 "Customer Credit Status" extends "Customer - List"
{
    dataset
    {
        add(Customer)
        {
            column(CreditStatus; GetCreditStatus())
            {
                Caption = 'Credit Status';
            }
        }
    }
    local procedure GetCreditStatus(): Text
    begin
        if Customer."Balance (LCY)" > Customer."Credit Limit (LCY)" then
            exit('⚠️ OVER LIMIT')
        else if Customer."Balance (LCY)" > (Customer."Credit Limit (LCY)" * 0.8) then
            exit('⚡ NEAR LIMIT')
        else
            exit('✓ OK');
    end;
}

What this does:

  • Checks customer’s balance vs credit limit
  • Shows warning symbols for customers near or over limit
  • Makes it easy to spot credit issues

Tips for Beginners

Tip 1: Start Simple

Don’t try to do everything at once. Start with:

  1. Adding one field
  2. Test it
  3. Then add more

Tip 2: Use Good Names

Al
// BAD - Unclear names
column(X1; Customer.Name)
column(Amt; Amount)
// GOOD - Clear names
column(CustomerName; Customer.Name)
column(TotalAmount; Amount)

Tip 3: Always Add Captions

Al
// BAD - No caption
column(CustomerName; Customer.Name)
{
}
// GOOD - Has caption
column(CustomerName; Customer.Name)
{
    Caption = 'Customer Name';
}

Tip 4: Format Money Properly

al
// For money, always use 2 decimal places
column(Price; Item."Unit Price")
{
    DecimalPlaces = 2:2;
}

Tip 5: Test Your Reports

  • Always run your report after making changes
  • Check if the data looks correct
  • Make sure calculations work properly

Common Mistakes to Avoid

Mistake 1: Forgetting DecimalPlaces

Al
// BAD - Might show $10.5000000
column(Price; Item."Unit Price")
{
}
// GOOD - Always shows $10.50
column(Price; Item."Unit Price")
{
    DecimalPlaces = 2:2;
}

Mistake 2: Not Testing with Real Data

  • Test your report with actual data
  • Check what happens with zero values
  • Try it with big numbers and small numbers

Mistake 3: Making Complex Calculations

Al
// BAD - Too complex, hard to debug
column(ComplexValue; ((Amount * Tax) + (Discount / 100)) - Fees)
// GOOD - Break it down
column(ComplexValue; CalculateComplexValue())
local procedure CalculateComplexValue(): Decimal
var
    Step1: Decimal;
    Step2: Decimal;
begin
    Step1 := Amount * Tax;
    Step2 := Discount / 100;
    exit((Step1 + Step2) - Fees);
end;

Quick Reference Guide

For Report Fields

PropertyWhat It DoesExample
CaptionLabels the fieldCaption = ‘Customer Name’;
DecimalPlacesControls decimalsDecimalPlaces = 2:2;
BlankZeroHides zerosBlankZero = true;

For Report Extensions

ActionCode PatternUse When
Add fieldadd(DataItem) { column(…) }Adding new data
Add optionsrequestpage { layout { field(…) } }User needs choices
Calculatelocal procedure Name(): DecimalNeed to compute values

Your First Complete Report Extension

Here’s everything together in one working example:

Al
reportextension 50107 "My First Extension" extends "Customer - List"
{
    dataset
    {
        // Add new fields
        add(Customer)
        {
            // Show account manager
            column(AccountMgr; Customer."Salesperson Code")
            {
                Caption = 'Account Manager';
            }
            // Calculate and show customer value
            column(CustomerValue; GetCustomerValue())
            {
                Caption = 'Total Customer Value';
                DecimalPlaces = 2:2;
            }
            // Show credit status
            column(Status; GetCreditStatus())
            {
                Caption = 'Status';
            }
        }
    }
    // Add user options
    requestpage
    {
        layout
        {
            addafter(Options)
            {
                field(ShowDetails; ShowDetails)
                {
                    ApplicationArea = All;
                    Caption = 'Show Detailed Information';
                }
            }
        }
    }
    var
        ShowDetails: Boolean;
    // Calculate customer's total value
    local procedure GetCustomerValue(): Decimal
    var
        SalesInvoiceHeader: Record "Sales Invoice Header";
        TotalValue: Decimal;
    begin
        TotalValue := 0;
        SalesInvoiceHeader.SetRange("Sell-to Customer No.", Customer."No.");
        if SalesInvoiceHeader.FindSet() then
            repeat
                TotalValue := TotalValue + SalesInvoiceHeader."Amount Including VAT";
            until SalesInvoiceHeader.Next() = 0;
        exit(TotalValue);
    end;
    // Check credit status
    local procedure GetCreditStatus(): Text
    begin
        if Customer."Balance (LCY)" > Customer."Credit Limit (LCY)" then
            exit('Over Limit')
        else
            exit('OK');
    end;
}

What this complete example does:

  1. Extends the Customer List report
  2. Adds Account Manager field
  3. Calculates total customer value from all invoices
  4. Shows credit status (OK or Over Limit)
  5. Adds a checkbox option for users
  6. Formats all money values properly

Next Steps

Now that you understand the basics:

  1. Practice: Try adding fields to existing reports
  2. Experiment: Create simple calculations
  3. Ask Questions: Join Business Central communities
  4. Learn More: Read Microsoft’s documentation as you get comfortable

Summary: Key Points to Remember

  • Report Fields show data in your reports
  • Captions make fields easy to understand
  • DecimalPlaces format numbers properly (use 2:2 for money)
  • BlankZero hides zero values when you don’t need them
  • Report Extensions let you customize reports safely
  • Add fields with add(DataItem) { column(…) }
  • Add options with requestpage { layout {…} }
  • Always test your changes with real data

Conclusion

Congratulations! You now know the basics of working with Business Central reports. Start small, practice often, and don’t be afraid to experiment. Every expert developer started exactly where you are now.

Remember: The best way to learn is by doing. Pick a simple report and try adding one field. Once that works, add another. Before you know it, you’ll be creating complex, professional reports!