I get a lot of questions from all my great viewers, and many of these questions turn into videos. This is one of them. In this video, I take a look at how we can use the List datatype to help us split strings in a controlled manner. Check it out:

In this video, Erik demonstrates a practical technique for splitting a long string of text into neatly formatted lines using Lists and TextBuilder in AL for Business Central. The approach leverages the Split function to break text into individual words, then reassembles them into lines that respect a maximum character width — all without breaking words in the middle.
The Problem
A common question Erik receives is: “I have a long string of text, and I need to break it down into multiple lines in a presentable way.” There are many ways to accomplish this — you could count ahead to a position and then walk backwards to find the nearest space, for example — but Erik wants to show a fun, readable approach using List operations in AL.
Setting Up the Text Source
First, we need some text to work with. Erik creates a simple helper procedure called GetText() that returns a long string — in this case, the product description from the Business Central Field Guide’s Amazon listing. This gives us a substantial block of text (305 words) to split.
procedure GetText(): Text
begin
exit('Updated for the 2022 wave to release a companion book for implementing Microsoft Dynamics 365 Business Central targeting end users...');
// (long text continues)
end;
Step 1: Split the Text into Words
The first step is to break the entire text into individual words using the Split function on the text, splitting on spaces. This returns a List of [Text] where each entry is a single word.
var
Words: List of [Text];
begin
Words := GetText().Split(' ');
// Words now contains 305 individual word entries
end;
After running this, the debugger confirms that the Words list contains 305 entries — each word from the original text as a separate list element.
Step 2: Reassemble Words into Lines
Now we need to reassemble those words into lines that don’t exceed a maximum character width. Erik uses a TextBuilder to efficiently construct each line inside a loop, and a second List of [Text] to collect the finished lines.
var
Words: List of [Text];
Lines: List of [Text];
Builder: TextBuilder;
WordPointer: Integer;
begin
Words := GetText().Split(' ');
for WordPointer := 1 to Words.Count() do begin
// Add a space before the next word if the line already has content
if Builder.Length() > 0 then
Builder.Append(' ');
// Append the current word
Builder.Append(Words.Get(WordPointer));
// If the line exceeds 80 characters, flush it to the Lines list
if Builder.Length() > 80 then begin
Lines.Add(Builder.ToText());
Clear(Builder);
end;
end;
// Don't forget to flush the last line!
if Builder.Length() > 0 then
Lines.Add(Builder.ToText());
Message('%1\\%2\\%3', Lines.Get(1), Lines.Get(2), Lines.Get(3));
end;
Key Points in the Logic
- Re-inserting spaces: The
Splitcommand removes all the spaces, so we need to add them back. Before appending each word, we check if the builder already has content (Builder.Length() > 0), and if so, we append a space first. - Line length check: After adding each word, we check if the builder’s length exceeds 80 characters. If it does, we flush the current builder content into the
Lineslist and clear the builder to start a new line. - Whole words only: Because we’re working with complete words rather than individual characters, we never break a word in the middle. The line might slightly exceed 80 characters (since we check after appending), but every word remains intact.
The “Last Line” Bug
Erik catches an important bug during the demo: the last line being built in the TextBuilder never gets flushed into the Lines list if it doesn’t exceed 80 characters. This is a classic off-by-one scenario in text processing. The fix is simple — after the loop ends, check if the builder still has content and add it:
// After the loop
if Builder.Length() > 0 then
Lines.Add(Builder.ToText());
After this fix, the debugger shows 22 properly formatted lines, with the last one being shorter since the text naturally ended before reaching 80 characters.
Handling Pre-existing Line Breaks
Erik also addresses a scenario where the original text might already contain line breaks that you want to preserve. The solution is to add an outer loop: first split the text on line feed characters to get “input lines,” then process each input line through the same word-splitting logic.
var
InputLines: List of [Text];
Words: List of [Text];
Lines: List of [Text];
Builder: TextBuilder;
InputLine: Text;
WordPointer: Integer;
LF: Char;
begin
LF := 10; // Line feed character
InputLines := GetText().Split(LF);
foreach InputLine in InputLines do begin
Words := InputLine.Split(' ');
for WordPointer := 1 to Words.Count() do begin
if Builder.Length() > 0 then
Builder.Append(' ');
Builder.Append(Words.Get(WordPointer));
if Builder.Length() > 80 then begin
Lines.Add(Builder.ToText());
Clear(Builder);
end;
end;
// Flush at end of each input line to preserve the original line break
if Builder.Length() > 0 then begin
Lines.Add(Builder.ToText());
Clear(Builder);
end;
end;
end;
This way, original line breaks in the source text are preserved, and each paragraph segment is independently word-wrapped at 80 characters.
A Note on Proportional Fonts
Erik points out one limitation of this character-counting approach: it assumes a monospaced font where every character has the same width. In reality, a “W” is much wider than an “i” in proportional fonts. Windows has APIs that can render text to a memory buffer with a specific font and measure the actual pixel width, but these aren’t readily exposed in AL’s .NET interop libraries. If you had access to such a function, you could replace the character count check with an actual width measurement for even more precise line breaking — but for most Business Central scenarios, character counting works well enough.
Summary
This technique demonstrates elegant “list gymnastics” in AL. Rather than manually walking through characters, finding spaces, and using substring operations, you:
- Split the text into a word list using
Split(' ') - Iterate through the words, building lines with a
TextBuilder - Flush each line into a result list when it exceeds your desired width
- Remember to flush the final line after the loop
The result is clean, readable code that works with whole words instead of individual characters — making both the code and the output easy to understand.