Boost Your AL Development with These Overlooked Business Central Functions

Share this Article
Business Central's AL language has several powerful functions that don't get much attention but can seriously improve your code's performance, readability, and reliability. Here's a complete list of 15 hidden gems, explained with examples.
1. SetLoadFields()
Loads only the required fields from SQL, improving performance.
Customer.SetLoadFields("No.", Name);
if Customer.FindSet() then
repeat
Message(Customer.Name);
until Customer.Next() = 0;
Why use it?
• Faster data retrieval
• Less memory consumption
• Recommended for large tables
2. IsTemporary()
Checks whether a record variable is temporary (in-memory) or a physical database record.
if SalesLine.IsTemporary() then
Message('Temporary Record');
Useful when writing generic codeunits that may receive either temporary or physical records, so you can branch logic accordingly (e.g., skip locking on temp records).
3. CopyFilters()
Copies all filters from one record/table to another in one line, instead of manually copying every SetRange/SetFilter.
SalesHeader.CopyFilters(Customer);Saves time and reduces code duplication, especially in reports and processing codeunits.
4. HasFilter()
Checks whether any filter is currently applied to the record.
if Customer.HasFilter() then
Message('Filters are applied');
Helpful as a safety check before processing records in batch jobs or reports, to avoid accidentally processing the entire table.
5. GetPosition() and SetPosition()
Save and restore the current position in a record set — like a bookmark.
Position := Customer.GetPosition();
// ... do other processing ...
Customer.SetPosition(Position);
Useful when navigating large datasets and you need to return to a specific record after temporarily moving elsewhere in the set.
6. Mark() and MarkedOnly()
Mark specific records for later processing without creating a temporary table.
if Customer.FindSet() then
repeat
if Customer.Balance > 1000 then
Customer.Mark(true);
until Customer.Next() = 0;
Customer.MarkedOnly(true);
if Customer.FindSet() then
repeat
Message(Customer.Name);
until Customer.Next() = 0;
Useful for batch operations where you want to filter records based on calculated/business logic rather than a simple field filter.
7. SetRecFilter()
Creates a filter based on the current record's primary key values, restricting the record set to just that one record.
Customer.SetRecFilter();Very useful in reports and processing codeunits when you want to pass a single-record context downstream.
8. FieldError()
Displays an error tied to a specific field, so the UI highlights that exact field for the user.
Customer.FieldError(Name, 'Customer name cannot be blank.');Gives a much better user experience than a generic Error() message, since the person immediately sees which field needs attention.
9. FilterGroup()
Separates internal (system-applied) filters from user-facing filters, so internal logic doesn't interfere with what the user sees or can modify.
Customer.FilterGroup(2);
Customer.SetRange("Global Dimension 1 Filter", 'RETAIL');
Customer.FilterGroup(0);Commonly used in list pages and permission-based filtering, where you don't want your internal filter visible or removable in the UI filter pane.
10. SetAutoCalcFields()
Automatically calculates FlowFields while looping, instead of calling CalcFields() manually on every iteration.
Customer.SetAutoCalcFields(Balance);
if Customer.FindSet() then
repeat
Message('%1', Customer.Balance);
until Customer.Next() = 0;Avoids repeated calls to CalcFields() and keeps loop code cleaner.
11. LockTable()
Explicitly locks a table before updating records, preventing conflicting simultaneous updates.
SalesHeader.LockTable();Useful when multiple users may update the same data simultaneously, especially in posting routines or number series handling, to avoid record locking errors mid-transaction.