You are currently on IBM Systems Media’s archival website. Click here to view our new website.


Tips and Tricks to Answer Reader Questions

IBM Systems Magazine, Business Systems edition Technical Editors Susan Gantner and Jon Paris are known experts in the System i world. They receive questions all the time from people just like you. In this article, they share a few…and provide the answers.


This month we're featuring a potpourri of short tips and techniques concerning RPG IV functions that are either misunderstood or underutilized. Our inspiration was the questions we’ve received in recent months and we hope our answers will save you some time and research in your own job.

Q: I need to convert a five-digit numeric value to a string so it can be incorporated into an XML document. %CHAR seemed the natural choice, but it strips off all leading zeros. I need the value 1 to be converted to "00001" but when I use %CHAR I get "1 " which is no good. I know I could use a type S field in a Data Structure but is there a better way?

A: There certainly is. As you’ve discovered, %CHAR is useful when you don't want the leading zeros, but useless when you do. The built-in function (BIF) that probably best fits your needs is %EDITC. This effectively works the same way as applying an edit code to a numeric field on a display screen or printer report. The edit code specified as the second parameter is applied to the numeric value specified in the first parameter and the edited string returned. To meet your requirements, we need to specify the edit code “X,” which will retain the leading zeros. The code would look like this:

charField = %EditC( numField: 'X');

In fact, you can do anything with %EditC that you can do with the edit codes used in DDS or RPG Output specifications. This includes the capability to specify check protection using the optional third parameter *ASTFILL, which would produce the result '****1' in our example.

If %EditC just doesn't give you enough flexibility, you can use the companion BIF %EDITW, which allows the application of an edit word to the numeric data.

Q: Is there an easy way to specify that I want to process a specific member in a file?

A: We’ve always been able to do this via the Override With Database File (OVRDBF) CL command, but we suspect you’re looking for something a little easier. The answer lies in the EXTFILE( ) and EXTMBR( ) file specification keywords that were introduced in V5R1. If the file you wish to open has the same name as that specified on the F-spec and can be found via the library list, then you need to use only the EXTMBR keyword. The keyword takes a single parameter, which can either be a literal naming the member you wish to open (e.g. EXTMBR('MEMBER1') ) or the name of a field in the program that contains the member name. It’s important to note that the actual member name must be in upper case and that, in the case of a field name, the field must be populated before the file is opened. This means that either a) The file must be specified as USROPN and the field populated before the OPEN is issued, or b) The field must either have an initialization value or be passed in either as a parameter or IMPORTed from another module. EXTMBR also allows for the special value *ALL to permit processing of all members.

The EXTFILE keyword goes one step further and lets you specify the name and library of the file to be opened. The name must be in the format LIBRARY/FILENAME and the library list (*LIBL) is used if no library name is supplied. Note that the special value *CURLIB can’t be used as the library name with this option. One important point to make here is that even if a literal is used for this value, a file with the name specified on the F-spec must still be available at compile time to supply the format of the file. The compiler won’t use the value in the literal. As you’ve probably guessed, the same rules that we described for EXTMBR regarding upper case and the value being set before the file is opened apply also to EXTFILE.

We’re sure you can see why we rarely bother with using the OVRDBF command anymore!



Q: Why do some Integrated Language Environment applications experience strange errors after the Reclaim Activation Group CL command RCLACTGRP(*ELIGIBLE) has been used to clean up their activation groups (AGs)?

A: The *ELIGIBLE option is probably one that IBM wishes it had never made available. But since they can't remove the option without breaking compatibility, these days they simply try to hide it. To see what we mean, prompt the RCLACTGRP command and then try to find *ELIGIBLE as an option.

They’ve hidden it in the text help because of the problems it can introduce when used in production code. *ELIGIBLE means reclaim every AG with no active call stack entries. There are two main problems with this. First, if you use service programs, then it’s highly likely that they have no current call stack entries when the command is issued. As a result if they are currently running in their own AG, the AG will disappear. But it’s also highly likely that one of your other programs has already linked to the service program and has pointers to one or more of its subprocedures. It has no way of knowing that the service program disappeared because an AG was reclaimed, so guess what happens the next time it tries to use the subprocedure. Yep, a pointer error!

The second problem with *ELIGIBLE is that it makes the assumption that your applications created all of the AGs in the job and that you know it’s OK to clean them all up. But sometimes the system needs to create an AG to perform some task you’ve requested. Such AGs will also frequently be reclaimed by the *ELIGIBLE option. This, in turn, can lead to some unexpected error messages later.

If you want to clean up AGs you’ve created, don't try to take the easy way out—reclaim them by name. The ONLY time you should ever use *ELIGIBLE is when you’re doing development and need to do a quick-and-dirty cleanup. NEVER use it in production.

Q: I have some big arrays in my program that get loaded as the program runs. I then need to sort these arrays before processing them at the end of the run. Usually the arrays are only partly full. I know I can speed up the lookup process by using %LOOKUP and specifying the number of records to search, but I can't see how to restrict the number of elements sorted by SORTA.

A: While SORTA might be the obvious place to look, you won't find the answer there. You can however achieve the desired result using the BIF %SUBARR in place of the array name when invoking SORTA. %SUBARR takes three parameters: the name of the array, the starting element (this would be 1 in the questioner’s case) and the number of elements to be used. So if we wanted to sort only the first 50 elements in the array MyArray, we would code it as:

SortA %SubArr( MyArray : 1 : 50 );

That's all there is to it. There's much more you can do with %SUBARR—including many of the tasks that used to be performed by MOVEA. But we’ll leave that for another day.

Hope you found something useful here. If you have questions of your own, just let us know.


Jon Paris is a technical editor with IBM Systems Magazine and co-owner of Partner400.

Susan Gantner is a technical editor with IBM Systems Magazine and co-owner of Partner400.



2019 Solutions Edition

A Comprehensive Online Buyer's Guide to Solutions, Services and Education.

New and Improved XML-INTO

Namespace support makes the opcode a viable option

Authenticating on the Web

The finer points of OpenRPGUI, Part 1

The Microphone is Open

Add your voice: Should IBM i include open-source RPG tools?

IBM Systems Magazine Subscribe Box Read Now Link Subscribe Now Link iPad App Google Play Store
IBMi News Sign Up Today! Past News Letters