Wildcard matching strings in AL, the lazy way!

Matching strings can be a daunting task, and it might even involve RegEx or other exotic technologies. In this video, I explore how to use Business Central’s filter functionality to work on strings. Check out the video:

https://youtu.be/KOSRpgF2EUQ

In this video, Erik shares a clever AL hack for wildcard matching strings in Business Central — without writing your own parser or forcing users to learn regular expressions. The trick? Leverage Business Central’s built-in filter engine by using a temporary table with a single record.

The Problem: Matching Strings Against Patterns

Imagine you have a string value like 12345678 and you need to check whether it matches a user-provided pattern like *345*. Your first instinct might be to reach for regex — and while that works, it creates a terrible user experience. As Erik puts it, asking a Business Central user to write a valid regular expression is “a lousy user experience.”

So the question becomes: is there a matching syntax that Business Central users already know? The answer is yes — the filter syntax. Every Business Central user knows how to set filters on list pages. They understand wildcards like *, ranges like 100..200, and other filter expressions.

The Initial (Hard) Approach

Erik’s first thought was to parse the filter string manually — splitting it into parts, handling each wildcard segment, and implementing the matching logic from scratch:

Parts: list of [text];
// Split s2 into parts and do all the heavy lifting...

But then it dawned on him: Microsoft has already built a fully-featured filter parser. Why reinvent the wheel?

The Lazy (Brilliant) Approach: A Temporary Table

The trick is simple: create a temporary table with a single field, insert the value you want to test as the only record, apply the user’s filter expression, and then check if the record set is empty or not.

Step 1: Create a Minimal Temporary Table

Define a table with TableType = Temporary and just the fields you need for matching. You can add fields of different data types to support matching against text, decimals, dates, etc.:

table 50100 "StringMatch"
{
    TableType = Temporary;

    fields
    {
        field(1; Match; Text[2000])
        {

        }
        field(2; MatchDec; Decimal)
        { }
    }
}

Since this is a temporary table, you don’t need to worry about the primary key or schema changes — no data is persisted to the database.

Step 2: Insert the Test Value and Apply the Filter

The matching logic itself is remarkably concise. Insert your test value into the temporary table as a single record, set the filter using the user’s filter expression, and check if the filtered result is empty:

pageextension 50100 CustomerListExt extends "Customer List"
{
    trigger OnOpenPage();
    var
        s1, s2 : Text;
        Regex: Codeunit Regex;
        Parts: list of [text];
        mrec: Record StringMatch;
    begin
        // s1 := '12345678';
        // s2 := '*B3*';
        // mrec.Match := s1;
        mrec.MatchDec := 123.345;
        mrec.insert();
        mrec.setfilter(MatchDec, '120..125');
        message('Filter %1 in %2 = %3', s2, s1, not mrec.IsEmpty());
    end;
}

The key line is not mrec.IsEmpty(). If the record survives the filter, it’s a match. If the filtered set is empty, it’s not a match.

How It Works in Practice

Here are a few examples Erik walks through:

  • String 12345678 with filter *345* — Does the string contain “345”? Yes.
  • String 12345678 with filter *B3* — Does the string contain “B3”? No.
  • Decimal 123.345 with filter 120..125 — Is the value between 120 and 125? Yes.

Bonus: Built-In Filter Validation

One of the best side benefits of this approach is that you get free filter validation from Business Central. If a user enters an invalid filter expression, Business Central will throw an exception when you call SetFilter. This means you can validate user input without writing any validation logic yourself — just wrap the SetFilter call in error handling.

Extending the Pattern

Since the table is temporary, you can easily add fields for every data type you need to support — Text, Decimal, Integer, Date, DateTime, and so on. Each field gives you full filter-matching capability for that data type, all powered by Business Central’s built-in filter engine.

You could package this into a clean utility procedure that accepts a value and a filter string, and returns a boolean — making it reusable across your entire codebase.

Summary

This is one of those elegant “lazy” solutions that turns out to be the smartest approach:

  1. Create a temporary table with fields matching the data types you need to filter on.
  2. Insert the value you want to test as a single record.
  3. Apply the user’s filter expression using SetFilter.
  4. Check not IsEmpty() to determine if it’s a match.

You get the full power of Business Central’s filter language — wildcards, ranges, Boolean expressions, and more — without writing a single line of parsing code, and without asking users to learn regex. As Erik mentions, this technique is live in a published app on AppSource, so it’s proven in production. Sometimes the laziest solution really is the best one.