I have a couple of communications asking about how to "correctly" code a data structure to receive the data from and update a data area in the latest, all free, RPG. One of person even sent me their code, which I will be using for the basis for my examples.
While I am not sure if there is just one "correct" way to do this I will be giving my version of the following three scenarios:
- Receive data from a data area into a data structure
- Update the data area with data from a data structure
- Equivalent of UDS
I am not going to describe the basics of how to code Data Structures in free format in this post, as I covered this in Defining variables in RPG all free.
In this example the data area is called PPZ500D and I am creating it in QTEMP using the CRTDTAARA command:
CRTDTAARA DTAARA(QTEMP/PPZ500D) TYPE(*CHAR) LEN(100) + VALUE('abcdefghijklmnopqrstuvwxyz01234567890')
I can use the DSPDTAARA to display the contents of the data area:
And this is the command's output:
Data area . . . . . . . : PPZ500D Library . . . . . . . : QTEMP Type . . . . . . . . . : *CHAR Length . . . . . . . . : 100 Text . . . . . . . . . : Value Offset *...+....1....+....2....+....3....+....4....+....5 0 'abcdefghijklmnopqrstuvwxyz01234567890 ' 50 ' '
Receive data from a data area into a data structure
As you all know I like to things simple and uncomplicated, therefore, I would code the data structure like below:
01 dcl-ds PPZ500D dtaara len(100) ; 02 Char25 char(1) pos(25) ; 03 end-ds ; 04 in PPZ500D ;
On line 1 I use the data area name, PPZ500D, as the name of my data structure and define it 100 characters long.
I just need to code one subfield, Char25, that is one character (= 1A) and starts at position 25.
On line 3 I code the end-ds to mark the end of the data structure.
To receive the data from the data area I just use the IN operation code followed by the data structure name, which is the same as the data structure's name as I used its name as the data structure name.
I could have made it a bit more complicated by coding it as:
01 dcl-ds DataArea1 dtaara('QTEMP/PPZ500D') ; 02 Char100 char(100) ; 03 Char25 char(1) overlay(Char100:25) ; 04 end-ds ; 05 in DataArea1 ;
On line 1 I have decided not to use the data area's name as the data structure's name. Therefore, I have to give the name of the data structure in the dtaara keyword, I have also chosen to qualify it with the library name but I could have used '*LIBL' or just not give the library name for it to use the library list.
Update the data area with data from a data structure
This time I am only going to give an example with my preferred format of data structure. In this example I am going to increment part of the data area, positions 60-62, by one:
01 dcl-ds PPZ500D dtaara len(100) ; 02 Char60 char(3) pos(60) ; 03 end-ds ; 04 dcl-s Nbr60 uns(3) ; 05 in *lock PPZ500D ; 06 if ((Char60 = ' ') or (Char60 = '999')) ; 07 Nbr60 = 0 ; 08 else ; 09 Nbr60 = %dec(Char60:3:0) ; 10 endif ; 11 Nbr60 += 1 ; 12 Char60 = %editc(Nbr60:'X') ; 13 out PPZ500D ;
The only difference from the data structure in previous examples is that this time I have defined a alphanumeric subfield, Char60, which is 3 long. On line 6 I have defined a stand alone variable, Nbr60, which is an unsigned integer that is 3 long with (inferred) 0 decimal places. I have to admit that I am surprised that IBM insists that you have to have decimal places with integer and unsigned integer variables as, by their nature, they cannot have decimals.
On line 5 I "in" the contents of the data area. As I am going to update it I need to lock it, with *LOCK.
In lines 5 – 10 I convert the value in the alphanumeric subfield Char60 into a number in the unsigned integer Nbr60.
On line 11 I increment Nbr60 by 1. I use the %EDITC built in function with the edit code 'X' to convert Nbr60 to character on line 12. Then I update the data area using OUT on line 13.
After this program has completed if I look at the data structure I see that the 60-62 characters have been incremented.
Data area . . . . . . . : PPZ500D Library . . . . . . . : QTEMP Type . . . . . . . . . : *CHAR Length . . . . . . . . : 100 Text . . . . . . . . . : Value Offset *...+....1....+....2....+....3....+....4....+....5 0 'abcdefghijklmnopqrstuvwxyz01234567890 ' 50 ' 001 '
Equivalent of UDS
What is an "UDS" data area/structure?
D Data_Area_1 UDS 100 dtaara('MYLIB/TESTDA') D Char1 1 10
In fixed format RPG by defining a data structure as "UDS" the following happens without any additional programming:
- The data in the data area is brought into the data structure at program initialization, and the data area is locked. This makes it unavailable to other jobs.
- When the program ends the data in the data structure is used to update the data area, and the data area is unlocked/released.
You could use the UNLOCK operation code to unlock the data area during the program, but that runs counter to the whole idea of wanting the data area to be brought in at initialization and update at termination. I only use the "UDS" for the LDA, Local Data Area, as that is unique to each job.
In the example below I want to update the printer name in the first 10 characters of the LDA:
01 dcl-ds *n dtaara(*auto) ; 02 Printer char(10) pos(1) ; 03 end-ds ; 04 Printer = 'PRT02' ; 05 *inlr = *on ;
On line 1 by not giving the data structure a name, *N, and using *AUTO in the DTAARA keyword denotes that this data structure will get the data from LDA at program initialization. I define the subfield Printer on line 2.
I change the value of the subfield Printer on line 4, and when the program ends that value updates the LDA.
Data area . . . . . . . : *LDA Type . . . . . . . . . : *CHAR Length . . . . . . . . : 1024 Text . . . . . . . . . : *LDA for Job 999999/SIMONH/DSP001 Value Offset *...+....1....+....2....+....3....+....4....+....5 0 'PRT02 ' 50 ' '
You can learn more about these on the IBM website:
This article was written for IBM i 7.2, and it should work with 7.1 TR7 and greater too.