Lets start with a reasonably mixed RPGLE code example which is older style column based RPG400 for its variable definitions but then uplifts to RPGLE /FREE for its body code:
h dftactgrp(*no) actgrp(*caller) expropts(*resdecpos)
h datfmt(*iso) timfmt(*iso) option(*nodebugio) debug
//===============================================================
//
// application : Book To Bill.
//
// program id : BTB010R
//
// title : Book to Bill Selection.
//
// author : toby schofield (www.3psc.net)
//
// date : 02/12/2019
//
// version : v 1.0
//
// modifications
// mark by date
//
//===============================================================
fBTB010D cf e workstn infds(infds) infsr(*pssr)
// Fiscal Calendar.
fGPML01 if e k disk infsr(*PSSR) usropn
//===============================================================
// Like Record Formats
//===============================================================
d IPG100PM_i ds LikeRec(IPG100PM :*input )
//===============================================================
// define *entry plist parms
d EntryPList PR Extpgm('BTB010R')
d sParmFunctionKey...
d 3A
//===============================================================
d EntryPlist Pi
d sParmFunctionKey...
d 3A
//===============================================================
// define indicators
d IndicatorPtr s * inz(%addr(*IN))
d ds based(IndicatorPtr)
// variable definition
d lError s 1n inz('0')
d sFunction s 10 inz(*blanks)
d Space s 1A inz(' ')
d Comma s 1A inz(',')
d sSdatdsSave s inz(*blanks) like(sSdatds)
d sEdatdsSave s inz(*blanks) like(sEdatds)
d nAmthdsSave s inz(0) like(nAmthds)
//===============================================================
// Define LDA Variables
//===============================================================
d lda uds dtaara(*lda)
d nS6DateParm 1 6 0
d nE6DateParm 7 12 0
d nR6DateParm 13 18 0
d sMessageParm...
d 50 250
//===============================================================
// Date Conversion Variables.
//===============================================================
d nYears s 2 0 inz(28)
d nCompany s 2 0 inz(10)
d dCurrent s d
d sCurrentDate s 10 inz(*blanks)
d sCurrentYear s 2 inz(*blanks)
d nCurrentYear s 2 0 inz(0)
d nC6Date s 6 0 inz(0)
d dStart s d
d dEnd s d
d dRep s d
d dFiscalStart S d
d dFiscalEnd S d
//===============================================================
// command keys
d Cmd01 c const(x'31') Cmd-1
d Cmd02 c const(x'32') Cmd-2
d Cmd03 C const(x'33') Cmd-3
d Cmd04 c const(x'34') Cmd-4
d Cmd05 c const(x'35') Cmd-5
d Cmd06 c const(x'36') Cmd-6
d Cmd07 c const(x'37') Cmd-7
d Cmd08 c const(x'38') Cmd-8
d Cmd09 c const(x'39') Cmd-9
d Cmd10 c const(x'3A') Cmd-10
d Cmd11 c const(x'3B') Cmd-11
d Cmd12 c const(x'3C') Cmd-12
d Cmd13 c const(x'B1') Cmd-13
d Cmd14 c const(x'B2') Cmd-14
d Cmd15 c const(x'B3') Cmd-15
d Cmd16 c const(x'B4') Cmd-16
d Cmd17 c const(x'B5') Cmd-17
d Cmd18 c const(x'B6') Cmd-18
d Cmd19 c const(x'B7') Cmd-19
d Cmd20 c const(x'B8') Cmd-20
d Cmd21 c const(x'B9') Cmd-21
d Cmd22 c const(x'BA') Cmd-22
d Cmd23 c const(x'BB') Cmd-23
d Cmd24 c const(x'BC') Cmd-24
d EnterKey c const(x'F1') Enter
d RollUp c const(x'F5') Roll Up
d RollDown c const(x'F4') Roll Down
//===============================================================
d infds ds infds data structure
d $Choice 369 369
//===============================================================
d sds sds system DS
d $pgmid 1 10
d $wsid 244 253
d $user 254 263
//===============================================================
// main line
//===============================================================
/Free
Dow sFunction <> 'EXIT';
Exfmt F01;
Exsr #Keys;
If sFunction<>'EXIT';
Exsr #Validate;
Endif;
Enddo;
*inlr = *on; // --- program termination ---
//==============================================================
// # keys process function keys.
//==============================================================
Begsr #keys;
select;
when $Choice = Cmd03; // Exit.
sFunction = 'EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'F03';
when $Choice = EnterKey; // Submit.
Exsr #Validate;
If lError = *off;
Exsr #Submit;
sFunction='EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'ENT';
Endif;
when $Choice = Cmd18; // Interactive.
Exsr #Validate;
If lError = *off;
Exsr #Submit;
sFunction='EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'F18';
Endif;
endsl;
Endsr;
//==============================================================
// # Validate Validate Panel (F03).
//==============================================================
Begsr #Validate;
lError=*off;
Clear sStatds;
// dates must be valid.
monitor;
dStart = %date(sSdatds:*mdy);
on-error;
sStatds ='Start Date Invalid';
lError=*on;
endmon;
monitor;
dEnd = %date(sEdatds:*mdy);
on-error;
sStatds ='End Date Invalid';
lError=*on;
endmon;
If lError=*off;
// Add Months to Report End Date.
// Default Start Date + default Months (Report End Date)
dRep = dStart + %Months(nAmthds);
sRdatds = %Char(dRep:*mdy/);
Endif;
// If Dates are Valid Start must be < End.
If lError=*off;
If dEnd<dStart;
sStatds='End Date Greater Than Start Date';
lError=*on;
Endif;
Endif;
// if any field has changed - represent before submission.
If lError=*off;
If sSdatds <> sSdatdsSave Or
sEdatds <> sEdatdsSave Or
nAmthds <> nAmthdsSave;
sSdatdsSave = sSdatds;
sEdatdsSave = sEdatds;
nAmthdsSave = nAmthds;
lError=*on;
Endif;
Endif;
Endsr;
//==============================================================
// # Convert * ISO Date to BPCS Date
//==============================================================
Begsr #ISODateToBPCSDate;
// Start Date Short.
// subtract 28 Years before Conversion.
dStart = dStart - %Years(nYears);
// Convert to 6 Digit Numeric Date.
nS6DateParm = %Dec(dStart:*ymd);
// End Date Short.
// subtract 28 Years before Conversion.
dEnd = dEnd - %Years(nYears);
// Convert to 6 Digit Numeric Date.
nE6DateParm = %Dec(dEnd:*ymd);
// End Date (Report) Short.
// subtract 28 Years before Conversion.
dRep = dRep - %Years(nYears);
// Convert to 6 Digit Numeric Date.
nR6DateParm = %Dec(dRep:*ymd);
// Set up a Header Message for E Mail.
sMessageParm = (%Trim('Period:') +
Space +
%Editc(nFmthds:'4') +
%Trim(Comma) +
Space +
%Trim('Start Date:') +
Space +
%Trim(sSdatdsSave) +
%Trim(Comma) +
Space +
%Trim('End Date:') +
Space +
%Trim(sEdatdsSave) +
%Trim(Comma) +
Space +
%Trim('End Report Date:') +
Space +
%Trim(sRdatds));
Endsr;
//==============================================================
// # FisCalDefaults Get Fiscal Defaults from Calendar.
//==============================================================
Begsr #FisCalDefaults;
// Use Todays Date to find which month is Current.
dCurrent = %Date();
// subtract 28 Years before Conversion.
dCurrent = dCurrent - %Years(nYears);
// Place Date in String to retrieve Year.
sCurrentDate = %Char(dCurrent);
// Convert to 6 Digit Numeric Date.
nC6Date = %Dec(dCurrent:*ymd);
// Get Year and Make Numeric.
sCurrentYear = %Subst(sCurrentDate:3:2);
nCurrentYear = %Dec(sCurrentYear:2:0);
Setll ( nCompany
: nCurrentYear
)
GPML01;
Reade ( nCompany
: nCurrentYear
)
GPML01 IPG100PM_i;
Dow Not %Eof(GPML01);
// Find Calender entry where Current Date Falls between (or on)
// Period Start/End Dates.
If nC6Date >= IPG100PM_i.Pstart
And nC6Date <= IPG100PM_i.Pend;
// Get current Month From Fiscal Calendar.
nFmthds = IPG100PM_i.Period;
// Start Date.
dFiscalStart = %date(IPG100PM_i.Pstart:*ymd);
// ESnd Date.
dFiscalEnd = %date(IPG100PM_i.Pend:*ymd);
Leave;
Endif;
Reade ( nCompany
: nCurrentYear
)
GPML01 IPG100PM_i;
Enddo;
// Add 28 Years to Fiscal Dates.
dFiscalStart = dFiscalStart + %Years(nYears);
dFiscalEnd = dFiscalEnd + %Years(nYears);
Endsr;
//==============================================================
// # Submit Submit Dates to Batch Process.
//==============================================================
Begsr #Submit;
// Set Dates to relate to BPCS database.
Exsr #ISODateToBPCSDate;
Out LDA;
Endsr;
//==============================================================
// * INZSR Initialization.
//==============================================================
Begsr *INZSR;
// Fiscal Calendar.
If Not %Open(GPML01);
Open GPML01;
Endif;
// find Current Month Date Range from Fiscal Calendar
Exsr #FisCalDefaults;
// Fiscal Start Date.
sSdatds = %Char(dFiscalStart:*mdy/);
sSdatdsSave = sSdatds;
// Fiscal End Date.
sEdatds = %Char(dFiscalEnd:*mdy/);
sEdatdsSave = sEdatds;
// Default Add Months.
nAmthds = 6;
nAmthdsSave = nAmthds;
// Default todays Date (Start Date)
// Add Months to Report End Date.
// Default Fiscal Start Date + default Months (Report End Date)
dRep = dFiscalStart + %Months(nAmthds);
sRdatds = %Char(dRep:*mdy/);
Endsr;
//==============================================================
// * PSSR Dump Routine.
//==============================================================
Begsr *PSSR;
Dump;
Endsr;
/End-free
Step1 – Run code through the Projex4i Code Moderniser.
The Upgrade RPG Source command (UPGRPGSRC) will clean our code, converting it to fully /FREEFORMAT ILE RPG source. Obviously you can use whichever modernisation tool, or manual technique you wish to get your code uplifted to something like this:
**FREE
ctl-opt dftactgrp(*no) actgrp(*caller) expropts(*resdecpos) datfmt(*iso) timfmt(*iso) option(*nodebugio) debug;
// application : Book To Bill.
// program id : BTB010R
// title : Book to Bill Selection.
// author : toby schofield (www.3psc.net)
// date : 02/12/2019
// version : v 1.1
// modifications
// mark by date
// None Nick Litten 2020.02.12
dcl-f BTB010D workstn infds(infds) infsr(*pssr);
// Fiscal Calendar.
dcl-f GPML01 keyed infsr(*pssr) usropn;
dcl-ds IPG100PM_i likerec(ipg100pm :*input );
dcl-pr EntryPList extpgm('BTB010R');
*n char(3); // sParmFunctionKey
end-pr;
dcl-pi EntryPlist;
sParmFunctionKey char(3);
end-pi;
// define indicators
dcl-s IndicatorPtr pointer inz(%addr(*in));
dcl-ds *n based(indicatorptr) end-ds;
// variable definition
dcl-s lError ind inz('0');
dcl-s sFunction char(10) inz(*blanks);
dcl-s Space char(1) inz(' ');
dcl-s Comma char(1) inz(',');
dcl-s sSdatdsSave inz(*blanks) like(ssdatds);
dcl-s sEdatdsSave inz(*blanks) like(sedatds);
dcl-s nAmthdsSave inz(0) like(namthds);
// Define LDA Variables
dcl-ds lda dtaara(*auto: *lda);
nS6DateParm zoned(6) pos(1);
nE6DateParm zoned(6) pos(7);
nR6DateParm zoned(6) pos(13);
sMessageParm char(201) pos(50);
end-ds;
// Date Conversion Variables.
dcl-s nYears packed(2) inz(28);
dcl-s nCompany packed(2) inz(10);
dcl-s dCurrent date;
dcl-s sCurrentDate char(10) inz(*blanks);
dcl-s sCurrentYear char(2) inz(*blanks);
dcl-s nCurrentYear packed(2) inz(0);
dcl-s nC6Date packed(6) inz(0);
dcl-s dStart date;
dcl-s dEnd date;
dcl-s dRep date;
dcl-s dFiscalStart date;
dcl-s dFiscalEnd date;
// command keys
dcl-c Cmd01 const(x'31'); // Cmd-1
dcl-c Cmd02 const(x'32'); // Cmd-2
dcl-c Cmd03 const(x'33'); // Cmd-3
dcl-c Cmd04 const(x'34'); // Cmd-4
dcl-c Cmd05 const(x'35'); // Cmd-5
dcl-c Cmd06 const(x'36'); // Cmd-6
dcl-c Cmd07 const(x'37'); // Cmd-7
dcl-c Cmd08 const(x'38'); // Cmd-8
dcl-c Cmd09 const(x'39'); // Cmd-9
dcl-c Cmd10 const(x'3A'); // Cmd-10
dcl-c Cmd11 const(x'3B'); // Cmd-11
dcl-c Cmd12 const(x'3C'); // Cmd-12
dcl-c Cmd13 const(x'B1'); // Cmd-13
dcl-c Cmd14 const(x'B2'); // Cmd-14
dcl-c Cmd15 const(x'B3'); // Cmd-15
dcl-c Cmd16 const(x'B4'); // Cmd-16
dcl-c Cmd17 const(x'B5'); // Cmd-17
dcl-c Cmd18 const(x'B6'); // Cmd-18
dcl-c Cmd19 const(x'B7'); // Cmd-19
dcl-c Cmd20 const(x'B8'); // Cmd-20
dcl-c Cmd21 const(x'B9'); // Cmd-21
dcl-c Cmd22 const(x'BA'); // Cmd-22
dcl-c Cmd23 const(x'BB'); // Cmd-23
dcl-c Cmd24 const(x'BC'); // Cmd-24
dcl-c EnterKey const(x'F1'); // Enter
dcl-c RollUp const(x'F5'); // Roll Up
dcl-c RollDown const(x'F4'); // Roll Down
dcl-ds infds; // infds data structure
$Choice char(1) pos(369);
end-ds;
dcl-ds sds PSDS; // system DS
$pgmid char(10) pos(1);
$wsid char(10) pos(244);
$user char(10) pos(254);
end-ds;
// main line
Dow sFunction <> 'EXIT';
Exfmt F01;
Exsr #Keys;
If sFunction<>'EXIT';
Exsr #Validate;
Endif;
Enddo;
*inlr = *on; // --- program termination ---
//==============================================================
// # keys process function keys.
//==============================================================
Begsr #keys;
select;
when $Choice = Cmd03; // Exit.
sFunction = 'EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'F03';
when $Choice = EnterKey; // Submit.
Exsr #Validate;
If lError = *off;
Exsr #Submit;
sFunction='EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'ENT';
Endif;
when $Choice = Cmd18; // Interactive.
Exsr #Validate;
If lError = *off;
Exsr #Submit;
sFunction='EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'F18';
Endif;
endsl;
Endsr;
//==============================================================
// # Validate Validate Panel (F03).
//==============================================================
Begsr #Validate;
lError=*off;
Clear sStatds;
// dates must be valid.
monitor;
dStart = %date(sSdatds:*mdy);
on-error;
sStatds ='Start Date Invalid';
lError=*on;
endmon;
monitor;
dEnd = %date(sEdatds:*mdy);
on-error;
sStatds ='End Date Invalid';
lError=*on;
endmon;
If lError=*off;
// Add Months to Report End Date.
// Default Start Date + default Months (Report End Date)
dRep = dStart + %Months(nAmthds);
sRdatds = %Char(dRep:*mdy/);
Endif;
// If Dates are Valid Start must be < End.
If lError=*off;
If dEnd<dStart;
sStatds='End Date Greater Than Start Date';
lError=*on;
Endif;
Endif;
// if any field has changed - represent before submission.
If lError=*off;
If sSdatds <> sSdatdsSave Or
sEdatds <> sEdatdsSave Or
nAmthds <> nAmthdsSave;
sSdatdsSave = sSdatds;
sEdatdsSave = sEdatds;
nAmthdsSave = nAmthds;
lError=*on;
Endif;
Endif;
Endsr;
//==============================================================
// # Convert * ISO Date to BPCS Date
//==============================================================
Begsr #ISODateToBPCSDate;
// Start Date Short.
// subtract 28 Years before Conversion.
dStart = dStart - %Years(nYears);
// Convert to 6 Digit Numeric Date.
nS6DateParm = %Dec(dStart:*ymd);
// End Date Short.
// subtract 28 Years before Conversion.
dEnd = dEnd - %Years(nYears);
// Convert to 6 Digit Numeric Date.
nE6DateParm = %Dec(dEnd:*ymd);
// End Date (Report) Short.
// subtract 28 Years before Conversion.
dRep = dRep - %Years(nYears);
// Convert to 6 Digit Numeric Date.
nR6DateParm = %Dec(dRep:*ymd);
// Set up a Header Message for E Mail.
sMessageParm = (%Trim('Period:') +
Space +
%Editc(nFmthds:'4') +
%Trim(Comma) +
Space +
%Trim('Start Date:') +
Space +
%Trim(sSdatdsSave) +
%Trim(Comma) +
Space +
%Trim('End Date:') +
Space +
%Trim(sEdatdsSave) +
%Trim(Comma) +
Space +
%Trim('End Report Date:') +
Space +
%Trim(sRdatds));
Endsr;
//==============================================================
// # FisCalDefaults Get Fiscal Defaults from Calendar.
//==============================================================
Begsr #FisCalDefaults;
// Use Todays Date to find which month is Current.
dCurrent = %Date();
// subtract 28 Years before Conversion.
dCurrent = dCurrent - %Years(nYears);
// Place Date in String to retrieve Year.
sCurrentDate = %Char(dCurrent);
// Convert to 6 Digit Numeric Date.
nC6Date = %Dec(dCurrent:*ymd);
// Get Year and Make Numeric.
sCurrentYear = %Subst(sCurrentDate:3:2);
nCurrentYear = %Dec(sCurrentYear:2:0);
Setll ( nCompany
: nCurrentYear
)
GPML01;
Reade ( nCompany
: nCurrentYear
)
GPML01 IPG100PM_i;
Dow Not %Eof(GPML01);
// Find Calender entry where Current Date Falls between (or on)
// Period Start/End Dates.
If nC6Date >= IPG100PM_i.Pstart
And nC6Date <= IPG100PM_i.Pend;
// Get current Month From Fiscal Calendar.
nFmthds = IPG100PM_i.Period;
// Start Date.
dFiscalStart = %date(IPG100PM_i.Pstart:*ymd);
// ESnd Date.
dFiscalEnd = %date(IPG100PM_i.Pend:*ymd);
Leave;
Endif;
Reade ( nCompany
: nCurrentYear
)
GPML01 IPG100PM_i;
Enddo;
// Add 28 Years to Fiscal Dates.
dFiscalStart = dFiscalStart + %Years(nYears);
dFiscalEnd = dFiscalEnd + %Years(nYears);
Endsr;
//==============================================================
// # Submit Submit Dates to Batch Process.
//==============================================================
Begsr #Submit;
// Set Dates to relate to BPCS database.
Exsr #ISODateToBPCSDate;
Out LDA;
Endsr;
//==============================================================
// * INZSR Initialization.
//==============================================================
Begsr *INZSR;
// Fiscal Calendar.
If Not %Open(GPML01);
Open GPML01;
Endif;
// find Current Month Date Range from Fiscal Calendar
Exsr #FisCalDefaults;
// Fiscal Start Date.
sSdatds = %Char(dFiscalStart:*mdy/);
sSdatdsSave = sSdatds;
// Fiscal End Date.
sEdatds = %Char(dFiscalEnd:*mdy/);
sEdatdsSave = sEdatds;
// Default Add Months.
nAmthds = 6;
nAmthdsSave = nAmthds;
// Default todays Date (Start Date)
// Add Months to Report End Date.
// Default Fiscal Start Date + default Months (Report End Date)
dRep = dFiscalStart + %Months(nAmthds);
sRdatds = %Char(dRep:*mdy/);
Endsr;
//==============================================================
// * PSSR Dump Routine.
//==============================================================
Begsr *PSSR;
Dump;
Endsr;
So, now we have a fully free piece of code lets convert it to sub-procedures because… erm.. we can 🙂
Step2 – IBM RDi Extract Procedure Refactoring
Sadly, this new refactor procedure doesn’t (YET) handle conversion of subroutines into sub-procedures… but… we can select the subroutine body itself and convert to a sub-procedure and then just copy/paste/replace the EXSR statements with the sub-procedure calls instead:

