Can’t believe, it has been an year since I blogged!!!. So, I am back :).
Regular Expression or Regex is a sequence of characters that specifies a match pattern in text. Regex is very powerful though it is not so easy to understand. If you want to know more about Regex in BC world, Areopa webinar or BC Techdays video of David Feldhoff is a must watch.
This post is about the system app Regex. It provides a set of functions that are quite useful when working with text search and replace. If you have a pattern, validations for e-mail, url, phone no. etc. can be done with a single line of code. Four main methods offered by Regex app are IsMatch, Match, Replace and Split. These methods are available with different overloads.
Following Regex expression only extracts ‘date’ from a csv file. This screenshot from regex101.com shows how the matches look like. We do have ‘match’ and ‘group’ tables in regex system app that hold exactly the same data shown here for the below regular expression.

And here is my function:-
procedure ReadDataFromFile()
var
Matches: Record Matches;
FileManagement: Codeunit "File Management";
Regex: Codeunit Regex;
TempBlob: Codeunit "Temp Blob";
FileInStream: InStream;
FileLine: Text;
LineCount: Integer;
DateRegexLbl: Label '^([1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/[0-9]{4}', Locked = true;
begin
ClearSampleLine();
FileManagement.BLOBImportWithFilter(TempBlob, 'Choose file', '', 'All Files (*.*)|*.*', '*.*');
if not TempBlob.HasValue() then
exit;
TempBlob.CreateInStream(FileInStream);
while not FileInStream.EOS() do begin
LineCount += 1;
if LineCount = 50 then
break;
FileInStream.ReadText(FileLine);
Regex.Match(FileLine, DateRegexLbl, Matches);
if not Matches.IsEmpty() then
InsertIntoDemoLineRec(Matches, Regex);
end;
end;
This is how we can insert the extracted ‘matches’ into our table.
procedure InsertIntoDemoLineRec(var TempMatches: Record Matches temporary; var Regex: Codeunit Regex)
var
SampleLine: Record "Sample Line";
TempGroups: Record Groups temporary;
LineNo: Integer;
begin
if TempMatches.IsEmpty() then
exit;
if TempMatches.FindSet() then
repeat
RegEx.Groups(TempMatches, TempGroups);
if SampleLine.FindLast() then
LineNo := SampleLine."Line No." + 10000
else
LineNo := 10000;
SampleLine.Reset();
SampleLine.Init();
SampleLine."Line No." := LineNo;
SampleLine.Data1 := TempGroups.ReadValue();
SampleLine.Insert();
until TempMatches.Next() = 0;
end;
If we replace ‘DateRegexLabel’ in the above function with ([^,]*)\S
or (,|\r?\n|^)([^",\r\n]+|"(?:[^"]|"")*")?
we can loop through every single field in the csv file.
IsMatch function example that validates e-mail:-
procedure IsValidEmail(InputText: Text): Boolean;
var
Regex: Codeunit Regex;
begin
exit(Regex.IsMatch(InputText, '^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$'));
end;
Of course, you can write a better or more complex regular expression that includes more criteria:).
Replace function is used to replace all strings that match a specified regular expression with a specified replacement string.
procedure ReplaceDate()
var
SampleLine: Record "Sample Line";
Regex: Codeunit Regex;
DateRegexLbl: Label '^([1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/[0-9]{4}', Locked = true;
begin
if SampleLine.FindSet() then
repeat
SampleLine.Data2 := CopyStr(Regex.Replace(SampleLine.Data1, DateRegexLbl, Format(Today)), 1, 80);
SampleLine.Modify();
until SampleLine.Next() = 0;
end;
The following regular expression splits a text into smaller texts of size 60:-

Below function uses the same regex in Split function and returns the result as a list:-
procedure ParseText(InputText: Text): List of [Text]
var
Regex: Codeunit Regex;
TextArr: List of [Text];
RegExPattern: Text;
RegExPatternLbl: Label '([^\n]{1,%1})\s', Locked = true;
begin
RegExPattern := StrSubstNo(RegExPatternLbl, 60);
Regex.Split(InputText, RegExPattern, TextArr);
exit(TextArr);
end;
Regex app also provides ‘Escape’ and ‘Unescape’ methods which can be useful when working with Odata webservices though I haven’t tested.
That’s all for now :).
One thought on “Regex system app”