How to add a custom Transformation Rule

In this video, I show another example of what you can do with a single event. Adding a custom transformation rule for the Data Exchange Definitions.

https://youtu.be/L2qt0GKmiGk

In this video, Erik walks through how to create a custom transformation rule using AL in Business Central. He explains what transformation rules are, demonstrates how the built-in ones work, and then shows step-by-step how to subscribe to the right event to implement your own custom transformation logic. Along the way, he shares important best practices for writing event subscribers.

What Are Transformation Rules?

In Business Central, the Data Exchange Definition allows you to define file types for banks, imports, and exports. Sometimes a field in your data isn’t in the format you need, and that’s where transformation rules come in.

Business Central ships with several built-in transformation types:

  • Uppercase – converts text to all uppercase
  • Title Case – capitalizes the first letter of each word
  • Substring – extracts a portion of text based on position and length
  • Regular Expressions – pattern-based text matching and replacement
  • Custom – your own logic, implemented via an event subscriber

For example, the Substring transformation with a start position of 2 and a length of 2 applied to the word “hobart” would return “ob”. Simple and powerful.

But what happens when you select Custom as the transformation type and hit Update? You get nothing. There’s no field for specifying a codeunit number, no configuration UI — just a blank result. So how does it work?

Finding the Right Event

The answer, as you might expect, is that you need to subscribe to an event. Erik demonstrates a useful feature in Visual Studio Code: the AL: Find Events command from the command palette.

This command lists all events exposed in your symbols, and you can search through them. Searching for “transformation” reveals several candidates:

  • OnBeforeTextTransformation – in a report conflict package process (not what we want)
  • OnTransformation – from the Transformation Rule table (this is the one!)
  • OnCreateTransformationRules – not quite what we need either

To verify that OnTransformation is the correct event, you can press F12 on the event name to navigate to its publisher in the base application source. There you’ll find it inside a case statement on the transformation type — specifically, in the Custom branch, the event is raised. That confirms this is exactly the event we need.

Implementing the Custom Transformation

The event provides three parameters: the transformation code (which identifies which rule is being applied), the input text, and the output text (passed by reference). Importantly, the output text is pre-populated with the input value (since the base code sets NewValue := OldValue before raising the event), so you’ll want to clear it before writing your own result.

Here’s the complete implementation that reverses a string:

codeunit 50114 "Custom transformation"
{
    [EventSubscriber(ObjectType::Table, Database::"Transformation Rule", 'OnTransformation', '', false, false)]
    local procedure OnTransformation(TransformationCode: Code[20]; InputText: Text; var OutputText: Text);
    var
        i: Integer;
    begin
        case TransformationCode of
            'AAA':
                begin
                    OutputText := '';
                    for i := 1 to strlen(InputText) do
                        OutputText += InputText[strlen(InputText) - i + 1];
                end;
        end;
    end;
}

The logic is straightforward: loop through each character of the input text, but read from the end toward the beginning, appending each character to the output. So “hogart” becomes “tragoh” and “youtube” becomes “ebutuoy”.

Handling Multiple Custom Rules

Notice the case TransformationCode of structure. The transformation code is the only piece of information you receive to distinguish between different custom transformation rules. If you create multiple custom rules (e.g., ‘AAA’, ‘BBB’, etc.), you need to use this code to determine which logic to apply.

If a transformation code doesn’t match any of your cases, the subscriber simply does nothing — which is exactly the right behavior, as another subscriber (from another extension, perhaps) might handle that code instead.

Two Critical Rules for Event Subscribers

Erik emphasizes two essential rules that apply whenever you write event subscriber code:

Rule 1: You Are Never Alone

You cannot assume your subscriber is the only one listening to a given event. Other extensions — including AppSource apps — may subscribe to the same event and execute before or after your code. Your implementation needs to be resilient to this. In the example above, the case statement ensures we only act on our specific transformation code and leave others untouched.

Rule 2: Do Not Throw Errors

Unless it is absolutely, deliberately intentional, an event subscriber should never throw an error. Erik warns that there are a fair number of poorly written event subscribers — even on AppSource apps — that fail because of a missing setup record, or because they’re running in a company where the app wasn’t configured properly. A random subscriber failing can block the entire system and render it inoperable, especially if it’s subscribed to a critical event. Always write defensive code that handles edge cases gracefully.

The Future of Custom Transformations

Erik notes that the “Custom” transformation type pattern originated during the early days of events around NAV 2017. He suspects this pattern will eventually be replaced by an enum-based approach, where adding a new transformation rule means extending an enum. This would allow users to select a descriptively named rule from a dropdown rather than relying on an opaque “Custom” option that requires developer intervention. It’s a more intuitive and extensible pattern that aligns with modern AL development practices.

Summary

To create a custom transformation rule in Business Central:

  1. Create a new codeunit in your AL extension.
  2. Subscribe to the OnTransformation event on the Transformation Rule table.
  3. Use the TransformationCode parameter to identify which custom rule is being invoked.
  4. Clear the OutputText before setting your custom result.
  5. Use a case statement to handle multiple custom rules cleanly.
  6. Follow best practices: be resilient to other subscribers and avoid throwing errors.

The AL: Find Events command in VS Code is a powerful tool for discovering available events without having to dig through documentation, making it much easier to find the right integration point for your custom logic.