Luckily, we can do it with a little manual copy/pasting. Simples.

This now gives us this subprocedure call:
// Process Function Keys
funcKeys();
// --------------------------------------------------
// Procedure name: funcKeys
// Purpose: Process Function Keys
// Returns:
// --------------------------------------------------
dcl-proc funcKeys;
// Local fields
select;
when $Choice = Cmd03; // Exit.
sFunction = 'EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'F03';
when $Choice = EnterKey; // Submit.
Exsr #Validate;
If lError = *off;
Exsr #Submit;
sFunction='EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'ENT';
Endif;
when $Choice = Cmd18; // Interactive.
Exsr #Validate;
If lError = *off;
Exsr #Submit;
sFunction='EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'F18';
Endif;
endsl;
return;
end-proc;
How cool is that?
So, if I scream through the code, slurping this cup of tepid coffee:

and it finally ends up looking this:
*FREE
ctl-opt dftactgrp(no) actgrp(caller) expropts(resdecpos)
datfmt(iso) timfmt(iso) option(*nodebugio) debug;
// application : Book To Bill.
// program id : BTB010R
// title : Book to Bill Selection.
// author : toby schofield (www.3psc.net)
// date : 02/12/2019
// version : v 1.2
// modifications
// mark by date
// None Nick Litten 2020.02.12
dcl-f BTB010D workstn infds(infds) infsr(*pssr);
// Fiscal Calendar.
dcl-f GPML01 keyed infsr(*pssr) usropn;
// Our Program *ENTRY point
dcl-pi *n;
sParmFunctionKey char(3);
end-pi;
dcl-ds IPG100PM_i likerec(ipg100pm :*input );
dcl-s IndicatorPtr pointer inz(%addr(*in));
dcl-ds *n based(indicatorptr) end-ds;
dcl-s lError ind inz('0');
dcl-s sFunction char(10) inz(blanks);
dcl-s Space char(1) inz(' ');
dcl-s Comma char(1) inz(',');
dcl-s sSdatdsSave inz(blanks) like(ssdatds);
dcl-s sEdatdsSave inz(*blanks) like(sedatds);
dcl-s nAmthdsSave inz(0) like(namthds);
dcl-ds lda dtaara(*auto: *lda);
nS6DateParm zoned(6) pos(1);
nE6DateParm zoned(6) pos(7);
nR6DateParm zoned(6) pos(13);
sMessageParm char(201) pos(50);
end-ds;
// Date Conversion Variables.
dcl-s nYears packed(2) inz(28)
dcl-s nCompany packed(2) inz(10);
dcl-s dCurrent date;
dcl-s sCurrentDate char(10) inz(blanks);
dcl-s sCurrentYear char(2) inz(blanks);
dcl-s nCurrentYear packed(2) inz(0);
dcl-s nC6Date packed(6) inz(0);
dcl-s dStart date;
dcl-s dEnd date;
dcl-s dRep date;
dcl-s dFiscalStart date;
dcl-s dFiscalEnd date;
// command keys
dcl-c Cmd01 const(x'31'); // Cmd-1
dcl-c Cmd02 const(x'32'); // Cmd-2
dcl-c Cmd03 const(x'33'); // Cmd-3
dcl-c Cmd04 const(x'34'); // Cmd-4
dcl-c Cmd05 const(x'35'); // Cmd-5
dcl-c Cmd06 const(x'36'); // Cmd-6
dcl-c Cmd07 const(x'37'); // Cmd-7
dcl-c Cmd08 const(x'38'); // Cmd-8
dcl-c Cmd09 const(x'39'); // Cmd-9
dcl-c Cmd10 const(x'3A'); // Cmd-10
dcl-c Cmd11 const(x'3B'); // Cmd-11
dcl-c Cmd12 const(x'3C'); // Cmd-12
dcl-c Cmd13 const(x'B1'); // Cmd-13
dcl-c Cmd14 const(x'B2'); // Cmd-14
dcl-c Cmd15 const(x'B3'); // Cmd-15
dcl-c Cmd16 const(x'B4'); // Cmd-16
dcl-c Cmd17 const(x'B5'); // Cmd-17
dcl-c Cmd18 const(x'B6'); // Cmd-18
dcl-c Cmd19 const(x'B7'); // Cmd-19
dcl-c Cmd20 const(x'B8'); // Cmd-20
dcl-c Cmd21 const(x'B9'); // Cmd-21
dcl-c Cmd22 const(x'BA'); // Cmd-22
dcl-c Cmd23 const(x'BB'); // Cmd-23
dcl-c Cmd24 const(x'BC'); // Cmd-24
dcl-c EnterKey const(x'F1'); // Enter
dcl-c RollUp const(x'F5'); // Roll Up
dcl-c RollDown const(x'F4'); // Roll Down
dcl-ds infds; // infds data structure
$Choice char(1) pos(369);
end-ds;
dcl-ds sds PSDS; // system DS
$pgmid char(10) pos(1);
$wsid char(10) pos(244);
$user char(10) pos(254);
end-ds;
/title ---------------- MAINLINE ------------------
// Initialise the Program variables
initialise();
Dow sFunction <> 'EXIT';
Exfmt F01;
// Process Function Keys
funcKeys();
If sFunction<>'EXIT';
// main code validation
validate();
Endif;
Enddo;
*inlr = *on; // --- program termination ---
// --------------------------------------------------
// * PSSR Dump Routine.
// --------------------------------------------------
Begsr *PSSR;
Dump;
Endsr;
// --------------------------------------------------
// Procedure name: funcKeys
// Purpose: Process Function Keys
// Returns:
// --------------------------------------------------
dcl-proc funcKeys;
select;
when $Choice = Cmd03; // Exit.
sFunction = 'EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'F03';
when $Choice = EnterKey; // Submit.
validate();
If lError = *off;
// Submit Submit Dates to Batch Process.
submit();
sFunction='EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'ENT';
Endif;
when $Choice = Cmd18; // Interactive.
validate();
If lError = *off;
// Submit Submit Dates to Batch Process.
submit();
sFunction='EXIT';
// Set External Function Parameter.
sParmFunctionKey = 'F18';
Endif;
endsl;
return;
end-proc;
// --------------------------------------------------
// Procedure name: validate
// Purpose: main code validation
// Returns:
// --------------------------------------------------
dcl-proc validate;
lError=*off;
Clear sStatds;
// dates must be valid.
monitor;
dStart = %date(sSdatds:mdy);
on-error;
sStatds ='Start Date Invalid';
lError=on;
endmon;
monitor;
dEnd = %date(sEdatds:mdy);
on-error;
sStatds ='End Date Invalid';
lError=on;
endmon;
If lError=off;
// Add Months to Report End Date.
// Default Start Date + default Months (Report End Date)
dRep = dStart + %Months(nAmthds); sRdatds = %Char(dRep:mdy/);
Endif;
// If Dates are Valid Start must be < End.
If lError=off; If dEndon;
Endif;
Endif;
// if any field has changed - represent before submission.
If lError=*off;
If sSdatds <> sSdatdsSave Or sEdatds <> sEdatdsSave Or nAmthds <> nAmthdsSave;
sSdatdsSave = sSdatds;
sEdatdsSave = sEdatds;
nAmthdsSave = nAmthds;
lError=*on; Endif;
Endif;
return;
end-proc;
// --------------------------------------------------
// Procedure name: convertISOdatetoBPCSDate
// Purpose: Start Date Short.
// Returns:
// --------------------------------------------------
dcl-proc convertISOdatetoBPCSDate;
// Start Date Short.
// subtract 28 Years before Conversion.
dStart = dStart - %Years(nYears);
// Convert to 6 Digit Numeric Date.
nS6DateParm = %Dec(dStart:*ymd);
// End Date Short.
// subtract 28 Years before Conversion.
dEnd = dEnd - %Years(nYears);
// Convert to 6 Digit Numeric Date.
nE6DateParm = %Dec(dEnd:*ymd);
// End Date (Report) Short.
// subtract 28 Years before Conversion.
dRep = dRep - %Years(nYears);
// Convert to 6 Digit Numeric Date.
nR6DateParm = %Dec(dRep:*ymd);
// Set up a Header Message for E Mail.
sMessageParm = (%Trim('Period:') +
Space +
%Editc(nFmthds:'4') +
%Trim(Comma) +
Space +
%Trim('Start Date:') +
Space +
%Trim(sSdatdsSave) +
%Trim(Comma) +
Space +
%Trim('End Date:') +
Space +
%Trim(sEdatdsSave) +
%Trim(Comma) +
Space +
%Trim('End Report Date:') +
Space +
%Trim(sRdatds));
return;
end-proc;
// --------------------------------------------------
// Procedure name: submit
// Purpose: Submit Submit Dates to Batch Process.
// Returns:
// --------------------------------------------------
dcl-proc submit;
// Set Dates to relate to BPCS database.
convertISOdatetoBPCSDate();
Out LDA;
return;
end-proc;
// --------------------------------------------------
// Procedure name: getFiscalDefaults
// Purpose: Get Fiscal Defaults from Calendar.
// Returns:
// --------------------------------------------------
dcl-proc getFiscalDefaults;
// Use Todays Date to find which month is Current.
dCurrent = %Date();
// subtract 28 Years before Conversion.
dCurrent = dCurrent - %Years(nYears);
// Place Date in String to retrieve Year.
sCurrentDate = %Char(dCurrent);
// Convert to 6 Digit Numeric Date.
nC6Date = %Dec(dCurrent:*ymd);
// Get Year and Make Numeric.
sCurrentYear = %Subst(sCurrentDate:3:2);
nCurrentYear = %Dec(sCurrentYear:2:0);
Setll ( nCompany : nCurrentYear ) GPML01;
Reade ( nCompany : nCurrentYear ) GPML01 IPG100PM_i;
Dow Not %Eof(GPML01);
// Find Calender entry where Current Date Falls between (or on)
// Period Start/End Dates.
If nC6Date >= IPG100PM_i.Pstart And nC6Date <= IPG100PM_i.Pend;
// Get current Month From Fiscal Calendar.
nFmthds = IPG100PM_i.Period;
// Start Date.
dFiscalStart = %date(IPG100PM_i.Pstart:*ymd);
// ESnd Date.
dFiscalEnd = %date(IPG100PM_i.Pend:*ymd);
Leave;
Endif;
Reade ( nCompany : nCurrentYear ) GPML01 IPG100PM_i;
Enddo;
// Add 28 Years to Fiscal Dates.
dFiscalStart = dFiscalStart + %Years(nYears);
dFiscalEnd = dFiscalEnd + %Years(nYears);
return;
end-proc;
// --------------------------------------------------
// Procedure name: initialise
// Purpose: Initialise the Program variables
// Returns:
// --------------------------------------------------
dcl-proc initialise;
// Fiscal Calendar.
If Not %Open(GPML01);
Open GPML01;
Endif;
// find Current Month Date Range from Fiscal Calendar
// Get Fiscal Defaults from Calendar.
getFiscalDefaults();
// Fiscal Start Date.
sSdatds = %Char(dFiscalStart:mdy/);
sSdatdsSave = sSdatds;
// Fiscal End Date.
sEdatds = %Char(dFiscalEnd:mdy/);
sEdatdsSave = sEdatds;
// Default Add Months.
nAmthds = 6;
nAmthdsSave = nAmthds;
// Default todays Date (Start Date)
// Add Months to Report End Date.
// Default Fiscal Start Date + default Months (Report End Date)
dRep = dFiscalStart + %Months(nAmthds);
sRdatds = %Char(dRep:*mdy/);
return;
end-proc;
I dunno if thats more efficient.
But its definitely nerdily prettier. #thatsaword
Nice Work IBM Rational Developer Nerds 🙂
Of course I could have kept going down the RPG code modernisation rabbit hole with locally defined variables, using SQL for data retrieval, variable length fields, but I had to stop… the coffee was cold.
