Wednesday, May 19, 2021

Upper and Lower built in functions come to RPG

new rpg %upper and %lower bif

When I saw these mentioned in the list of new enhancements made to RPG in IBM i 7.2 TR and And 7.3 TR10 the word "Finally" escaped my lips. Now we have built in functions, BiF, that would allow us to easily convert upper case letters to lower case, and vice versa.

For years I have been able to convert the case of characters in CL:

  CHGVAR VAR(&STRING1) VALUE(%UPPER(&STRING1))

  CHGVAR VAR(&STRING2) VALUE(%LOWER(&STRING2))

And in SQL too:

VALUES (UPPER('Simon was here'),LOWER('AND HE WAS THERE TOO'))

But in RPG we had to use the Translate BIF, %XLATE:

01  **free
02  dcl-s String1 char(20) inz('Simon was here') ;
03  dcl-s String2 char(24) inz('áâãåæçèéêëìíîïñòóôõøùúûý') ;

04  dcl-c UpperCase 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ;
05  dcl-c LowerCase 'abcdefghijklmnopqrstuvwxyz' ;

06  String1 = %xlate(LowerCase:UpperCase:String1) ;
07  dsply ('RPG XLATE String1 = ' + String1) ;

08  String1 = %xlate(LowerCase:UpperCase:String2) ;
09  dsply ('RPG XLATE String2 = ' + String2) ;

Line 4 and 5: There were the characters %XLATE would use to convert from one case to another.

Line 6: Here is a simple translate as all the characters are in the range A-Z.

Line 7: This is more complicated as the characters all have accents, umlauts, circumflex, etc.

The results show that the A-Z characters were translate, but not the others:

DSPLY  RPG XLATE String1 = SIMON WAS HERE
DSPLY  RPG XLATE String2 = áâãåæçèéêëìíîïñòóôõøùúûý

In recent years I have been using the SQL UPPER and LOWER to do the conversions for me, as they will convert those characters with the accents, etc.

01  **free
02  dcl-s String1 char(20) inz('Simon was here') ;
03  dcl-s String2 char(24) inz('áâãåæçèéêëìíîïñòóôõøùúûý') ;

04  exec sql SET :String1 = UPPER(:String1) ;
05  dsply ('SQL Upper String1 = ' + String1) ;

06  exec sql SET :String2 = UPPER(:String2) ;
07  dsply ('SQL Upper String2 = ' + String2) ;

08  exec sql SET :String1 = LOWER(:String1) ;
09  dsply ('SQL Lower String1 = ' + String1) ;

Line 4, 6, and 8: The SQL SET operation allows me to perform the translation and place the result into a variable.

As the results show it does convert the characters with accents, etc.:

DSPLY  SQL Upper String1 = SIMON WAS HERE
DSPLY  SQL Upper String2 = ÁÂÃÅÆÇÈÉÊËÌÍÎÏÑÒÓÔÕØÙÚÛÝ
DSPLY  SQL Lower String1 = simon was here

The program below shows some good examples of what can be done with the new BiFs:

01  **free
02  dcl-s String1 char(20) inz('Simon was here') ;
03  dcl-s String2 char(24) inz('áâãåæçèéêëìíîïñòóôõøùúûý') ;

04  String1 = %upper(String1) ;
05  dsply ('#1 Upper String1 = ' + String1) ;

06  String1 = %lower(String1) ;
07  dsply ('#2 Lower String1 = ' + String1) ;

08  String2 = %upper(String2) ;
09  dsply ('#3 Upper String2 = ' + String2) ;

10  String2 = %lower(String2) ;
11  dsply ('#4 Lower String2 = ' + String2) ;

Nothing special here are I am just translating the strings to upper case, and then to lower case. For doing this the syntax is very simple, just the name of the BiF followed by the variable or string of characters I want to convert.

The results are what I am sure you expected:

DSPLY  #1 Upper String1 = SIMON WAS HERE
DSPLY  #2 Lower String1 = simon was here
DSPLY  #3 Upper String2 = ÁÂÃÅÆÇÈÉÊËÌÍÎÏÑÒÓÔÕØÙÚÛÝ
DSPLY  #4 Lower String2 = áâãåæçèéêëìíîïñòóôõøùúûý

The BiFs have a second parameter which tells the BiF where to start converting. In these examples I want to keep the first character upper case.

12  reset String1 ;

13  String1 = %upper(String1) ;
14  dsply ('#5 Upper = ' + String1) ;

15  String1 = %lower(String1:2) ;
16  dsply ('#6 Lower = ' + String1) ;

Line 12: The RESET operation code restores the value in the variable to be what it was at the start of the program.

Line 13: The characters in the variable are converted to upper case.

Line 15: By using the second parameter of the %LOWER BiF I am saying that the conversion should happen starting in the second place, leaving the first character unchanged.

The results are:

DSPLY  #5 Upper = SIMON WAS HERE
DSPLY  #6 Lower = Simon was here

There is a third parameter too. This is the length of the string to convert. In my example I only want to convert the first 10 characters:

17  String1 = %upper(String1:1:10) ;
18  dsply ('#7 Upper = ' + String1) ;

As you can see the first 10 characters are now upper case:

DSPLY  #7 Upper = SIMON WAS here

To prove that you can do the same, but the other way around:

19  reset String1 ;

20  String1 = %lower(String1) ;
21  dsply ('#8 Lower = ' + String1) ;

22  String1 = %upper(String1:2) ;
23  dsply ('#9 Upper = ' + String1) ;

24  String1 = %lower(String1:1:10) ;
25  dsply ('#10 Lower = ' + String1) ;

And the results are what I expected:

DSPLY  #8 Lower = simon was here
DSPLY  #9 Upper = sIMON WAS HERE
DSPLY  #10 Lower = simon was HERE

These are so simple to use it wonders why it took so long to make it into RPG.

Warning: To be able to use the %UPPER and %LOWER BiFs on other partitions they must have the run time PTF installed.

 

You can learn more about the %UPPER and %LOWER RPG BiF on the IBM website here.

 

This article was written for IBM i 7.4 TR4, and will work for 7.3 TR10 too.

6 comments:

  1. Now if only they combined the two into 1 BIF, made upper or lower a parameter and included sentence case as one of those parameters, then this would make it really useful IMO.

    Still, happy not to have to use %xlate any longer.

    ReplyDelete
  2. Great examples Simon. BIF”s are great tools.

    ReplyDelete
  3. Gustavo Valdes ChavanaDecember 6, 2021 at 2:04 PM

    Excelent technical information

    ReplyDelete
  4. I abandoned %xlate long ago and use sql values upper() lower(). Glad to see the new rpg bif to handle this.

    ReplyDelete
    Replies
    1. I was doing the same as you and using the SQL UPPER and LOWER.

      Delete
  5. Simon, thanks for another teaching moment. The %XLATE function is a very useful BIF. I have never used the %lower BIF. It’s Another useful BIF. It get better every release. Thanks for sharing.

    ReplyDelete

To prevent "comment spam" all comments are moderated.
Learn about this website's comments policy here.

Some people have reported that they cannot post a comment using certain computers and browsers. If this is you feel free to use the Contact Form to send me the comment and I will post it for you, please include the title of the post so I know which one to post the comment to.