10. november 2003 - 18:53
Der er
3 kommentarer og
1 løsning
StringList's DelimitedText er blevet tosset
jeg har en meget simpel tekst, som jeg vil splitte op med StringList's DelimitedText funktion. Det virker nu også meget godt med fx Delimiter := ';' eller Delimiter := #9 (tab) men!!!
Den spliter sørmer også ved alm. mellemrum!! hva skal de nu ligne?? hvis jeg har teksten: "dav med dig;du er en gammel nar" og sætter delimiter til ; så splitterne den:
dav
med
dig
du
er
en
gammel
nar
går ud fra det er synligt hvad problemet er!! men hvordan løser jeg det?
nca
Juniormester
10. november 2003 - 19:24
#1
Jeg har sakset nedenstående fra en nyhedsgruppe på nettet:
It's not a bug - it's noted in the help file. Still a PITA, so here's my
personal replacement (public domain, as-is):
{ procedure CSVParse
Parses a line from a CSV file into distinct fields.
<sInput> is the line of CSV data.
<Fields> is a TStrings/TStringList variable that will hold the results.
The list will be cleared before use.
<AQual> is the string qualifier and defaults to a double-quote (").
Qualifiers will be stripped from fields and any literals within the
field
will be undoubled.
<ADelim> is the field delimiter and defaults to a comma (,). }
procedure CSVParse(const sInput: String; Fields: TStrings;
const AQual: String = '"'; const ADelim: String = ',');
var
sWork, sField, sChar: String;
i, w: Integer;
begin
Fields.Clear;
sWork := sInput;
while Length(sWork) > 0 do
begin
// Is this field surrounded by the qualifier?
if sWork[1] = AQual then
begin
// Find the next instance of the delimiter preceeded by a non-literal
// qualifier. If not present, find the next qualifier and/or EOL.
sWork := Copy(sWork, 2, MaxInt);
i := Pos(AQual, sWork);
if i < 1 then i := 1;
sField := Copy(sWork, 1, i - 1);
w := Length(sWork);
while i <= w do
begin
sChar := sWork[i];
if sChar = AQual then
begin
if i = w then
begin // EOL. We're done, but discard this trailing qualifier.
Inc(i);
break;
end
else if sWork[i + 1] = ADelim then
begin // Qualifier followed by a delimiter. Done!
Inc(i, 2);
break;
end
else if sWork[i + 1] = AQual then
begin // It's a literal when followed by another qualifier. Skip
ahead.
Inc(i);
end;
end;
sField := sField + sChar;
Inc(i);
end;
sWork := Copy(sWork, i, MaxInt);
end
else
begin // Not a qualified field - just find the next delimiter or EOL:
i := Pos(ADelim, sWork);
if i > 0 then
begin
sField := Copy(sWork, 1, i - 1);
sWork := Copy(sWork, i + 1, MaxInt);
end
else
begin // EOL
sField := sWork;
sWork := '';
end;
end;
// Add this field to the TStrings/TStringList:
Fields.Add(sField);
end; // while Length(sWork) > 0
// If the line ends with a delimiter, add a blank field to the list:
i := Length(sInput);
if (i > 0) and (sInput[i] = ADelim) then
Fields.Add('');
end;
Slettet bruger
10. november 2003 - 19:26
#2
Du kan jo også erstatte mellemrummene i sætningen med et andet tegn:
var
Str: String;
L: TStringList;
begin
L := TStringList.Create;
Str := AnsiReplaceStr('dav med dig;du er en gammel nar', ' ',Chr(255));
L.Delimiter := ';';
L.DelimitedText := Str;
L.Text := AnsiReplaceStr( L.Text, Chr(255), ' ');
end;
10. november 2003 - 20:11
#3
Når man nu er gået så vidt, kan det jo bare ende helt med stringreplace:
var
Str: String;
st: TStringList;
begin
Str := 'dav med dig;du er en gammel nar';
st := TStringList.Create;
st.text := stringreplace(Str, ';', #13#10, [rfreplaceall]);
showmessage(st.text);
st.free;
end;
10. november 2003 - 21:50
#4
dkn må siges at have lavet den nemmeste løsning. det er ikke alverden tekst der skal parses, så at metoden går hurtigere vil ikke vise den store forskel.
tak til jer alle sammen