Wczytywanie pliku CSV do StringGrid

0

Witam

Powiedzcie mi jaki jest najprostszy (najszybszy)sposób na wczytanie do stringgrida pliku CVS o takiej budowie:

 5907809372411;SOBIK SMIETANKOWY SMAK 200G;SOBIK;2,73;5;2,87;0;2,73;2,87;szt.
5903732000308;SOBIK BRYNDZA OWCZA-NOWY SACZ 120G;SOBIK;2,56;5;2,69;0;2,56;2,69;szt.
0000000017;OPOLE LUBELSKIE MLEKO 1.5% FOLIA 900ML;OPOLE LUBELSKIE;1,68;5;1,76;-9 %;1,53;1,61;szt.
0000000018;OPOLE LUBELSKIE MLEKO 1.5% FOLIA 5L;OPOLE LUBELSKIE;1,66;5;1,74;-9 %;1,51;1,59;szt.

Napisałem sobie procedurę która sprawdza plik znak po znaku:

 

procedure TForm1.Button2Click(Sender: TObject);
VAR
oferta,zamowienie:textfile;
x,y,cdlugoscrekordu:integer;
bufor,znak:string;
wiersz: array[1..10] of string;

begin         
assignfile(oferta,'plik.txt');
reset(oferta)   
while not eof(oferta) do {dopoki nie koniec pliku, wtedy odczytaj linie i ja wypisz}
                      begin
                         StringGrid1.RowCount:=  StringGrid1.RowCount+1;  //dodajemy wiersz do StringGrida
                         ReadLn(oferta,Bufor);                                        // odczytujemy linie pliku do "bufora"
                         dlugoscrekordu:=length(Bufor);                           // odczytujemy długośc "bufora"
                         for i:=1 to dlugoscrekordu do                    
                               begin
                                    znak:=Copy(Bufor, i, 1);                        // kopiujemy "i" znak z bufora
                                   if znak<>';' then                                    // jeśli znak nie jest średnikiem
                                                  wiersz[x]:=wiersz[x]+znak;          dopisujemy do rekordu "x" znak "i"
                                       
                                if znak=';' then
                                             x:=x+1;                                     // jeśli "i" znak z bufora jest średnikiem
                                                                                                zwiększamy numer rekordu "x"
                             for c:=1 to x do
                              begin
                               StringGrid1.Cells[c,y]:=wiersz[c];              // wpisujemy kolejne rekordy do stringgrida (wiersz y)      
                              end;

                            for c:=1 to x do wiersz[c]:='';                   // czyścimy rekordy
                          y:=y+1;                                                  // zwiększamy numer wiersza "y"
                          x:=1;                                                      // "zerujemy" numer rekordu "x"
                      end;
                  end;  
closefile(oferta);
end;

Domyślam się, że nie jest to najlepszy sposób (choć działa ;) ), stąd moje pytanie...

0

najprościej to tak

var
  plik, linia: TStringList;
  i, j: Integer;
begin
  plik := TStringList.Create;
  linia := TStringList.Create;
  try
    plik.LoadFromFile('plik.csv');
    if plik.Count = 0 then
      Exit;
    linia.Delimiter := ';';
    linia.DelimitedText := StringReplace(plik[0], ' ', '~', [rfReplaceAll]);
    StringGrid1.RowCount := plik.Count;
    StringGrid1.ColCount := linia.Count;
    for i := 0 to plik.Count - 1 do
    begin
      linia.DelimitedText := StringReplace(plik[i], ' ', '~', [rfReplaceAll]);
      for j := 0 to linia.Count - 1 do
      begin
        StringGrid1.Cells[j, i] := StringReplace(linia[j], '~', ' ', [rfReplaceAll]);
      end;
    end;
  finally
    linia.Free;
    plik.Free;
  end;

"hak" z StringReplace jest potrzebny ponieważ DelimitedText dzieli też po spacji a nie tylko po Delimiter

0

Witam,
Moja propozycja wygląda tak:

procedure ImportToStringGrid(const FileName: String);
var
  I: Integer;
begin
  with StringGrid1 do
  begin
    Cols[0].LoadFromFile(FileName);
    Cols[0].Text := StringReplace(Cols[0].Text, ' ' , '~', [rfReplaceAll]);
    for I := 0 to Cols[0].IndexOf(' ') - 1 do
    with Rows[I] do
    begin
      BeginUpdate;
      Delimiter := ';';
      DelimitedText := Text;
      Text := StringReplace(Text, '~', ' ', [rfReplaceAll]);
      EndUpdate;
    end;
  end;
end;
0

@abrakadaber - raczej tak bo dzieli na linie:

procedure TForm1.Button2Click(Sender: TObject);
var
  plik, linia: TStringList;
  i, j: Integer;
begin
  plik := TStringList.Create;
  linia := TStringList.Create;
  try
  plik.LoadFromFile('plik.csv');
  for i := 0 to plik.lines.Count - 1 do
    plik.Add(plik.lines.Strings[i]);
    if plik.Count = 0 then
      Exit;
    linia.Delimiter := ';';
    linia.DelimitedText := StringReplace(plik[0], ' ', '~', [rfReplaceAll]);
    StringGrid1.RowCount := plik.Count;
    StringGrid1.ColCount := linia.Count;
    for i := 0 to plik.Count - 1 do
    begin
      linia.DelimitedText := StringReplace(plik[i], ' ', '~', [rfReplaceAll]);
      for j := 0 to linia.Count - 1 do
      begin
        StringGrid1.Cells[j, i] := StringReplace(linia[j], '~', ' ', [rfReplaceAll]);
      end;
    end;
  finally
    linia.Free;
    plik.Free;
  end;
end;
0

To i ja dorzucę swoją wizję:

procedure TForm1.Button1Click(Sender: TObject);
var
  sl, sLine: TStringList;
  i, j: Integer;
begin
  sl := TStringList.Create;
  sLine := TStringList.Create;
  try
    sl.LoadFromFile('c:\p.csv');
    for i := 0 to sl.Count - 1 do
    begin
      sLine.Clear;
      ExtractStrings([';'], [' '], PWideChar(sl[i]), sLine);
      if i = 0 then
      begin
        StringGrid1.RowCount := sl.Count;
        StringGrid1.ColCount := sLine.Count;
      end;
      for j := 0 to sLine.Count - 1 do
        StringGrid1.Cells[j, i] := sLine[j];
    end;
  finally
    sLine.Free;
    sl.Free;
  end;
end;

1 użytkowników online, w tym zalogowanych: 0, gości: 1