What I'm attempting to do is read over a RFC4180 compliant csv file, and throw each value into an array, for processing further on down the script. Below is the most convoluted but compliant csv line I could come up with, and it works, but this script will be customer facing, so I'd love it if you could have a look over and test the logic / show me the parts where I've missed things.
I'd love best practice pointers too, if possible.
This is an extract, basically I read in a line from the CSV file, and iterate over each char, testing and applying different things based on my understanding of RFC 4180. chr(34) represents double quote ("), it's the only way I could find to do a comparison in VBScript.
If isFirstChar = True And thisChar = chr(34) Then
'Mark it as in quotes, but don't print it, as it's not part of the text meant for the din file
isInQuotes = True
isFirstChar = False
ElseIf thisChar = chr(34) And isInQuotes = True Then
If nextChar = chr(34) Then
'Per RFC4108, "" is an escape sequence
'Print it, jump up the old CharCounter to prevent double handling.
CharCounter = CharCounter +1
FieldData = FieldData & thisChar
isFirstChar = False
ElseIf nextChar = "," Then
'It's the end of the field, we can set the isInQuotes to false so that the next char is handled as end of field
isInQuotes = False
isFirstChar = False
Else
'CSV isn't RFC4180 compliant
WScript.Echo "This CSV isn't RFC4180 compliant, please fix the file or contact <redacted> for assistance."
End If
ElseIf thisChar = "," Then
If isInQuotes = False Then
'End of Field, handle appropriately
FieldCounter = FieldCounter + 1
Redim Preserve FieldArray(FieldCounter)
FieldArray(FieldCounter) = FieldData
FieldData = ""
isFirstChar = True
Else
'In quotes, handle as regular char
FieldData = FieldData & thisChar
isFirstChar = False
End If
Else
'Got all the way here, it's just a regular character! (We hope)
FieldData = FieldData & thisChar
isFirstChar = False
End If
And below is an example of a row from a CSV record:
"Luke ,, Pearson","Luke ""Lucky""","""111 ""Brown Mountain Cres",,"CO""OROY",QLD,4563,,1234567,1,1.11,N,AT FRONT GATE,0712345678,0.0022,2
I wanted a standalone solution so here is what I came up with. (I am sure there is room for improvement):
Tested with the following (Note the
WriteLine
function is just a custom function that outputs to a console for testing purposes.:Output: