Displaying a CSV File
Program DisplayCSV reads a CSV file and uses the pos and posEx functions to format the output to the screen. We add a comma after the last field to make the processing of fields consistent. Starting from the left of the string, if a comma is found with the pos function then all the characters before the comma make up a field and all the characters to the right of the comma (if any) make up the next string to be processed in the same way.
In procedure ProcessCSVposEx, PosEx(SubString, MainString, Offset) returns the index of SubString in MainString, beginning the search at Offset. If the Offset is 1 (the default), then the function posEx is equivalent to pos. This ability to search from a character position greater than one allows us to separate the original string into fields rather than repeatedly beheading it.
For your convenience, we include a procedure that saves the test CSV file into your program folder.
program DisplayCSV; {$APPTYPE CONSOLE} uses SysUtils, StrUtils; const FILENAME = 'marks.csv'; procedure SaveCSV; var CSVFile : textFile; begin assignFile(CSVFile, 'marks.csv'); rewrite(CSVFile); writeln(CSVFile,'Forename, Surname, Theory Mark, Practical Mark'); writeln(CSVFile,'Jo, Wood, 55, 66'); writeln(CSVFile,'John, Bode, 73, 58'); writeln(CSVFile,'Kapil, Shah, 59, 58'); closeFile(CSVFile); end; procedure ProcessCSV(strFileName : string); const MAX_COLS = 100; MAX_ROWS = 10; SPACING = 2; var CSVFile : textFile; CurrentString, CurrentField : string; CommaPosition, UsedCols, UsedRows, ColCount, RowCount, NoOfSpaces : integer; Table : array [1 .. MAX_COLS, 1 .. MAX_ROWS] of string; ColWidths : array [1 .. MAX_ROWS] of integer; begin assignFile(CSVFile, strFilename); reset(CSVFile); UsedCols := 0; UsedRows := 0; while not eof(CSVFile) do begin readln(CSVFile, CurrentString); CurrentString := CurrentString + ','; inc(UsedCols); UsedRows := 0; repeat CommaPosition := pos(',', CurrentString); if CommaPosition > 0 then begin inc(UsedRows); CurrentField := leftStr(CurrentString, CommaPosition - 1); CurrentString := rightStr(CurrentString, length(CurrentString) - CommaPosition); Table[UsedCols, UsedRows] := CurrentField; end; until CommaPosition = 0; end; closeFile(CSVFile); //Find max field length for each column for RowCount := 1 to UsedRows do begin colWidths[RowCount] := Length(Table[1, RowCount]); for ColCount := 2 to UsedCols do begin if length(Table[ColCount, RowCount]) > colWidths[RowCount] then begin colWidths[RowCount] := length(Table[ColCount, RowCount]); end; end; end; //Output the data, right justified for ColCount := 1 to UsedCols do begin for RowCount := 1 to UsedRows do begin write(Table[ColCount, RowCount] : colWidths[RowCount] + SPACING); end; writeln; end; writeln; //Output the data, left justified for ColCount := 1 to UsedCols do begin for RowCount := 1 to UsedRows do begin CurrentField := Table[ColCount, RowCount]; NoOfSpaces := colWidths[RowCount] + SPACING - length(CurrentField); write(CurrentField, stringOfChar(' ', NoOfSpaces)); end; writeln; end; writeln; end; procedure ProcessCSVposEx (strFileName : string); var CSVFile : textFile; CurrentString, CurrentField : string; CommaPosition, StartPos : integer; begin assignFile(CSVFile, strFilename); reset(CSVFile); while not eof(CSVFile) do begin readln(CSVFile, CurrentString); CurrentString := CurrentString + ','; StartPos:=1; repeat CommaPosition := posEx(',', CurrentString, StartPos); CurrentField := MidStr(CurrentString, StartPos, CommaPosition - StartPos); StartPos := CommaPosition + 1; write(CurrentField, ' '); until (CommaPosition = 0); writeln; end; closeFile(CSVFile); end; begin SaveCSV; ProcessCSV(FILENAME); ProcessCSVposEx(FILENAME); readln; end.
The program produced the following output from our test file.

Output from program DisplayCSV