DECSTR (like INCSTR but decreasing)

kriki
Member, Moderator Posts: 9,121
A function to descrease a string:
DecStr(IcodIncoming : Code[20];IintStep : Integer) OcodReturnCode : Code[20]
// DecStr //> 104
// Like the NAVISION INCSTR-function but DECREASING
// PARAMETERS:
// IcodIncoming : String to be decreased (if this string does not contain a number, an empty string is returned)
// IintStep : Decrement with this value (if it is negative, an empty string will be returned)
// (if it is 0, the value of "IcodIncoming" will be returned)
// RETURN-VALUE : decreased string
// in some cases, just exit
IF IintStep = 0 THEN
EXIT(IcodIncoming);
IF IintStep < 0 THEN
EXIT('');
IF IcodIncoming = '' THEN
EXIT('');
LcodAllowedChars := '1234567890';
LintLen := STRLEN(IcodIncoming);
LintStartOfNumericPart := LintLen;
// search the last not numeric character
WHILE (STRPOS(LcodAllowedChars,COPYSTR(IcodIncoming,LintStartOfNumericPart,1)) <> 0) DO
LintStartOfNumericPart -= 1;
// start of numeric part
LintStartOfNumericPart += 1;
IF LintStartOfNumericPart > LintLen THEN
EXIT(''); // no numeric part found at right end of the string
EVALUATE(Lint,COPYSTR(IcodIncoming,LintStartOfNumericPart));
Lint -= IintStep;
IF Lint < 0 THEN
ERROR(LtxcNegative,IcodIncoming,IintStep,Lint);
LcodAllowedChars := FORMAT(Lint);
OcodReturnCode :=
COPYSTR(IcodIncoming,1,LintStartOfNumericPart - 1) +
PADSTR('',LintLen - LintStartOfNumericPart - STRLEN(LcodAllowedChars) + 1,'0') +
LcodAllowedChars;
DecStr(IcodIncoming : Code[20];IintStep : Integer) OcodReturnCode : Code[20]
// DecStr //> 104
// Like the NAVISION INCSTR-function but DECREASING
// PARAMETERS:
// IcodIncoming : String to be decreased (if this string does not contain a number, an empty string is returned)
// IintStep : Decrement with this value (if it is negative, an empty string will be returned)
// (if it is 0, the value of "IcodIncoming" will be returned)
// RETURN-VALUE : decreased string
// in some cases, just exit
IF IintStep = 0 THEN
EXIT(IcodIncoming);
IF IintStep < 0 THEN
EXIT('');
IF IcodIncoming = '' THEN
EXIT('');
LcodAllowedChars := '1234567890';
LintLen := STRLEN(IcodIncoming);
LintStartOfNumericPart := LintLen;
// search the last not numeric character
WHILE (STRPOS(LcodAllowedChars,COPYSTR(IcodIncoming,LintStartOfNumericPart,1)) <> 0) DO
LintStartOfNumericPart -= 1;
// start of numeric part
LintStartOfNumericPart += 1;
IF LintStartOfNumericPart > LintLen THEN
EXIT(''); // no numeric part found at right end of the string
EVALUATE(Lint,COPYSTR(IcodIncoming,LintStartOfNumericPart));
Lint -= IintStep;
IF Lint < 0 THEN
ERROR(LtxcNegative,IcodIncoming,IintStep,Lint);
LcodAllowedChars := FORMAT(Lint);
OcodReturnCode :=
COPYSTR(IcodIncoming,1,LintStartOfNumericPart - 1) +
PADSTR('',LintLen - LintStartOfNumericPart - STRLEN(LcodAllowedChars) + 1,'0') +
LcodAllowedChars;
Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!
0
Comments
-
Here's another one
Will see if there are more than one numeric in the string passedOBJECT Codeunit 99998 Decrease Numeric in a String { OBJECT-PROPERTIES { Date=30/04/07; Time=13:30:25; Modified=Yes; Version List=Toolbox; } PROPERTIES { OnRun=BEGIN Text := 'Year2007 0000.txt'; Text2 := DecStr(Text); MESSAGE('text bef = %1\text aft = %2',Text,Text2); END; } CODE { VAR Text@1000000001 : Text[30]; Text2@1000000000 : Text[30]; Text000@1000000003 : TextConst 'ENU=" ABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()_+=|\{}[]"":;?/<>,."'; Text001@1000000004 : TextConst 'ENU=Decrement Numeric String %1 by 1,'; Text002@1000000005 : TextConst 'ENU=Change All Numeric Strings to 9''s'; Text003@1000000002 : TextConst 'ENU=0123456789'; Text004@1000000006 : TextConst 'ENU=%1 to %2,'; PROCEDURE DecStr@1000000000(PText@1000000000 : Text[1024]) : Text[1024]; VAR Idx@1000000009 : Integer; Idx2@1000000006 : Integer; Len@1000000005 : Integer; Position@1000000004 : Integer; Int@1000000003 : ARRAY [100] OF Integer; Int2@1000000017 : Integer; Pos@1000000002 : ARRAY [100] OF Integer; LText1@1000000001 : Text[1024]; Split@1000000007 : Boolean; SplitPos@1000000008 : ARRAY [100] OF Integer; StartSplitPos@1000000010 : ARRAY [100] OF Integer; EndSplitPos@1000000011 : ARRAY [100] OF Integer; Selection@1000000012 : Integer; SplitText@1000000013 : ARRAY [100] OF Text[30]; SplitText2@1000000016 : ARRAY [100] OF Text[30]; SplitLen@1000000014 : ARRAY [100] OF Integer; Text2@1000000021 : Text[1024]; Text3@1000000015 : Text[1024]; BEGIN CLEAR(Pos); CLEAR(StartSplitPos); CLEAR(EndSplitPos); Len := STRLEN(PText); Position := 0; Idx2 := 0; LText1 := DELCHR(UPPERCASE(PText),'=',Text000); // No Numeric found return same string IF STRLEN(LText1) <> 0 THEN BEGIN // Get position of all numerics FOR Idx := Len DOWNTO 1 DO IF EVALUATE(Int2,FORMAT(PText[Idx])) THEN BEGIN Position := Position + 1; Pos[Position] := Idx; END; // Get Starting Ending Positions and Length of the Numeric Strings FOR Idx := 1 TO Position DO IF (Pos[Idx] <> 0) THEN BEGIN IF NOT Split THEN BEGIN Idx2 := Idx2 + 1; EndSplitPos[Idx2] := Pos[Idx]; Split := TRUE; END; IF ((ABS(Pos[Idx + 1] - Pos[Idx])) > 1) THEN BEGIN Split := FALSE; StartSplitPos[Idx2] := Pos[Idx]; SplitLen[Idx2] := EndSplitPos[Idx2] - StartSplitPos[Idx2] + 1; END; END; IF StartSplitPos[Idx] = 0 THEN BEGIN StartSplitPos[Idx2] := Pos[Idx]; SplitLen[Idx2] := EndSplitPos[Idx2] - StartSplitPos[Idx2] + 1; END; // Create the replace strings Text3 := STRSUBSTNO(Text001,PText); FOR Idx := 1 TO Idx2 DO BEGIN Int[Idx] := StartSplitPos[Idx] - EndSplitPos[Idx + 1] - 1; Int2 := StartSplitPos[Idx] - Int[Idx]; SplitText[Idx] := COPYSTR(PText,Int2,SplitLen[Idx] + Int[Idx]); SplitText2[Idx] := COPYSTR(PText,StartSplitPos[Idx],SplitLen[Idx]); EVALUATE(Int[Idx],SplitText2[Idx]); Int[Idx] := Int[Idx] - 1; IF Int[Idx] <= 0 THEN BEGIN Text3 := Text3 + STRSUBSTNO(Text004,SplitText[Idx], PADSTR(DELCHR(SplitText2[Idx],'=',Text003),STRLEN(SplitText2[Idx]),'9')) END ELSE CASE TRUE OF STRLEN(SplitText2[Idx]) > STRLEN(FORMAT(Int[Idx])) : BEGIN Text2 := COPYSTR(SplitText2[Idx],1,STRLEN(SplitText2[Idx]) - (STRLEN(FORMAT(Int[Idx])) + 1)) + '0' + FORMAT(Int[Idx]); Text3 := Text3 + STRSUBSTNO(Text004,SplitText[Idx],Text2); END; ELSE Text3 := Text3 + STRSUBSTNO(Text004,SplitText[Idx],FORMAT(Int[Idx])); END; END; Text3 := Text3 + Text002; Selection := STRMENU(DELCHR(Text3,'>',','),2); IF Selection = 1 THEN BEGIN EVALUATE(Int[1],LText1); Int[1] := Int[1] - 1; LText1 := FORMAT(Int[1]); Idx2 := 0; // Replace numerics in passed string FOR Idx := STRLEN(LText1) DOWNTO 1 DO BEGIN Idx2 := Idx2 + 1; PText := INSSTR(DELSTR(PText,Pos[Idx2],1),FORMAT(LText1[Idx]),Pos[Idx2]); END; END ELSE BEGIN IF Selection > 0 THEN Selection := Selection - 1; IF Selection <> 0 THEN BEGIN IF Selection > Idx2 THEN FOR Idx := 1 TO Idx2 DO BEGIN LText1 := SplitText2[Idx]; FOR Int2 := 1 TO STRLEN(LText1) DO LText1[Int2] := '9'; PText := INSSTR(DELSTR(PText,StartSplitPos[Idx],SplitLen[Idx]), FORMAT(LText1),StartSplitPos[Idx]); END ELSE BEGIN IF Int[Selection] <= 0 THEN BEGIN LText1 := PADSTR(DELCHR(SplitText2[Selection],'=',Text003), STRLEN(SplitText2[Selection]),'9') END ELSE CASE TRUE OF STRLEN(SplitText2[Selection]) > STRLEN(FORMAT(Int[Selection])) : BEGIN LText1 := COPYSTR(SplitText2[Selection],1,STRLEN(SplitText2[Selection]) - (STRLEN(FORMAT(Int[Selection])) + 1)) + '0' + FORMAT(Int[Selection]); END; ELSE LText1 := FORMAT(Int[Selection]); END; PText := INSSTR(DELSTR(PText,StartSplitPos[Selection],SplitLen[Selection]), FORMAT(LText1),StartSplitPos[Selection]); END; END; END; END; EXIT(PText); END; BEGIN END. } }
0 -
Thanks a lot kirki, your function works perfectly.0
-
Thanks so much Kirki. Even after all those years, this is still really helpful.
Just to make your code even better, I implemented some code to handle values that already consist of only integers.
Add this code to the top of the Kirki's code, just above the Exit statements.
This will make sure that no errors occur when the codefield consists of only integers (for scenario's where you might not know that up-front).
The code will then just decrement the integer and exit with that value.
Create this local variable within the DecStr function:
>>
IntValue of type Integer
<<
Add the below code: >>
IF EVALUATE(IntValue, IcodIncoming) THEN BEGIN
IntValue -= IintStep;
OcodReturnCode := FORMAT(DecValueInt);
EXIT(OcodReturnCode);
END;
Just put all of it in a global function in a "Common Functions" Codeunit to use this whenever you need.0
Categories
- All Categories
- 73 General
- 73 Announcements
- 66.6K Microsoft Dynamics NAV
- 18.7K NAV Three Tier
- 38.4K NAV/Navision Classic Client
- 3.6K Navision Attain
- 2.4K Navision Financials
- 116 Navision DOS
- 851 Navision e-Commerce
- 1K NAV Tips & Tricks
- 772 NAV Dutch speaking only
- 617 NAV Courses, Exams & Certification
- 2K Microsoft Dynamics-Other
- 1.5K Dynamics AX
- 320 Dynamics CRM
- 111 Dynamics GP
- 10 Dynamics SL
- 1.5K Other
- 990 SQL General
- 383 SQL Performance
- 34 SQL Tips & Tricks
- 35 Design Patterns (General & Best Practices)
- 1 Architectural Patterns
- 10 Design Patterns
- 5 Implementation Patterns
- 53 3rd Party Products, Services & Events
- 1.6K General
- 1.1K General Chat
- 1.6K Website
- 83 Testing
- 1.2K Download section
- 23 How Tos section
- 252 Feedback
- 12 NAV TechDays 2013 Sessions
- 13 NAV TechDays 2012 Sessions