Though more than requested, this program should handle most CSV records. It was not tested with tab-delimiters. The program converts the CSV text (with removal of added quotes) from delimited by a selected delimiter to delimited by LOW-VALUES
. Making it easier to separate the fields with UNSTRING ... DELIMITED LOW-VALUES INTO ...
.
IDENTIFICATION DIVISION.
PROGRAM-ID. CSV2STR.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 I COMP PIC 9(4).
01 J COMP PIC 9(4).
01 FLD-START COMP PIC 9(4).
01 STATE COMP PIC 9(4).
01 FLD-SEP PIC X VALUE LOW-VALUES.
01 QUOT PIC X VALUE """".
01 APOS PIC X VALUE "'".
01 COMM PIC X VALUE ",".
LINKAGE SECTION.
01 INPUT-REC PIC X(2000).
01 INPUT-LENGTH COMP PIC 9(4).
01 OUTPUT-REC PIC X(2000).
01 OUTPUT-LENGTH COMP PIC 9(4).
01 DELIM PIC X.
PROCEDURE DIVISION USING INPUT-REC INPUT-LENGTH
OUTPUT-REC OUTPUT-LENGTH DELIM.
BEGIN.
IF INPUT-LENGTH = 0 OR > 2000
MOVE 0 TO OUTPUT-LENGTH
EXIT PROGRAM
END-IF
IF DELIM NOT = SPACE
MOVE DELIM TO COMM
ELSE
MOVE "," TO COMM
END-IF
PERFORM CONVERT-RECORD
SUBTRACT 1 FROM J GIVING OUTPUT-LENGTH
EXIT PROGRAM
.
CONVERT-RECORD.
MOVE 1 TO STATE I J FLD-START
PERFORM CONVERT-RECORD-PROC
UNTIL I > INPUT-LENGTH
MOVE FLD-SEP TO OUTPUT-REC (J:1)
*> FOR NO FIELD AFTER THE LAST DELIMITER
IF INPUT-REC (I - 1:1) = COMM
ADD 1 TO J
MOVE FLD-SEP TO OUTPUT-REC (J:1)
END-IF
.
CONVERT-RECORD-PROC.
*> CSV-DT
EVALUATE STATE
ALSO I = FLD-START
ALSO INPUT-REC (I:1)
ALSO INPUT-REC (I + 1:1)
*> RULE 1 DETERMINES IF FIELD BEGINS WITH QUOTE
WHEN 1 ALSO TRUE ALSO QUOT ALSO ANY
MOVE 2 TO STATE
ADD 1 TO I
*> RULE 2 SPECIAL CASE OF SPACE + APOSTROPHE AT FIELD START
WHEN 1 ALSO TRUE ALSO SPACE ALSO APOS
ADD 1 TO I
*> RULE 3 COPIES ONE CHARACTER
WHEN 1 ALSO ANY ALSO NOT COMM ALSO ANY
MOVE INPUT-REC (I:1) TO OUTPUT-REC (J:1)
ADD 1 TO I
ADD 1 TO J
*> RULE 4 ENDS A FIELD
WHEN 1 ALSO ANY ALSO COMM ALSO ANY
MOVE FLD-SEP TO OUTPUT-REC (J:1)
ADD 1 TO I
ADD 1 TO J
MOVE I TO FLD-START
*> RULE 5 FOR QUOTED FIELD DROPS INITAL QUOTE
WHEN 2 ALSO ANY ALSO NOT QUOT ALSO ANY
MOVE INPUT-REC (I:1) TO OUTPUT-REC (J:1)
ADD 1 TO I
ADD 1 TO J
*> RULE 6 FOR QUOTED FIELD CONVERTS TWO QUOTED TO ONE
WHEN 2 ALSO ANY ALSO QUOT ALSO QUOT
MOVE QUOTE TO OUTPUT-REC (J:1)
ADD 2 TO I
ADD 1 TO J
*> RULE 7 FOR QUOTED FIELD DROPS QUOTE BEFORE DELIMITER
WHEN 2 ALSO ANY ALSO QUOT ALSO COMM
MOVE FLD-SEP TO OUTPUT-REC (J:1)
ADD 2 TO I
ADD 1 TO J
MOVE I TO FLD-START
MOVE 1 TO STATE
*> RULE 8 FOR QUOTED FIELD DROPS FINAL QUOTE OF LAST FIELD
WHEN 2 ALSO ANY ALSO QUOT ALSO SPACE
ADD 2 TO I
ADD 1 TO J
MOVE I TO FLD-START
MOVE 1 TO STATE
END-EVALUATE
.
The following CSV file was tested:
120,ABC,123,"12"" RULER","""ABC"", ""DEF"", ""GHI""", 'ABC',"123,456"
"""789""",,,,"""mno""",,
Test program output:
1: 120
2: ABC
3: 123
4: 12" RULER
5: "ABC", "DEF", "GHI"
6: 'ABC'
7: 123,456
1: "789"
2:
3:
4:
5: "mno"
6:
7: