Figure 1. Bill of Materials example |
DDS for PARTS file
A R PARTS
A PART_ID 15A
A REQ_ID 15A
A REQ_QTY 15P 0
A K PART_ID
RPG prototype file BOM_PR
// Note the use of the library-qualified file in EXTNAME |
D partsDs_in E DS extname('DEVLIB/PARTS'
D : *INPUT)
D qualified
D template |
A |
D bom PR
D filename 21a const
D itemId like(partsDs_in.part_id)
D const
D quantity 10i 0 value options(*nopass)
D indentLen 10i 0 value options(*nopass)
RPG source file
/copy BOM_PR |
P bom B
// F-specs: Note
// - the use of files local to a subprocedure
// - the use of the STATIC keyword for outFile
// so the same file open is used for all calls
// - the use of the QUALIFIED keyword for inFile
// so the record format PARTS will be infile.parts
// - the use of the EXTDESC keyword to tell the
// compiler where to find the file at compile time
FoutFile o f 80 printer static |
B |
NF extfile('QSYSPRT')
F usropn |
FinFile if e k disk qualified
F extdesc('DEVLIB/PARTS')
F extfile(filename) |
C |
D bom PI
D filename 21a const
D itemId like(partsDs_in.part_id)
D const
D quantityParm 10i 0 value options(*nopass)
D indentLenParm...
D 10i 0 value options(*nopass)
D quantityParmNum...
D c 3
D indentLenParmNum...
D c 4 |
D outDs ds len(80) |
D |
D inDs ds likeDs(partsDS_in)
D closeOutfile s n inz(*off)
D indentLen s 10i 0 inz(0)
D quantity s 10i 0 inz(1) |
D indentVal s a len(80) varying inz(*blanks) |
E |
// This data structure "totals" is much larger than the
// former limit of 65535.
D totals ds qualified static
D numParts 10i 0 inz
// Array "info" has a dimension much higher than the former
// limit of 32767.
D info dim(100000)
D part like(partsDs_in.part_id)
D overlay(info:*next)
D quantity 10i 0 overlay(info:*next)
D ix s 10i 0
D qty_factor s 10i 0 inz(1)
/free
// Get the "quantity" from the parameter, if passed
if %parms >= quantityParmNum;
quantity = quantityParm;
endif;
// Get the "indentLen" from the parameter, if passed
if %parms >= indentLenParmNum;
indentLen = indentLenParm;
endif;
// Open the file if necessary
// (This is the initial call)
if not %open(outFile);
open outFile;
closeOutfile = *on;
// Since this is the initial call, write out
// the main part to have its bill-of-materials
// exploded
outDs = itemId + ' '
+ %char(quantity);
write outFile outDs;
// Increase the indent length for any required subparts
indentLen += 2;
// Initialize the totals data structure, in case
// this procedure has been run before
totals.numParts = 0;
endif;
// Set up the number of blanks for indentation
%len(indentVal) = indentLen;
// Find all other parts required for this part
// Note
// - the use of the qualified record format infile.parts
// - the use of the result data structure inDs
// - how using a qualified record format makes it
// easier to relate the %FOUND(filename) to the
// CHAIN operation to the record format |
chain itemId inFile.parts inDs;
if %found(inFile);
dow %status(inFile) = 0;
outDs = indentVal
+ inDs.req_id
+ %char(inDs.req_qty);
write outFile outDs;
// Call this procedure recursively to handle
// the items required by the required part
bom (filename : inDs.req_id
: inDS.req_qty * quantity: indentLen + 2);
reade itemId inFile.parts inDs;
enddo; | F |
else;
// This part doesn't require any other parts
// so just keep track of totals number needed
ix = %lookup(itemId : totals.part
: 1 : totals.numParts);
if ix = 0;
// We haven't seen this part before so add
// it to the totals array
totals.numParts += 1;
ix = totals.numParts;
totals.part(ix) = itemId;
totals.quantity(ix) = 0;
endif;
totals.quantity(ix) += quantity;
endif;
// If this is the controlling invocation of the
// subprocedure, print out the totals now
if closeOutfile;
outDs = '***** TOTALS *****';
write outFile outDs;
for ix = 1 to totals.numParts;
outDs = totals.part(ix) + ' '
+ %editc(totals.quantity(ix) : 'P');
write outFile outDs;
endfor;
close outFile;
endif;
/end-free
P bom E
Sample input
PART_ID REQ_ID REQ_QTY
FAUCET_001 HANDLE_002 2
CUPBOARD_007 HINGE_013 3
HANDLE_002 MECH_003 1
MECH_003 WASHER_009 4
MECH_003 SCREW_017 6
FAUCET_001 TAP_063 1
Sample output, for part FAUCET_001, quantity 3
FAUCET_001 3
HANDLE_002 2
MECH_003 1
WASHER_009 4
SCREW_017 6
TAP_063 1
***** TOTALS *****
WASHER_009 24
SCREW_017 36
TAP_063 3 |