********************************************************************************************** * DBG201R4: Copy to field delimited format (.csv) * Copyright (C) 2001 Martin Rowe <martin@dbg400.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ********************************************************************************************** H DATEDIT(*YMD) DEBUG(*YES) OPTION(*NODEBUGIO : *SRCSTMT) ********************************************************************************************** * FILES: ********************************************************************************************** * Input file FINFILE IF F 5000 DISK InfDS(InFileDS) * Output file FDBGCSV00 O F 5000 DISK * Field mapping table FDBGFMT00 IF E K DISK ********************************************************************************************** * ARRAYS: ********************************************************************************************** D FldDta S 281 Dim(999) D FldEdt S 70 Dim(999) ********************************************************************************************** * DATA STRUCTURES: ********************************************************************************************** * Program Name D SDS D SDS_PGM 10 * D MapRules E DS ExtName(DBGFMT00) * * Information Data Structure D InFileDS DS D NbrOfRcds 9B 0 Overlay(InFileDS:156) * D Screen_DS DS D KeyPress 1 Overlay(Screen_DS:369) * ==List API structures== * Standard error code DS for API error handling D Error_Code DS D BytesProvd 1 4B 0 Inz(0) D BytesAvail 5 8B 0 Inz(0) D Except_ID 9 15 D Reserved 16 16 D Exception 17 272 * Receiver value DS for user space header info (used in first call to QUSRTVUS) D GenRcvrDS DS D UserArea 1 64 D GenHdrSize 65 68B 0 D StrucLevel 69 72 D FormatName 73 80 D APIused 81 90 D CreateStamp 91 103 D InfoStatus 104 104 D SizeUSused 105 108B 0 D InpParmOff 109 112B 0 D InpParmSiz 113 116B 0 D HeadOffset 117 120B 0 D HeaderSize 121 124B 0 D ListOffset 125 128B 0 D ListSize 129 132B 0 D ListNumber 133 136B 0 D EntrySize 137 140B 0 * QUSLFLD format FLDL0100 structure D FldL0100DS DS D FldL0100 D L_FieldName 10A Overlay( FldL0100 : 1 ) D L_DataType 1A Overlay( FldL0100 : 11 ) D L_Use 1A Overlay( FldL0100 : 12 ) D L_OutBuffer 9B 0 Overlay( FldL0100 : 13 ) D L_InBuffer 9B 0 Overlay( FldL0100 : 17 ) D L_Length 9B 0 Overlay( FldL0100 : 21 ) D L_Digits 9B 0 Overlay( FldL0100 : 25 ) D L_DecimalPos 9B 0 Overlay( FldL0100 : 29 ) D L_FieldText 50A Overlay( FldL0100 : 33 ) D L_EditCode 2A Overlay( FldL0100 : 83 ) D L_EditWordLn 9B 0 Overlay( FldL0100 : 85 ) D L_EditWord 64A Overlay( FldL0100 : 89 ) D L_ColHead1 20A Overlay( FldL0100 : 153 ) D L_ColHead2 20A Overlay( FldL0100 : 173 ) D L_ColHead3 20A Overlay( FldL0100 : 193 ) D L_IntFldName 10A Overlay( FldL0100 : 213 ) D L_AltFldName 30A Overlay( FldL0100 : 223 ) D L_AltFldLen 9B 0 Overlay( FldL0100 : 253 ) D L_NbrDBCS 9B 0 Overlay( FldL0100 : 257 ) D L_AllowNull 1A Overlay( FldL0100 : 261 ) D L_HostVryInd 1A Overlay( FldL0100 : 262 ) D L_DatTimFmt 4A Overlay( FldL0100 : 263 ) D L_DatTimSep 1A Overlay( FldL0100 : 267 ) D L_VaryLenInd 1A Overlay( FldL0100 : 268 ) D L_FldTxtCSID 1A Overlay( FldL0100 : 269 ) D L_FldDtaCSID 1A Overlay( FldL0100 : 273 ) D L_ColHedCSID 1A Overlay( FldL0100 : 277 ) D L_EdtWrdCSID 1A Overlay( FldL0100 : 281 ) * QUSLRCD format RCDL0100 structure D RcdL0100DS DS D RcdL0100 10 D L_FormatName 10A Overlay( RcdL0100 : 1 ) * D DS D CharField16 16A D PackField30 30P 0 Overlay( CharField16 : 1 ) * D DS D CharField30 30A D ZoneField30 30S 0 Overlay( CharField30 : 1 ) * D DS D CharDate 10A D DateField D Overlay( CharDate ) * D DS D CharTime 8A D TimeField T Overlay( CharTime ) * D DS D CharFloat D FloatField 8F Overlay( CharFloat ) D SmallFloat 4F Overlay( CharFloat ) * D DS D CharBin 4A D BinField 9B 0 Overlay( CharBin ) D SmallBin 4B 0 Overlay( CharBin ) * DD/MM/YY date breakdown. D DS D Dmy 6 0 D D_Dmy 2 0 Overlay(Dmy) D M_Dmy 2 0 Overlay(Dmy:3) D Y_Dmy 2 0 Overlay(Dmy:5) * DD/MM/YYYY date breakdown. D DS D Dmcy 8 0 D D_Dmcy 2 0 Overlay(Dmcy) D M_Dmcy 2 0 Overlay(Dmcy:3) D C_Dmcy 2 0 Overlay(Dmcy:5) D Y_Dmcy 2 0 Overlay(Dmcy:7) * YYYY/MM/DD date breakdown. D DS D Cymd 8 0 D C_Cymd 2 0 Overlay(Cymd) D Y_Cymd 2 0 Overlay(Cymd:3) D M_Cymd 2 0 Overlay(Cymd:5) D D_Cymd 2 0 Overlay(Cymd:7) * MM/DD/YY date breakdown. D DS D Mdy 6 0 D M_Mdy 2 0 Overlay(Mdy) D D_Mdy 2 0 Overlay(Mdy:3) D Y_Mdy 2 0 Overlay(Mdy:5) * MM/DD/YYYY date breakdown. D DS D Mdcy 8 0 D M_Mdcy 2 0 Overlay(Mdcy) D D_Mdcy 2 0 Overlay(Mdcy:3) D C_Mdcy 2 0 Overlay(Mdcy:5) D Y_Mdcy 2 0 Overlay(Mdcy:7) * YYYY/MM date breakdown. D DS D Cym 6 0 D C_Cym 2 0 Overlay(Cym) D Y_Cym 2 0 Overlay(Cym:3) D M_Cym 2 0 Overlay(Cym:5) ********************************************************************************************** * WORK FIELDS: ********************************************************************************************** ??? D LilianStart S D D WorkDate S D D Centry S 2 0 D Day S 2 0 D Month S 2 0 D DateCvt S 8 0 D Bad S 2 ??? D Cmdlength S 15 5 ??? D Cmdstring S 256 D ColHdgs S 62 Varying D CurrentEnt S 5P 0 Inz(1) D DataLength S 9B 0 Inz(140) D DecSide S 30 Varying D DecSym S 1 Inz('.') Varying D EditField S 40 Varying D ExtendAttr S 10 Inz('USRSPC ') D FileFormat S 10 D Good S 2 D Idx1 S 5 0 D Idx2 S 3 0 D InitialSiz S 9B 0 Inz(1024) D InitialVal S 1 Inz(X'00') D IntSide S 30 Varying D IntLen S 3 0 ??? D K_fld S 10 D ListFormat S 8 D LoopTotal S 5 0 D OnePercent S 11 2 D OverrideProc S 1 Inz('0') D P_File S 10 D P_ColHdg S 7 D P_FldDel S 1 D P_Library S 10 D P_Marker S 1 Inz(X'33') Yellow D P_Percent S 3 0 ??? D P_Pgm S 10 D P_RplFldDel S 1 D P_RplStrDel S 1 D P_StrDel S 1 D P_Text S 20 Inz('Records processed') D PosNeg S 1 Varying D PublicAut S 10 Inz('*ALL ') D QualifyFile S 20 ??? D ReturnCode S 7 D RcdsRead S 9 0 D Record S 5000 Varying D Remainder S 9 0 D ReplaceSpc S 10 Inz('*YES ') D StartPos S 9B 0 Inz(1) D StrDel S 1 Varying D Type_A S 999 Varying D TextDescrp S 50 Inz('QUSLRCD/QUSLFLD List APIs') D UserSpace S 20 Inz('DBG201US QTEMP ') D Year S 2 0 ********************************************************************************************** * CONSTANTS: ********************************************************************************************** ********************************************************************************************** IINFILE NS 01 I 1 5000 RCDDTA ********************************************************************************************** * ENTRY PARAMETERS: ********************************************************************************************** C *ENTRY PList C Parm P_File C Parm P_Library C Parm P_ColHdg C Parm P_FldDel C Parm P_RplFldDel C Parm P_StrDel C Parm P_RplStrDel ********************************************************************************************** * KEY LISTS: ********************************************************************************************** C DBGFMT00KEY KList C KFld P_Library C KFld P_File C KFld L_FieldName ********************************************************************************************** * MAINLINE: ********************************************************************************************** * Initialisation C ExSr Inits * Get the field details for this file C ExSr GetFldDtls * If column headings required in first record B001 C If P_ColHdg <> '*NONE' C ExSr SetColHdgs E001 C EndIf * Loop through the file, and create our flat file according to the field mapping rules C 1 SetLL INFILE C Read INFILE B001 C DoW Not %Eof(INFILE) * Keep track of how far the takeon has got C Eval RcdsRead = RcdsRead + 1 C RcdsRead Div OnePercent P_Percent C MvR Remainder B002 C If Remainder = 0 C Call 'DBG202R4' C Parm P_Percent C Parm P_Text C Parm P_Marker E002 C EndIf C ExSr ParseLine C Read INFILE E001 C EndDo * Time to go... C Eval *INLR = *On C Return ********************************************************************************************** * GetFldDtls: Get field details ********************************************************************************************** C GetFldDtls BegSr * Process returned entries B001 C If ListNumber > 0 * Set the initial offset for the start of the list entries C Eval ListOffset = ListOffset + 1 * Loop through the entries held in the list section of the user space B002 C DoW CurrentEnt <= ListNumber * Get the header info for this space C Call 'QUSRTVUS' C Parm UserSpace C Parm ListOffset C Parm EntrySize C Parm FldL0100DS C Parm Error_Code C Eval Idx1 = Idx1 + 1 C Eval FldDta(Idx1) = FldL0100 * Get mapping rules for this field (if present) C DBGFMT00KEY Chain (N) DBGFMT00 B003 C If %Found(DBGFMT00) C Eval FldEdt(Idx1) = MapRules X003 C Else C Eval FldEdt(Idx1) = *blanks E003 C EndIf * Bump up the counter & offset for the next entry C Eval ListOffset = ListOffset + EntrySize C Eval CurrentEnt = CurrentEnt + 1 E002 C EndDo E001 C EndIf * Set total number of fields in the record C Eval LoopTotal = Idx1 * Set XLATE from/to values for field & string delimiter conversions C Eval Bad = P_FldDel + P_StrDel C Eval Good = P_RplFldDel + P_RplStrDel * If no string delimiter required, set it to zero length (varying field) B001 C If P_StrDel = *blanks C Eval StrDel = '' X001 C Else C Eval StrDel = P_StrDel E001 C EndIf * C EndSr ********************************************************************************************** * SetColHdgs: Add column headings to first line of file ********************************************************************************************** C SetColHdgs BegSr * Loop through each field entry and process in turn B001 C Do LoopTotal Idx1 C Eval FldL0100 = FldDta(Idx1) * Process according to column heading type B002 C Select S002 C When P_ColHdg = '*COLHDG' C Eval ColHdgs = StrDel + %Trim(%Trim(L_ColHead1) + C ' ' + %Trim(L_ColHead2) + ' ' + C %Trim(L_ColHead3)) + StrDel S002 C When P_ColHdg = '*TEXT' C Eval ColHdgs = StrDel + %Trim(L_FieldText) + C StrDel S002 C When P_ColHdg = '*FIELD' C Eval ColHdgs = StrDel + %Trim(L_FieldName) + C StrDel E002 C EndSl * First entry resets the field - no leading delimiter B002 C If Idx1 = 1 C Eval Record = ColHdgs X002 C Else C Eval Record = Record + P_FldDel + ColHdgs E002 C EndIf E001 C EndDo * Write out the current line C Except TFRFORMAT * C EndSr ********************************************************************************************** * ParseLine: Parse input file line to create flat file in .csv format ********************************************************************************************** C ParseLine BegSr * Loop through each field entry and process in turn B001 C Do LoopTotal Idx1 C Eval FldL0100 = FldDta(Idx1) * Pick up appropriate mapping rules if set for current field B002 C If FldEdt(Idx1) <> *blanks C Eval MapRules = FldEdt(Idx1) * Otherwise don't use rules, just defaults X002 C Else C Eval FMRULE = *blanks E002 C EndIf * Process according to data type B002 C Select * Character data type S002 C When L_DataType = 'A' * Varying fields store the actual length used in the first two bytes so don't include them B003 C If L_VaryLenInd = *On C Eval Type_A = C %TrimR( %SubSt(RCDDTA : + C L_OutBuffer + 2 : + C L_Length - 2 ) ) X003 C Else C Eval Type_A = C %TrimR( %SubSt(RCDDTA : + C L_OutBuffer : + C L_Length ) ) E003 C EndIf * Strings might contain characters that conflict with the requested string & field delimiters * so replace them with the substitutes provided. C Bad:Good Xlate Type_A Type_A * Add character field prefix if required (so Excel doesn't treat is as a number on import) B003 C If FMRULE = 'Y' B003 C and FMPFIX <> *blanks C Eval Type_A = StrDel + FMPFIX + Type_A + StrDel X003 C Else C Eval Type_A = StrDel + Type_A + StrDel E003 C EndIf * First entry resets the field - no leading delimiter B003 C If Idx1 = 1 C Eval Record = Type_A X003 C Else C Eval Record = Record + P_FldDel + Type_A E003 C EndIf * Zoned numeric data type S002 C When L_DataType = 'S' C Eval ZoneField30 = *Zero C EvalR %SubSt(CharField30 : + C 31 - L_Length : + C L_Length) = C %SubSt(RCDDTA : + C L_OutBuffer : + C L_Length ) * Detect negative number, set sign & reverse sign of actual value (reapplied later) B003 C If ZoneField30 < 0 C Eval PosNeg = '-' C Eval ZoneField30 = -ZoneField30 X003 C Else C Eval PosNeg = '' E003 C EndIf * Format & add to current record C ExSr ProcNbr * Packed numeric data type S002 C When L_DataType = 'P' C Eval PackField30 = *Zero C EvalR %SubSt(CharField16 : + C 17 - L_Length : + C L_Length) = C %SubSt(RCDDTA : + C L_OutBuffer : + C L_Length ) * Detect negative number, set sign & reverse sign of actual value (reapplied later) B003 C If PackField30 < 0 C Eval PosNeg = '-' C Eval PackField30 = 0 - PackField30 X003 C Else C Eval PosNeg = '' E003 C EndIf C Move PackField30 CharField30 * Format & add to current record C ExSr ProcNbr * Date data type S002 C When L_DataType = 'L' C Eval CharDate = C %TrimR( %SubSt(RCDDTA : + C L_OutBuffer : + C L_Length ) ) * If rules required B003 C If FMRULE = 'Y' C *ISO Move DateField DateCvt * If change of date format required B004 C If FMINTF <> FMEXPF C ExSr DateFmt E004 C EndIf C Eval ZoneField30 = DateCvt C Eval IntSide = %SubSt(CharField30 : 23 : 8) C Eval IntLen = 8 * If date editing required B004 C If FMEDTD = 'Y' C ExSr DateTimeEdit E004 C EndIf * If zero fill not required B004 C If FMZFIL = ' ' C ExSr EditZ E004 C EndIf C Eval EditField = IntSide * Otherwise leave as-is X003 C Else C Eval EditField = CharDate E003 C EndIf * First entry resets the field - no leading delimiter B003 C If Idx1 = 1 C Eval Record = EditField X003 C Else C Eval Record = Record + P_FldDel + EditField E003 C EndIf * Time data type S002 C When L_DataType = 'T' C Eval CharTime = C %TrimR( %SubSt(RCDDTA : + C L_OutBuffer : + C L_Length ) ) * If rules required B003 C If FMRULE = 'Y' C *HMS Move TimeField DateCvt C Eval ZoneField30 = DateCvt C Eval IntSide = %SubSt(CharField30 : 23 : 8) C Eval IntLen = 8 * If date editing required B004 C If FMEDTD = 'Y' C ExSr DateTimeEdit E004 C EndIf * If zero fill not required B004 C If FMZFIL = ' ' C ExSr EditZ E004 C EndIf C Eval EditField = IntSide * Otherwise leave as-is X003 C Else C Eval EditField = CharTime E003 C EndIf * First entry resets the field - no leading delimiter B003 C If Idx1 = 1 C Eval Record = EditField X003 C Else C Eval Record = Record + P_FldDel + EditField E003 C EndIf * Timestamp data type S002 C When L_DataType = 'Z' C Eval Type_A = C %TrimR( %SubSt(RCDDTA : + C L_OutBuffer : + C L_Length ) ) * First entry resets the field - no leading delimiter B003 C If Idx1 = 1 C Eval Record = Type_A X003 C Else C Eval Record = Record + P_FldDel + Type_A E003 C EndIf * Floating point data type (never seen any of these, so expect 'strange results') S002 C When L_DataType = 'F' C Eval CharFloat = C %TrimR( %SubSt(RCDDTA : + C L_OutBuffer : + C L_Length ) ) B003 C If L_Digits <= 8 C Eval EditField = %EDITFLT(SmallFloat) X003 C Else C Eval EditField = %EDITFLT(FloatField) E003 C EndIf * First entry resets the field - no leading delimiter B003 C If Idx1 = 1 C Eval Record = EditField X003 C Else C Eval Record = Record + P_FldDel + EditField E003 C EndIf * Binary point data type (rarely use these, so don't expect much more than for floating point) S002 C When L_DataType = 'B' C Eval CharBin = C %TrimR( %SubSt(RCDDTA : + C L_OutBuffer : + C L_Length ) ) B003 C If L_Digits <= 4 C Eval ZoneField30 = SmallBin X003 C Else C Eval ZoneField30 = BinField E003 C EndIf * Detect negative number, set sign & reverse sign of actual value (reapplied later) B003 C If ZoneField30 < 0 C Eval PosNeg = '-' C Eval ZoneField30 = -ZoneField30 X003 C Else C Eval PosNeg = '' E003 C EndIf * Format & add to current record C ExSr ProcNbr E002 C EndSl E001 C EndDo * Write out the current line C Except TFRFORMAT * C EndSr ********************************************************************************************** * ProcNbr: Process number field (Zoned, Packed & Binary) ********************************************************************************************** C ProcNbr BegSr * C Eval DecSym = '.' * If not using edit rules, or rules set but number isn't a date B001 C If FMRULE = ' ' C Or FMRULE = 'Y' And FMDATE = ' ' * Split up field into decimal & interger portions if present B002 C If L_DecimalPos > 0 C Eval DecSide = %SubSt(CharField30 : + C 31 - L_DecimalPos : + C L_DecimalPos) C Eval IntSide = %SubSt(CharField30 : + C 31 - L_Digits : + C L_Digits - L_DecimalPos) X002 C Else C Eval DecSide = '' C Eval DecSym = '' C Eval IntSide = %SubSt(CharField30 : + C 31 - L_Digits : + C L_Digits) E002 C EndIf * Zero suppression (unless explicitly not required) B002 C If FMRULE = ' ' C Or FMRULE = 'Y' And FMZFIL = ' ' C Eval IntLen = L_Digits - L_DecimalPos C ExSr EditZ E002 C EndIf * Set format of negative values B002 C Select * Negatives as -123.45 (default) S002 C When FMRULE = ' ' C Or FMRULE = 'Y' And FMNEGF = '*FLOAT' C Eval EditField = PosNeg + IntSide + DecSym + C DecSide * Negatives as 123.45- S002 C When FMRULE = 'Y' And FMNEGF = '*MINUS' C Eval EditField = IntSide + DecSym + DecSide + C PosNeg * Negatives as 123.45CR S002 C When FMRULE = 'Y' And FMNEGF = '*CR' C Eval EditField = IntSide + DecSym + DecSide B003 C If PosNeg = '-' C Eval EditField = EditField + 'CR' E003 C EndIf * Negatives as (123.45) S002 C When FMRULE = 'Y' And FMNEGF = '*BRKTS' C Eval EditField = IntSide + DecSym + DecSide B003 C If PosNeg = '-' C Eval EditField = '(' + EditField + ')' E003 C EndIf E002 C EndSl E001 C EndIf * If date formatting required B001 C If FMRULE = 'Y' And FMDATE = 'Y' * If change of date format required B002 C If FMINTF <> FMEXPF C Eval DateCvt = ZoneField30 C ExSr DateFmt C Eval ZoneField30 = DateCvt E002 C EndIf C Eval IntSide = %SubSt(CharField30 : 23 : 8) C Eval IntLen = 8 * If date editing required B002 C If FMEDTD = 'Y' C ExSr DateTimeEdit E002 C EndIf * If zero fill not required B002 C If FMZFIL = ' ' C ExSr EditZ E002 C EndIf C Eval EditField = IntSide E001 C EndIf * First entry resets the field - no leading delimiter B001 C If Idx1 = 1 C Eval Record = EditField X001 C Else C Eval Record = Record + P_FldDel + EditField E001 C EndIf * C EndSr ********************************************************************************************** * EditZ: Trim leading zeros (always leave one) ********************************************************************************************** C EditZ BegSr * Leading zero suppression C '0' Check IntSide Idx2 70 * If non-zero value found, strip all leading zeros B001 C If *IN70 C Eval IntSide = %SubSt(IntSide : + C Idx2 : + C ((IntLen + 1) - Idx2)) * If processing a date/time and the separator is the first character, add a leading zero B002 C If FMRULE = 'Y' And FMEDTD = 'Y' C And %SubSt(IntSide : 1 : 1) = FMDSEP C Eval IntSide = '0' + IntSide E002 C EndIf X001 C Else * Include a single leading zero if no integer portion C Eval IntSide = '0' E001 C EndIf * C EndSr ********************************************************************************************** * DateFmt: Date formatting ********************************************************************************************** C DateFmt BegSr * C Eval Day = 0 C Eval Month = 0 C Eval Year = 0 C Eval Centry = 0 B001 C If DateCvt <> 0 * Split out date subsections ready for reformatting B002 C Select * S002 C When FMINTF = '*CYMD' C Eval Cymd = DateCvt C Eval Day = D_Cymd C Eval Month = M_Cymd C Eval Year = Y_Cymd C Eval Centry = C_Cymd * S002 C When FMINTF = '*SYMD' C Eval Cymd = DateCvt C Eval Day = D_Cymd C Eval Month = M_Cymd C Eval Year = Y_Cymd * Set century from Synon century digit C Eval Centry = 19 + C_Cymd * S002 C When FMINTF = '*YMD' C Eval Cymd = DateCvt C Eval Day = D_Cymd C Eval Month = M_Cymd C Eval Year = Y_Cymd C Eval Centry = C_Cymd * Assume century B003 C If Year < FMWINY C Eval Centry = 20 X003 C Else C Eval Centry = 19 E003 C EndIf * S002 C When FMINTF = '*MDY' C Eval Mdy = DateCvt C Eval Day = D_Mdy C Eval Month = M_Mdy C Eval Year = Y_Mdy * Assume century B003 C If Year < FMWINY C Eval Centry = 20 X003 C Else C Eval Centry = 19 E003 C EndIf * S002 C When FMINTF = '*MDCY' C Eval Mdcy = DateCvt C Eval Day = D_Mdcy C Eval Month = M_Mdcy C Eval Year = Y_Mdcy C Eval Centry = C_Mdcy * S002 C When FMINTF = '*DMCY' C Eval Dmcy = DateCvt C Eval Day = D_Dmcy C Eval Month = M_Dmcy C Eval Year = Y_Dmcy C Eval Centry = C_Dmcy * S002 C When FMINTF = '*LILIAN' C FMLILS AddDur DateCvt:*DAYS WorkDate C SubDur 1:*DAYS WorkDate C *ISO Move WorkDate Cymd C Eval Day = D_Cymd C Eval Month = M_Cymd C Eval Year = Y_Cymd C Eval Centry = C_Cymd * S002 C When FMINTF = '*DMY' C Eval Dmy = DateCvt C Eval Day = D_Dmy C Eval Month = M_Dmy C Eval Year = Y_Dmy * Assume century B003 C If Year < FMWINY C Eval Centry = 20 X003 C Else C Eval Centry = 19 E003 C EndIf * S002 C When FMINTF = '*CYM' C Eval Cym = DateCvt C Eval Month = M_Cym C Eval Year = Y_Cym C Eval Centry = C_Cym * S002 C When FMINTF = '*YM' C Eval Cym = DateCvt C Eval Month = M_Cym C Eval Year = Y_Cym * Assume century B003 C If Year < FMWINY C Eval Centry = 20 X003 C Else C Eval Centry = 19 E003 C EndIf * S002 C When FMINTF = '*MY' C Eval Dmy = DateCvt C Eval Day = D_Dmy C Eval Month = M_Dmy C Eval Year = Y_Dmy * Assume century B003 C If Year < FMWINY C Eval Centry = 20 X003 C Else C Eval Centry = 19 E003 C EndIf E002 C EndSl * * Now move the date subsections to the required format * B002 C Select * S002 C When FMEXPF = '*CYMD' C Eval D_Cymd = Day C Eval M_Cymd = Month C Eval Y_Cymd = Year C Eval C_Cymd = Centry C Eval DateCvt= Cymd * S002 C When FMEXPF = '*LILIAN' C *ISO Move Cymd WorkDate C WorkDate SubDur FMLILS DateCvt:*DAYS C Eval DateCvt = DateCvt + 1 C Eval DateCvt= Cymd * S002 C When FMEXPF = '*SYMD' C Eval D_Cymd = Day C Eval M_Cymd = Month C Eval Y_Cymd = Year * Set Synon century digit C Eval C_Cymd = Centry - 19 C Eval DateCvt= Cymd * S002 C When FMEXPF = '*YMD' C Eval D_Cymd = Day C Eval M_Cymd = Month C Eval Y_Cymd = Year C Eval C_Cymd = 0 C Eval DateCvt= Cymd * S002 C When FMEXPF = '*MDY' C Eval D_Mdy = Day C Eval M_Mdy = Month C Eval Y_Mdy = Year C Eval DateCvt= Mdy * S002 C When FMEXPF = '*MDCY' C Eval D_Mdcy = Day C Eval M_Mdcy = Month C Eval Y_Mdcy = Year C Eval C_Mdcy = Centry C Eval DateCvt= Mdcy * S002 C When FMEXPF = '*DMY ' C Eval D_Dmy = Day C Eval M_Dmy = Month C Eval Y_Dmy = Year C Eval DateCvt= Dmy * S002 C When FMEXPF = '*DMCY' C Eval D_Dmcy = Day C Eval M_Dmcy = Month C Eval Y_Dmcy = Year C Eval C_Dmcy = Centry C Eval DateCvt= Dmcy * S002 C When FMEXPF = '*CYM' C Eval M_Cym = Month C Eval Y_Cym = Year C Eval C_Cym = Centry C Eval DateCvt= Cym * S002 C When FMEXPF = '*YM' C Eval M_Cym = Month C Eval Y_Cym = Year C Eval C_Cym = 0 C Eval DateCvt= Cym * S002 C When FMEXPF = '*MY' C Eval M_Dmy = Month C Eval Y_Dmy = Year C Eval D_Dmy = 0 C Eval C_Cym = 0 C Eval DateCvt= Dmy E002 C EndSl E001 C EndIf * C EndSr ********************************************************************************************** * DateTimeEdit: Date/Time Editing ********************************************************************************************** C DateTimeEdit BegSr * B001 C Select * nnnn/nn/nn format S001 C When FMEXPF = '*CYMD' C Eval IntSide = %SubSt(IntSide : 1 : 4) + C FMDSEP + %SubSt(IntSide : 5 : 2) + C FMDSEP + %SubSt(IntSide : 7 : 2) C Eval IntLen = 10 * nnn/nn/nn format S001 C When FMEXPF = '*SYMD' C Eval IntSide = %SubSt(IntSide : 2 : 3) + C FMDSEP + %SubSt(IntSide : 5 : 2) + C FMDSEP + %SubSt(IntSide : 7 : 2) C Eval IntLen = 9 * nn/nn/nn format S001 C When FMEXPF = '*YMD' Or FMEXPF = '*MDY' C Or FMEXPF = '*DMY' Or FMEXPF = '*HMS' C Eval IntSide = %SubSt(IntSide : 3 : 2) + C FMDSEP + %SubSt(IntSide : 5 : 2) + C FMDSEP + %SubSt(IntSide : 7 : 2) C Eval IntLen = 8 * S001 C When FMEXPF = '*MDCY' Or FMEXPF = '*DMCY' C Eval IntSide = %SubSt(IntSide : 1 : 2) + C FMDSEP + %SubSt(IntSide : 3 : 2) + C FMDSEP + %SubSt(IntSide : 5 : 4) C Eval IntLen = 10 * S001 C When FMEXPF = '*CYM' C Eval IntSide = %SubSt(IntSide : 3 : 4) + C FMDSEP + %SubSt(IntSide : 7 : 2) C Eval IntLen = 7 * S001 C When FMEXPF = '*YM' Or FMEXPF = '*MY' C Or FMEXPF = '*HM' C Eval IntSide = %SubSt(IntSide : 5 : 2) + C FMDSEP + %SubSt(IntSide : 7 : 2) C Eval IntLen = 5 E001 C EndSl * C EndSr ********************************************************************************************** * Inits: Program initialisation ********************************************************************************************** C Inits BegSr * Use the QUSLRCD (List Record Formats) and QUSLFLD (List Fields) APIs to get the fields * for the input file. C Eval QualifyFile = P_File + P_Library * Create a user space to hold the format list entries C Call 'QUSCRTUS' C Parm UserSpace C Parm ExtendAttr C Parm InitialSiz C Parm InitialVal C Parm PublicAut C Parm TextDescrp C Parm ReplaceSpc C Parm Error_Code * List the formats in the file C Call 'QUSLRCD' C Parm UserSpace C Parm 'RCDL0100' ListFormat C Parm QualifyFile C Parm OverrideProc C Parm Error_Code * Get the header info for this space C Call 'QUSRTVUS' C Parm UserSpace C Parm StartPos C Parm DataLength C Parm GenRcvrDS C Parm Error_Code * Process returned entries B001 C If ListNumber > 0 * Set the initial offset for the start of the list entries C Eval ListOffset = ListOffset + 1 * Get the header info for this space C Call 'QUSRTVUS' C Parm UserSpace C Parm ListOffset C Parm EntrySize C Parm RcdL0100DS C Parm Error_Code * Only interested in the first format - there should only be one for a physical file. C Eval FileFormat = L_FormatName E001 C EndIf * Now the format name is known, the fields for the file can be retrieved * Create a user space to hold the field list entries C Call 'QUSCRTUS' C Parm UserSpace C Parm ExtendAttr C Parm InitialSiz C Parm InitialVal C Parm PublicAut C Parm TextDescrp C Parm ReplaceSpc C Parm Error_Code * List the fields in the file using the format just obtained C Call 'QUSLFLD' C Parm UserSpace C Parm 'FLDL0100' ListFormat C Parm QualifyFile C Parm FileFormat C Parm OverrideProc C Parm Error_Code * Get the header info for this space C Call 'QUSRTVUS' C Parm UserSpace C Parm StartPos C Parm DataLength C Parm GenRcvrDS C Parm Error_Code * C Eval OnePercent = NbrOfRcds / 100 * C EndSr ********************************************************************************************** ODBGCSV00 E TFRFORMAT O Record 5000