Codeunit 58 Filter Tokens Impl., source in 24
Source242526272829metadata in 24
src/System Application/App/Filter Tokens/src/FilterTokensImpl.Codeunit.al485 lines, Copyright (c) Microsoft Corporation. MIT
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace System.Text;
codeunit 58 "Filter Tokens Impl."
{
Access = Internal;
SingleInstance = true;
InherentEntitlements = X;
InherentPermissions = X;
var
FilterTokens: Codeunit "Filter Tokens";
FilterType: Option DateTime,Date,Time;
TodayTxt: Label 'TODAY', Comment = 'Must be uppercase';
WorkdateTxt: Label 'WORKDATE', Comment = 'Must be uppercase';
AlphabetTxt: Label 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', Comment = 'Uppercase - translate into entire alphabet.';
NowTxt: Label 'NOW', Comment = 'Must be uppercase.';
YesterdayTxt: Label 'YESTERDAY', Comment = 'Must be uppercase';
TomorrowTxt: Label 'TOMORROW', Comment = 'Must be uppercase';
WeekTxt: Label 'WEEK', Comment = 'Must be uppercase';
MonthTxt: Label 'MONTH', Comment = 'Must be uppercase';
QuarterTxt: Label 'QUARTER', Comment = 'Must be uppercase';
UserTxt: Label 'USER', Comment = 'Must be uppercase';
MeTxt: Label 'ME', Comment = 'Must be uppercase';
CompanyTxt: Label 'COMPANY', Comment = 'Must be uppercase';
procedure MakeDateFilter(var DateFilter: Text)
begin
if not (DateFilter = '''''') then
MakeFilterExpression(FilterType::Date, DateFilter);
end;
procedure MakeTimeFilter(var TimeFilter: Text)
begin
MakeFilterExpression(FilterType::Time, TimeFilter);
end;
procedure MakeDateTimeFilter(var DateTimeFilterText: Text)
var
FilterText: Text;
begin
FilterText := DateTimeFilterText;
MakeFilterExpression(FilterType::DateTime, FilterText);
DateTimeFilterText := CopyStr(FilterText, 1, MaxStrLen(DateTimeFilterText));
end;
procedure MakeTextFilter(var TextFilter: Text)
var
Position: Integer;
TextToken: Text;
Handled: Boolean;
begin
Position := 1;
GetPositionDifferentCharacter(' ', TextFilter, Position);
if FindText(TextToken, TextFilter, Position) then
case TextToken of
CopyStr('ME', 1, StrLen(TextToken)), CopyStr(MeTxt, 1, StrLen(TextToken)):
TextFilter := UserId();
CopyStr('USER', 1, StrLen(TextToken)), CopyStr(UserTxt, 1, StrLen(TextToken)):
TextFilter := UserId();
CopyStr('COMPANY', 1, StrLen(TextToken)), CopyStr(CompanyTxt, 1, StrLen(TextToken)):
TextFilter := CompanyName();
else
FilterTokens.OnResolveTextFilterToken(TextToken, TextFilter, Handled);
end;
end;
local procedure MakeFilterExpression(TypeOfFilter: Option; var FilterText: Text)
var
Head: Text;
Tail: Text;
Position: Integer;
Length: Integer;
begin
FilterText := DelChr(FilterText, '<>'); // Removes all trailing and leading spaces
Position := 1;
Length := StrLen(FilterText);
while Length <> 0 do begin
GetPositionDifferentCharacter(' |()', FilterText, Position);
if Position > 1 then begin
Head := Head + CopyStr(FilterText, 1, Position - 1);
FilterText := CopyStr(FilterText, Position);
Position := 1;
Length := StrLen(FilterText);
end;
if Length <> 0 then begin
ReadUntilCharacter('|()', FilterText, Position);
if Position > 1 then begin
Tail := CopyStr(FilterText, Position);
FilterText := CopyStr(FilterText, 1, Position - 1);
ResolveFilter(TypeOfFilter, FilterText);
Evaluate(Head, Head + FilterText);
FilterText := Tail;
Position := 1;
Length := StrLen(FilterText);
end;
end;
end;
FilterText := Head;
end;
local procedure ResolveFilter(TypeOfFilter: Option; var "Filter": Text)
begin
case TypeOfFilter of
FilterType::DateTime:
ResolveDateTimeFilter(Filter);
FilterType::Date:
ResolveDateFilter(Filter);
FilterType::Time:
ResolveTimeFilter(Filter);
end;
end;
local procedure ResolveDateTimeFilter(var DateTimeFilter: Text)
var
DateTimeFilter1: DateTime;
DateTimeFilter2: DateTime;
DateFilter1: Date;
DateFilter2: Date;
TimeFilter1: Time;
TimeFilter2: Time;
RangeStartPosition: Integer;
begin
RangeStartPosition := StrPos(DateTimeFilter, '..');
if RangeStartPosition = 0 then begin
// If DateTimeFilter is not a range
if not ExtractDateAndTimeFilter(DateTimeFilter, DateFilter1, TimeFilter1) or (DateFilter1 = 0D) then
exit;
if TimeFilter1 = 0T then begin
DateTimeFilter := Format(CreateDateTime(DateFilter1, 000000T)) + '..' + Format(CreateDateTime(DateFilter1, 235959.995T));
exit;
end;
DateTimeFilter := Format(CreateDateTime(DateFilter1, TimeFilter1));
exit;
end;
if not ExtractDateAndTimeFilter(CopyStr(DateTimeFilter, 1, RangeStartPosition - 1), DateFilter1, TimeFilter1) then
exit;
if not ExtractDateAndTimeFilter(CopyStr(DateTimeFilter, RangeStartPosition + 2), DateFilter2, TimeFilter2) then
exit;
if (DateFilter1 = 0D) and (DateFilter2 = 0D) then
exit;
if DateFilter1 <> 0D then begin
if TimeFilter1 = 0T then
TimeFilter1 := 000000T;
DateTimeFilter1 := CreateDateTime(DateFilter1, TimeFilter1);
end;
if DateFilter2 <> 0D then begin
if TimeFilter2 = 0T then
TimeFilter2 := 235959T;
DateTimeFilter2 := CreateDateTime(DateFilter2, TimeFilter2);
end;
DateTimeFilter := Format(DateTimeFilter1) + '..' + Format(DateTimeFilter2);
end;
local procedure ExtractDateAndTimeFilter(DateTimeText: Text; var DateFilter: Date; var TimeFilter: Time): Boolean
var
DateText: Text;
TimeText: Text;
Position: Integer;
begin
if DateTimeText in [NowTxt, 'NOW'] then begin
DateFilter := Today();
TimeFilter := Time();
exit(true);
end;
DateFilter := 0D;
TimeFilter := 0T;
Position := 1;
GetPositionDifferentCharacter(' ', DateTimeText, Position);
ReadUntilCharacter(' ', DateTimeText, Position);
DateText := DelChr(CopyStr(DateTimeText, 1, Position - 1), '<>');
TimeText := DelChr(CopyStr(DateTimeText, Position), '<>');
if DateText = '' then
exit(true);
if not ResolveDateText(DateText, DateFilter) then
exit(false);
if (TimeText = '') or ResolveTimeText(TimeText, TimeFilter) then
exit(true);
exit(false);
end;
local procedure ResolveDateText(DateText: Text; var DateFilter: Date) Handled: Boolean
var
DateToken: Text;
Position: Integer;
begin
Position := 1;
GetPositionDifferentCharacter(' ', DateText, Position);
if not FindText(DateToken, DateText, Position) then begin
Handled := Evaluate(DateFilter, DateText);
exit(Handled);
end;
case DateToken of
CopyStr('TODAY', 1, StrLen(DateToken)), CopyStr(TodayTxt, 1, StrLen(DateToken)):
begin
DateFilter := Today();
exit(true);
end;
CopyStr('WORKDATE', 1, StrLen(DateToken)), CopyStr(WorkdateTxt, 1, StrLen(DateToken)):
begin
DateFilter := WorkDate();
exit(true);
end;
else begin
FilterTokens.OnResolveDateTokenFromDateTimeFilter(DateText, DateFilter, Handled);
exit(Handled);
end;
end;
end;
local procedure ResolveTimeText(TimeText: Text; var TimeFilter: Time) Handled: Boolean
var
TimeToken: Text;
Position: Integer;
Length: Integer;
begin
Position := 1;
Length := StrLen(TimeText);
GetPositionDifferentCharacter(' ', TimeText, Position);
if not FindText(TimeToken, TimeText, Position) then begin
Handled := Evaluate(TimeFilter, TimeText);
exit(Handled);
end;
FilterTokens.OnResolveTimeTokenFromDateTimeFilter(TimeText, TimeFilter, Handled);
if not Handled then begin
Position := Position + StrLen(TimeToken);
GetPositionDifferentCharacter(' ', TimeText, Position);
if Position > Length then begin
TimeFilter := 000000T + Round(Time() - 000000T, 1000);
exit(true);
end;
end;
exit(Handled);
end;
local procedure ResolveDateFilter(var DateFilter: Text)
var
Date1: Date;
Date2: Date;
Text1: Text;
Text2: Text;
RangeStartPosition: Integer;
DateFilterRangeLbl: Label '%1..%2', Comment = '%1 - From date, %2 - Till date', Locked = true;
begin
DateFilter := DelChr(DateFilter, '<>');
if DateFilter = '' then
exit;
RangeStartPosition := StrPos(DateFilter, '..');
if RangeStartPosition = 0 then begin
// If DateFilter is not a range
if not ResolveDateFilterToken(Date1, Date2, DateFilter) then
exit;
if Date1 = Date2 then
DateFilter := Format(Date1)
else
DateFilter := StrSubstNo(DateFilterRangeLbl, Date1, Date2);
exit;
end;
Text1 := CopyStr(DateFilter, 1, RangeStartPosition - 1);
if not ResolveDateFilterToken(Date1, Date2, Text1) then
exit;
Text1 := Format(Date1);
GetPositionDifferentCharacter('.', DateFilter, RangeStartPosition);
Text2 := CopyStr(DateFilter, RangeStartPosition);
if not ResolveDateFilterToken(Date1, Date2, Text2) then
exit;
Text2 := Format(Date2);
DateFilter := Text1 + '..' + Text2;
end;
local procedure ResolveDateFilterToken(var Date1: Date; var Date2: Date; DateFilter: Text) Handled: Boolean
var
DateFormula: DateFormula;
DateToken: Text;
RemainderOfText: Text;
Position: Integer;
begin
if Evaluate(DateFormula, DateFilter) then begin
// If DateFilter can be evaluated to a DateFormula
RemainderOfText := DateFilter;
DateFilter := '';
end else begin
ClearLastError(); // When Evaluate fails, the error shows up in 'View the last known error'
Position := StrPos(DateFilter, '+');
if Position = 0 then
Position := StrPos(DateFilter, '-');
if Position > 0 then begin
RemainderOfText := DelChr(CopyStr(DateFilter, Position));
if Evaluate(DateFormula, RemainderOfText) then
DateFilter := DelChr(CopyStr(DateFilter, 1, Position - 1))
else
RemainderOfText := '';
end;
end;
Position := 1;
FindText(DateToken, DateFilter, Position);
if DateToken <> '' then begin
FilterTokens.OnResolveDateFilterToken(DateFilter, Date1, Date2, Handled);
DateToken := UpperCase(DateFilter);
if not Handled then
case DateToken of
CopyStr('TODAY', 1, StrLen(DateToken)), CopyStr(TodayTxt, 1, StrLen(DateToken)):
Handled := FindDate(Today(), Date1, Date2);
CopyStr('WORKDATE', 1, StrLen(DateToken)), CopyStr(WorkdateTxt, 1, StrLen(DateToken)):
Handled := FindDate(WorkDate(), Date1, Date2);
CopyStr('NOW', 1, StrLen(DateToken)), CopyStr(NowTxt, 1, StrLen(DateToken)):
Handled := FindDate(DT2Date(CurrentDateTime()), Date1, Date2);
CopyStr('YESTERDAY', 1, StrLen(DateToken)), CopyStr(YesterdayTxt, 1, StrLen(DateToken)):
Handled := FindDate(CalcDate('<-1D>'), Date1, Date2);
CopyStr('TOMORROW', 1, StrLen(DateToken)), CopyStr(TomorrowTxt, 1, StrLen(DateToken)):
Handled := FindDate(CalcDate('<1D>'), Date1, Date2);
CopyStr('WEEK', 1, StrLen(DateToken)), CopyStr(WeekTxt, 1, StrLen(DateToken)):
Handled := FindDates('<-CW>', '<CW>', Date1, Date2);
CopyStr('MONTH', 1, StrLen(DateToken)), CopyStr(MonthTxt, 1, StrLen(DateToken)):
Handled := FindDates('<-CM>', '<CM>', Date1, Date2);
CopyStr('QUARTER', 1, StrLen(DateToken)), CopyStr(QuarterTxt, 1, StrLen(DateToken)):
Handled := FindDates('<-CQ>', '<CQ>', Date1, Date2);
end
end else
if (DateFilter <> '') and Evaluate(Date1, DateFilter) then begin
Date2 := Date1;
Handled := true;
end else
if RemainderOfText <> '' then begin
Date1 := Today();
Date2 := Date1;
Handled := true;
end else
Handled := false;
if Handled and (RemainderOfText <> '') then begin
Date1 := CalcDate(DateFormula, Date1);
Date2 := CalcDate(DateFormula, Date2);
end;
exit(Handled);
end;
local procedure ResolveTimeFilter(var TimeFilter: Text)
var
Time1: Time;
Time2: Time;
RangeStartPosition: Integer;
begin
RangeStartPosition := StrPos(TimeFilter, '..');
if RangeStartPosition = 0 then begin
// If TimeFilter is not a range
if not ResolveTimeToken(Time1, TimeFilter) then
exit;
if Time1 = 0T then
TimeFilter := Format(000000T) + '..' + Format(235959.995T);
TimeFilter := Format(Time1);
end else begin
// If TimeFilter is a range
if not ResolveTimeToken(Time1, CopyStr(TimeFilter, 1, RangeStartPosition - 1)) then
exit;
if not ResolveTimeToken(Time2, CopyStr(TimeFilter, RangeStartPosition + 2)) then
exit;
if Time1 = 0T then
Time1 := 000000T;
if Time2 = 0T then
Time2 := 235959T;
TimeFilter := Format(Time1) + '..' + Format(Time2);
end;
end;
local procedure ResolveTimeToken(var TimeFilter: Time; TimeToken: Text) Handled: Boolean
begin
TimeToken := DelChr(TimeToken); // Deletes all spaces in TimeToken
case UpperCase(TimeToken) of
NowTxt, 'NOW':
begin
TimeFilter := Time();
Handled := true;
end;
else
FilterTokens.OnResolveTimeFilterToken(TimeToken, TimeFilter, Handled);
end;
if not Handled then
Handled := Evaluate(TimeFilter, TimeToken);
end;
local procedure FindDate(Date1Input: Date; var Date1: Date; var Date2: Date): Boolean
begin
Date1 := Date1Input;
Date2 := Date1;
exit(true);
end;
local procedure FindDates(DateFormulaText1: Text; DateFormulaText2: Text; var Date1: Date; var Date2: Date): Boolean
var
DateFormula1: DateFormula;
DateFormula2: DateFormula;
begin
Evaluate(DateFormula1, DateFormulaText1);
Evaluate(DateFormula2, DateFormulaText2);
Date1 := CalcDate(DateFormula1);
Date2 := CalcDate(DateFormula2);
exit(true);
end;
procedure FindText(var PartOfText: Text; Text: Text; Position: Integer): Boolean
var
Position2: Integer;
begin
Position2 := Position;
GetPositionDifferentCharacter(AlphabetTxt, Text, Position);
if Position = Position2 then
exit(false);
PartOfText := UpperCase(CopyStr(Text, Position2, Position - Position2));
exit(true);
end;
procedure GetPositionDifferentCharacter(Character: Text[50]; Text: Text; var Position: Integer)
var
Length: Integer;
begin
Length := StrLen(Text);
while (Position <= Length) and (StrPos(Character, UpperCase(CopyStr(Text, Position, 1))) <> 0) do
Position := Position + 1;
end;
local procedure ReadUntilCharacter(Character: Text[50]; Text: Text; var Position: Integer)
var
Length: Integer;
begin
Length := StrLen(Text);
while (Position <= Length) and (StrPos(Character, UpperCase(CopyStr(Text, Position, 1))) = 0) do
Position := Position + 1;
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Filter Helper Triggers", MakeDateTimeFilter, '', false, false)]
local procedure DoMakeDateTimeFilter(var DateTimeFilterText: Text)
begin
MakeDateTimeFilter(DateTimeFilterText);
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Filter Helper Triggers", MakeDateFilter, '', false, false)]
local procedure DoMakeDateFilter(var DateFilterText: Text)
begin
MakeDateFilter(DateFilterText);
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Filter Helper Triggers", MakeTextFilter, '', false, false)]
local procedure DoMakeTextFilter(var TextFilterText: Text)
begin
MakeTextFilter(TextFilterText);
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Filter Helper Triggers", MakeCodeFilter, '', false, false)]
local procedure DoMakeCodeFilter(var TextFilterText: Text)
begin
MakeTextFilter(TextFilterText);
end;
[EventSubscriber(ObjectType::Codeunit, Codeunit::"Filter Helper Triggers", MakeTimeFilter, '', false, false)]
local procedure DoMakeTimeFilter(var TimeFilterText: Text)
begin
MakeTimeFilter(TimeFilterText);
end;
}