Hi all,
here is the CSV decoding function. I have a problem with the array of
string as the compiler is saying the type is not good when trying the
SetLength(a). I must create a type for this.
Now I submit this procedure (because a function cant' return an array
of string, but could probably return the type?) and I want inputs:
- a better solution for 'array of string'
- if no solution, is a function better?
Then after I received the input I'll send a patch for sysutils (when
the forum is up again).
Thank you very much (for making this code and fpc/lazarus better). :)
type
TArrayOfString = array of string;
implementation
{ Summary:
Decode a CSV string and return an array of string.
Arguments:
s = csv record (line) to parse
a = array of string to fill (length will be set automatically)
stringDelimiter = the string delimiter to use (usually '"')
valueDelimiter = the value delimiter to use (usually ',')
looseQuoting = In strick CSV the stringDelimiter must be found right after
the valueDelimiter in order to be a valid quote. If looseQuoting is
activated, space (#32) chars will be accepted
Description:
The function will parse the 's' string and fill the 'a' array of string with
a dimension for each part of 's' delimited by valueDelimiter. If a
stringDelimier is first found, all valueDelimiter inside it will be ignored.
Results:
An array is returned, having the content of each column in the CSV record.
Notes:
Since this function is taking a string, we can' manage the aspect of imbeded
LF/CRLF in the CSV when reading from a file (since the function is not
reading from the file itself).
Also, the procedure is not intended to support improperly formed CSV
records. It was not intended to be so. Activating looseQuoting is allowing a
breach in CSV interpretation. Something like 'a, "b"c, d' will fail as it
should give 'a','"b"c','d' will rather give 'a','b"c','d'.
See also:
EncodeCSVStr
Author:
Alexandre Leclerc }
procedure DecodeCSVStr(const s: string; var a: TArrayOfString; const
stringDelimiter, valueDelimiter: Char; const looseQuoting: Boolean);
var
i: LongInt;
pc: PChar;
sp: Integer; //start pos when copying
count: Integer;
isQuoted: Boolean;
procedure AddCSVColumn;
begin
SetLength(a, count+1);
a[count] := Trim(Copy(s, sp, i-sp));
if isQuoted then //remove double-quote and last quote char
begin
sp := Length(a[count]); //reuse sp temporarily for column value length
a[count] := StringReplace(
IfThen(a[count][sp] = stringDelimiter,
Copy(a[count], 1, sp-1), a[count]),
stringDelimiter + stringDelimiter, stringDelimiter, [rfReplaceAll]);
end;
Inc(count);
sp := 0;
isQuoted := False;
end;
var
inString: Boolean;
begin
inString := False;
isQuoted := False;
pc := @s[1];
sp := 0;
count := 0;
for i := 1 to Length(s) do
begin
if not (looseQuoting and (pc^ = #32)) then
if pc^ = stringDelimiter then
begin
if sp = 0 then //string delimiter is only good at start
begin
isQuoted := True;
sp := i+1;
end;
if isQuoted then
inString := (not inString);
end else
begin
if sp = 0 then
sp := i;
if (not inString) and (pc^ = valueDelimiter) then
AddCSVColumn();
end;
Inc(pc);
end;
Inc(i);
AddCSVColumn();
end;
--
Alexandre Leclerc
_________________________________________________________________
To unsubscribe: mail [EMAIL PROTECTED] with
"unsubscribe" as the Subject
archives at http://www.lazarus.freepascal.org/mailarchives