Ik heb een aantal *.csv bestanden waarin de status van elk item word bijgehouden.
Zo'n bestand kan rond de 10.000 rijen bevatten. Hieronder een klein voorbeeld van de inhoud:
Nu wil ik graag drie van dat soort *.csv bestanden uitlezen met behulp van TCSVdocument. De bestanden wordt tijdens het starten van het programma al ingeladen. Ik heb ook drie TListviews aangemaakt die ik straks wil gaan vullen met de gevonden resultaten per *.csv bestand. Van elk bestand ga ik vervolgens controleren welke rijen de status "geleverd" bevatten. Wanneer aan deze voorwaarde is voldaan, wil ik de bijbehorende TListview vullen met als resultaat het item nummer en datum uit de gevonden rij.
Versie Categorie Leverancier Item Datum Status V1-0 PRODUCT-1 TEST 1 1-4-2019 V1-0 PRODUCT-1 TEST 2 1-4-2019 V1-0 PRODUCT-1 TEST 3 1-4-2019 V1-0 PRODUCT-1 TEST 4 1-4-2019 V1-0 PRODUCT-1 TEST 5 1-4-2019 V1-0 PRODUCT-1 TEST 6 1-4-2019 V1-0 PRODUCT-1 TEST 7 1-4-2019 V1-0 PRODUCT-1 TEST 8 1-4-2019 V1-0 PRODUCT-1 TEST 9 1-4-2019 V1-0 PRODUCT-1 TEST 10 3-4-2019 Geleverd V1-0 PRODUCT-1 TEST 11 3-4-2019 Geleverd V1-0 PRODUCT-1 TEST 12 3-4-2019 Geleverd V1-0 PRODUCT-1 TEST 13 3-4-2019 Geleverd V1-0 PRODUCT-1 TEST 14 3-4-2019 Geleverd
Hiervoor gebruik ik de volgende code:
Welke wordt aangeroepen via een button:Delphi Code:
Procedure Zoek_Geleverde_Items(Input: TCSVdocument; Aantal_lbl: TLabel; Lijst: TListView); var i: Integer; StatusKolom: Integer; ItemKolom: Integer; DatumKolom: Integer; Status: String; begin StatusKolom := Input.IndexOfCol('Status', 0); ItemKolom := Input.IndexOfCol('Item', 0); DatumKolom := Input.IndexOfCol('Datum', 0); for i := 1 to Input.RowCount -1 do begin Status := Input.Cells[StatusKolom, i]; if Status = 'Geleverd' then with Lijst.Items.Add do begin Caption := Input.Cells[ItemKolom, i]; SubItems.Add(Input.Cells[DatumKolom, i]); end; end; Aantal_lbl.Caption := 'Aantal: ' + IntToStr(Lijst.Items.Count); end;
Delphi Code:
procedure TForm1.Button1Click(Sender: TObject); var cStart, cStop: Cardinal; begin Screen.Cursor := crHourGlass; cStart := GetTickCount64; Listview1.BeginUpdate; Listview2.BeginUpdate; Listview3.BeginUpdate; try Listview1.Clear; Listview2.Clear; Listview3.Clear; Zoek_Geleverde_Items(Product1, Label1, Listview1); Zoek_Geleverde_Items(Product2, Label2, Listview2); Zoek_Geleverde_Items(Product3, Label3, Listview3); cStop := GetTickCount64-cStart; Showmessage(IntToStr(cStop)); finally Listview1.EndUpdate; Listview2.EndUpdate; Listview3.EndUpdate; Screen.Cursor := crDefault; end; end;
Volledige source:
Delphi Code:
unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls, CSVdocument; type { TForm1 } TForm1 = class(TForm) Button1: TButton; GroupBox1: TGroupBox; GroupBox2: TGroupBox; GroupBox3: TGroupBox; Label1: TLabel; Label2: TLabel; Label3: TLabel; ListView1: TListView; ListView2: TListView; ListView3: TListView; procedure Button1Click(Sender: TObject); procedure FormClose(Sender: TObject; var CloseAction: TCloseAction); procedure FormCreate(Sender: TObject); private Product1: TCSVdocument; Product2: TCSVdocument; Product3: TCSVdocument; public end; var Form1: TForm1; implementation {$R *.lfm} { TForm1 } Procedure Zoek_Geleverde_Items(Input: TCSVdocument; Aantal_lbl: TLabel; Lijst: TListView); var i: Integer; StatusKolom: Integer; ItemKolom: Integer; DatumKolom: Integer; Status: String; begin StatusKolom := Input.IndexOfCol('Status', 0); ItemKolom := Input.IndexOfCol('Item', 0); DatumKolom := Input.IndexOfCol('Datum', 0); for i := 1 to Input.RowCount -1 do begin Status := Input.Cells[StatusKolom, i]; if Status = 'Geleverd' then with Lijst.Items.Add do begin Caption := Input.Cells[ItemKolom, i]; SubItems.Add(Input.Cells[DatumKolom, i]); end; end; Aantal_lbl.Caption := 'Aantal: ' + IntToStr(Lijst.Items.Count); end; procedure TForm1.Button1Click(Sender: TObject); var cStart, cStop: Cardinal; begin Screen.Cursor := crHourGlass; cStart := GetTickCount64; Listview1.BeginUpdate; Listview2.BeginUpdate; Listview3.BeginUpdate; try Listview1.Clear; Listview2.Clear; Listview3.Clear; Zoek_Geleverde_Items(Product1, Label1, Listview1); Zoek_Geleverde_Items(Product2, Label2, Listview2); Zoek_Geleverde_Items(Product3, Label3, Listview3); cStop := GetTickCount64-cStart; Showmessage(IntToStr(cStop)); finally Listview1.EndUpdate; Listview2.EndUpdate; Listview3.EndUpdate; Screen.Cursor := crDefault; end; end; procedure TForm1.FormCreate(Sender: TObject); var Bestand1: String; Bestand2: String; Bestand3: String; begin Bestand1 := ExtractFilePath(Application.ExeName) + 'Data\Product_1.csv'; Bestand2 := ExtractFilePath(Application.ExeName) + 'Data\Product_2.csv'; Bestand3 := ExtractFilePath(Application.ExeName) + 'Data\Product_3.csv'; Product1 := TCSVdocument.Create; Product1.Delimiter:= ';'; if FileExists(Bestand1) then Product1.LoadFromFile(Bestand1); Product2 := TCSVdocument.Create; Product2.Delimiter:= ';'; if FileExists(Bestand2) then Product2.LoadFromFile(Bestand2); Product3 := TCSVdocument.Create; Product3.Delimiter:= ';'; if FileExists(Bestand3) then Product3.LoadFromFile(Bestand3); end; procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction); begin Product1.Free; Product2.Free; Product3.Free; end; end.
Dit werkt prima maar duurt nu een kleine 6/7 seconden voordat alles is doorlopen en de Listviews zijn gevuld.
Zou dit sneller kunnen? Mijn i5 processor gebruikt nu namelijk maar 25% aan rekenkracht. Mogelijk dat er meer winst te behalen valt met Multi Threading? Ik heb daar echter geen ervaring mee en ben benieuwd of dit parallel uitgevoerd kan worden? Daarmee zou deze taak 3x sneller kunnen worden lijkt mij.
Bookmarks