Options

DECSTR (like INCSTR but decreasing)

krikikriki Member, Moderator Posts: 9,096
edited 2009-07-29 in NAV Tips & Tricks
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;
Regards,Alain Krikilion
No PM,please use the forum. || May the <SOLVED>-attribute be in your title!


Comments

  • Options
    AlbertvhAlbertvh Member Posts: 516
    Here's another one
    Will see if there are more than one numeric in the string passed
    OBJECT 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.
      }
    }
    
    
  • Options
    DaniilConstantinDaniilConstantin Member Posts: 1
    Thanks a lot kirki, your function works perfectly.
  • Options
    rencolubbersrencolubbers Member Posts: 1
    edited 2020-04-30
    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.
Sign In or Register to comment.