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.
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.
ReplyDeleteStill, happy not to have to use %xlate any longer.
Great examples Simon. BIF”s are great tools.
ReplyDeleteExcelent technical information
ReplyDeleteI abandoned %xlate long ago and use sql values upper() lower(). Glad to see the new rpg bif to handle this.
ReplyDeleteI was doing the same as you and using the SQL UPPER and LOWER.
DeleteSimon, 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