|
![]() |
|
Registriert seit: 12. Jan 2007 Ort: Sulzbach a.d. Murr 1.029 Beiträge Delphi 10.4 Sydney |
#1
Das sieht doch soooo schlecht gar nicht aus
![]() Zunächst reicht eine FOR-Schleife aus. Und bei der IF-Abfrage fehlt ein BEGIN...END. Pseudocode:
Delphi-Quellcode:
FOR [...] DO BEGIN
IF ID=-1 THEN BEGIN { INSERT } END ELSE BEGIN { UPDATE } END; {else} END; {for}
Michael Kübler
|
![]() |
Registriert seit: 22. Feb 2017 1.017 Beiträge |
#2
alles schon gar nicht schlecht.
Aber es müssen lediglich die SQL-Statements in den If-Block und das Bestücken von ID. Außer dem, das parseSQL muss vor dem Zuweisen von Werten passieren. Danach macht's keinen Sinn mehr, bzw. wirkt sich nur auf den nächsten Schleifendurchlauf aus. In etwa so:
Delphi-Quellcode:
procedure TCustomerList.SavetoDB(con: TZConnection);
var zqryMain: TZQuery; i: Integer; begin zqryMain:=TZQuery.Create(nil); try zqryMain.connection:=con; for I := 0 to Self.Count-1 do begin if self[i].ID=-1 then zqryMain.SQL.Text:='UPDATE WARENVERKAUF1 SET KDNR=:KNR, NAME =:NAM, VORNAME=:VNA, FIRMA=:FIR, PRODUKT=:PRO, ANZAHL=:ANZ, PREIS=:PRE WHERE ID=:ID' else zqryMain.SQL.text:='INSERT INTO WARENVERKAUF1(KDNR,NAME,VORNAME,FIRMA,PRODUKT,ANZAHL,PREIS) VALUES(:KNR, :NAM, :VNA, :FIR, :PRO, :ANZ, :PRE)'; zqryMain.params.parseSQL(zqryMain.sql.text, True); if self[i].ID=-1 then zqryMain.Params.ParamValues['ID']:=self[i].ID; zqryMain.params.ParamValues['KNR']:=self[i].KDNR; zqryMain.params.paramValues['NAM']:=self[i].Name; zqryMain.params.paramValues['VNA']:=self[i].Vorname; zqryMain.params.ParamValues['FIR']:=self[i].Firma; zqryMain.Params.ParamValues['PRO']:=self[i].Produkt; zqryMain.Params.ParamValues['ANZ']:=self[i].Anzahl; zqryMain.params.paramValues['PRE']:=self[i].Preis; zqryMain.ExecSQL; end; finally zqryMain.free; end; end; |
![]() |
Registriert seit: 24. Okt 2006 Ort: Seifhennersdorf / Sachsen 5.458 Beiträge Delphi 12 Athens |
#3
Moin...
![]() ![]() ![]() Mit dem Debugger würdest du selber sehen warum manche Sachen nicht aufgerufen werden oder die Werte nicht stimmen (Breakpoints). ![]() ![]()
Delphi-Quellcode:
procedure TCustomerList.SavetoDB(con: TZConnection);
var zqryMain: TZQuery; I: Integer; begin zqryMain := TZQuery.Create(nil); try zqryMain.connection := con; // Connection zuordnen for I := 0 to Self.Count - 1 do // Liste durchlaufen begin if Self[I].ID = -1 then // !!!! Das hatten wir doch schonmal ähnlich...Ist die ID jedes Objektes in der Liste > -1 ???? begin // !!! begin-end Blöcke da du erkennst was zueinander gehört...auch bei einer Anweisung macht es Sinn. zqryMain.SQL.Text := 'UPDATE WARENVERKAUF1 SET KDNR = :KNR, NAME = :NAM, VORNAME =: VNA, FIRMA = :FIR, PRODUKT = :PRO, ANZAHL = :ANZ, PREIS = :PRE WHERE ID = :ID' // Parameter nur mit ID -1 zuordnen !!! zqryMain.ParamByName('ID').AsInteger := Self[I].ID; // As... übergibt gleich den "richtigen" Typ...Value ist was für Weicheier :-), die nicht wissen welcher Wert übergeben werden soll. end else begin zqryMain.SQL.Text := 'INSERT INTO WARENVERKAUF1(KDNR,NAME,VORNAME,FIRMA,PRODUKT,ANZAHL,PREIS) VALUES(:KNR, :NAM, :VNA, :FIR, :PRO, :ANZ, :PRE)'; // keine Codevervollständigung benutzt wegen Schreibfehler (text). :-( end; // zqryMain.params.parseSQL(zqryMain.sql.text, True); // Quatsch. ??? Wo hast du das her? Ich kenne kein Beispiel wo man das parseSQL benötigt...nur im Notfalle ist es "vorhanden". // Parameter zuordnen zqryMain.ParamByName('KNR').AsString := Self[I].KDNR; zqryMain.ParamByName('NAM').AsString := Self[I].Name; zqryMain.ParamByName('VNA').AsString := Self[I].Vorname; zqryMain.ParamByName('FIR').AsString := Self[I].Firma; zqryMain.ParamByName('PRO').AsString := Self[I].Produkt; zqryMain.ParamByName('ANZ').AsInteger := Self[I].Anzahl; zqryMain.ParamByName('PRE').AsString := Self[I].Preis; // besser Typ Float // As... übergibt gleich den "richtigen" Typ...Value ist was für Weicheier :-), die nicht wissen welcher Wert übergeben werden soll. // Ausführen zqryMain.ExecSQL; end; finally zqryMain.Free; // keine Codevervollständigung benutzt wegen Schreibfehler (free). :-( end; end; Geändert von haentschman (18. Apr 2017 um 08:03 Uhr) |
![]() |
Registriert seit: 1. Mai 2016 Ort: Berlin 419 Beiträge Delphi 10.2 Tokyo Professional |
#4
vielen Dank. Habe nun die else-Bedingung auch eingefügt und so sieht nun die SaveToDB-Methode aus:
Delphi-Quellcode:
ich hoffe, dass es nun so richtig ist. Leider bleibt alles beim alten, denn weiterhin kommt nach dem Programmaufruf und dem Versuch einen Datensatz zu löschen oder zu bearbeiten die Meldung "Argument außerhalb des Bereiches" und nach dem Aufruf von LoadFromDB und bearbeiten verschieben sich die Spalten nach links (Name steht unter KDNR Vorname unter Name usw) Da muss doch irgendwo ein Fehler mit der Spaltenzuordnung sein, den ich einfach nicht finden kann.Wenn sich die ganze Sache verschoben hat, kann ich jedoch den Datensatz bearbeiten und auch löschen. Im Listview ist dann nur ID nicht mehr sichtbar und die Tabelle ist wie erwähnt nach links gerückt.
procedure TCustomerList.SavetoDB(con: TZConnection);
var zqryMain: TZQuery; i: Integer; begin zqryMain:=TZQuery.Create(nil); try zqryMain.connection:=con; for I := 0 to Self.Count-1 do begin if self[i].ID=-1 then zqryMain.SQL.Text:='UPDATE WARENVERKAUF1 SET KDNR=:KNR, NAME =:NAM, VORNAME=:VNA, FIRMA=:FIR, PRODUKT=:PRO, ANZAHL=:ANZ, PREIS=:PRE WHERE ID=:ID' else zqryMain.SQL.text:='INSERT INTO WARENVERKAUF1(KDNR,NAME,VORNAME,FIRMA,PRODUKT,ANZAHL,PREIS) VALUES(:KNR, :NAM, :VNA, :FIR, :PRO, :ANZ, :PRE)'; zqryMain.params.parseSQL(zqryMain.sql.text, True); if self[i].ID=-1 then begin zqryMain.Params.ParamValues['ID']:=self[i].ID; zqryMain.params.ParamValues['KNR']:=self[i].KDNR; zqryMain.params.paramValues['NAM']:=self[i].Name; zqryMain.params.paramValues['VNA']:=self[i].Vorname; zqryMain.params.ParamValues['FIR']:=self[i].Firma; zqryMain.Params.ParamValues['PRO']:=self[i].Produkt; zqryMain.Params.ParamValues['ANZ']:=self[i].Anzahl; zqryMain.params.paramValues['PRE']:=self[i].Preis; zqryMain.ExecSQL; end else begin zqryMain.params.ParamValues['KNR']:=self[i].KDNR; zqryMain.params.paramValues['NAM']:=self[i].Name; zqryMain.params.paramValues['VNA']:=self[i].Vorname; zqryMain.params.ParamValues['FIR']:=self[i].Firma; zqryMain.Params.ParamValues['PRO']:=self[i].Produkt; zqryMain.Params.ParamValues['ANZ']:=self[i].Anzahl; zqryMain.params.paramValues['PRE']:=self[i].Preis; zqryMain.ExecSQL; end; end; finally zqryMain.free; end; end; Bei der Suche drehe ich mich im Kreis. Ich danke Euch jedoch für Eure Geduld mit mir. Ich würde es gern doch noch packen, um dann Zeile für Zeile alles nochmals durchzugehen und daraus zu lernen. Das ist überhaupt der tiefe Sinn des ganzen.
Norbert
|
![]() |
Registriert seit: 17. Sep 2006 Ort: Barchfeld 27.666 Beiträge Delphi 12 Athens |
#5
Wo genau kommt denn der Fehler? Bemüh doch mal den Debugger, dafür ist er ja da.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein) Dieser Tag ist längst gekommen |
![]() |
Registriert seit: 9. Dez 2010 Ort: Mönchengladbach 1.740 Beiträge Delphi 6 Enterprise |
#6
Müsstest du nicht nach LoadFromDB usw. auch wieder FuelleListView aufrufen. Irgendwie bin ich mir nicht sicher ob CustomerList und ListView immer sauber synchron sind. Ausserdem verstehe ich nicht, warum du die Cutomerlist einmal in der Connect-Funktion von außen füllst und dann wieder mit der LoadFromDB-Methode von innern füllst, da reicht doch eine Version.
Dann hast du öfter solche Konstrukte:
Delphi-Quellcode:
Das wäre mir alles viel zu lang zum lesen, da würde ich mit Hilfsvariablen arbeiten und dem frmCustomer ein paar Propertys spendieren, die das füllen der ganzen TEdits intern erledigen:
if lvCustomer.Selected<>nil then
begin //Über den Index kann man nun auf jedes Object in der ObjektListe zugreifen //Damit bestücken wir das Formular mit den Werten aus den Eigenschaften des Objects frmCustomer.edtKDNR.Text:=inttostr(CustomerList[lvCustomer.Selected.Index].KDNR); frmCustomer.edtName.Text:=CustomerList[lvCustomer.Selected.Index].Name; frmCustomer.edtVorname.Text:=CustomerList[lvCustomer.Selected.Index].Vorname; //... if FRMCustomer.ShowModal=mrOK then begin //Object erzeugen nicht nötig, da es bereits besteht. Zugriff also möglich //für die Übertragung der Daten aus dem Formular CustomerList[lvCustomer.Selected.Index].KDNR:=strtoint(frmCustomer.edtKDNR.Text); CustomerList[lvCustomer.Selected.Index].Name:=frmCustomer.edtName.Text; //...
Delphi-Quellcode:
Läßt sich viel schöner lesen, denke ich. Alternativ könnte man dem frmCustomer auch einfach einen kompletten TCustomer übergeben und der regelt dann alles intern selbst, dann säh das nur noch so aus (man müsste dann aber das frmCustomer aufwendiger gestalten:
var index:integer;
customer:TCustomer; begin if lvCustomer.Selected<>nil then begin index:=lvCustomer.Selected.Index; customer:=CustomerList[index]; frmCustomer.KDNR:=customer.KDNR; frmCustomer.Nachname:=Customer.Name; frmCustomer.Vorname:=Customer.Vorname; //... if FRMCustomer.ShowModal=mrOK then begin //Object erzeugen nicht nötig, da es bereits besteht. Zugriff also möglich //für die Übertragung der Daten aus dem Formular Customer.KDNR:=frmCustomer.KDNR; Customer.Name:=frmCustomer.Nachname; //...
Delphi-Quellcode:
var index:integer;
begin if lvCustomer.Selected<>nil then begin index:=lvCustomer.Selected.Index; frmCustomer.customer:=CustomerList[index]; if FRMCustomer.ShowModal=mrOK then FuelleListView; end; end;
Ralph
|
![]() |
Registriert seit: 1. Mai 2016 Ort: Berlin 419 Beiträge Delphi 10.2 Tokyo Professional |
#7
Das ist der Stand der Dinge:
Delphi-Quellcode:
und das Hauptformular:
unit UCustomerList;
interface uses classes, system.Types, system.SysUtils, ZAbstractRODataset, ZAbstractDataset, ZDataset, ZAbstractConnection, ZConnection ,contnrs, System.Generics.Collections; type TCustomer=class private FID: integer; FKDNR : Integer; FName: string; FVorname: string; FFirma : string; FProdukt: string; FAnzahl : Integer; FPreis : Currency; procedure SetID(const Value: Integer); procedure SetKDNR(const Value: Integer); procedure SetName(const Value: string); procedure SetVorname(const Value: string); procedure SetFirma (const Value : string); procedure SetProdukt(const Value : String); procedure SetAnzahl (const Value : Integer); procedure SetPreis(const Value: Currency); public constructor Create; published property ID: integer read FID write SetID; property KDNR: integer read FKDNr write SetKDNR; property Name: string read FName write SetName; property Vorname: string read FVorname write SetVorname; property Firma: string read FFirma write SetFirma; property Produkt: string read FProdukt write setProdukt; property Anzahl: Integer read FAnzahl write SetAnzahl; property Preis: Currency read FPreis write SetPreis; end; TCustomerList=class(TObjectList<TCustomer>)//generische Liste (contnrs, System.Generics.Collections) procedure LoadFromDB(con: TZConnection); procedure SavetoDB(con: TZConnection); public function AddCustomer(KDNR: integer; Name: string; Vorname: string; Firma: string; Produkt: string; Anzahl: Integer; Preis: Currency):integer; end; implementation { TCustomer } constructor TCustomer.Create; begin inherited; self.FID:=-1; end; procedure TCustomer.SetAnzahl(const Value: Integer); begin FAnzahl := Value; end; procedure TCustomer.SetFirma(const Value: string); begin FFirma := Value; end; procedure TCustomer.SetID(const Value: Integer); begin FID := Value; end; procedure TCustomer.SetKDNR(const Value: Integer); begin FKDNR:= Value; end; procedure TCustomer.SetName(const Value: string); begin FName := Value; end; procedure TCustomer.SetPreis(const Value: Currency); begin FPreis := Value; end; procedure TCustomer.SetProdukt(const Value: String); begin FProdukt := Value; end; procedure TCustomer.SetVorname(const Value: string); begin FVorname := Value; end; { TCustomerList } function TCustomerList.AddCustomer(KDNR: integer; Name, Vorname, Firma, Produkt: string; Anzahl: Integer; Preis: Currency): integer; var Customer: TCustomer; begin Customer:=TCustomer.Create; Customer.KDNR:=KDNR; Customer.Name:=Name; Customer.Vorname:=Vorname; Customer.Firma:=Firma; Customer.Produkt:=Produkt; Customer.Anzahl:=Anzahl; Customer.Preis:=Preis; self.Add(Customer); end; procedure TCustomerList.LoadFromDB(con: TZConnection); var zqyMain: TZQuery; Customer: TCustomer; begin zqyMain:=TZQuery.Create(nil); Try self.Clear; //Dank TObjectlist werden auch alle bereits vorhandenen Objecte automatisch freigegeben zqyMain.connection:=con; zqyMain.sql.text:='SELECT * FROM WARENVERKAUF1'; zqyMain.active:=True; while not zqyMain.eof do begin Customer:=TCustomer.Create; Customer.ID:=zqyMain.FieldByName('ID').AsInteger; // Customer.KDNR:=zqyMain.fieldbyname('KDNR').AsInteger; Customer.Name:=zqyMain.fieldbyname('Name').AsString; Customer.Vorname:=zqyMain.fieldbyname('Vorname').AsString; Customer.Firma:=zqyMain.fieldByName('Firma').AsString; Customer.Produkt:=zqyMain.fieldbyname('Produkt').AsString; Customer.Anzahl:=zqyMain.FieldByName('Anzahl').AsInteger; Customer.Preis:=zqyMain.fieldbyname('Preis').AsCurrency; self.Add(Customer); zqyMain.Next; end; zqyMain.active:=False; Finally zqyMain.free; End; end; procedure TCustomerList.SavetoDB(con: TZConnection); var zqryMain: TZQuery; i: Integer; begin zqryMain:=TZQuery.Create(nil); try zqryMain.connection:=con; for I := 0 to Self.Count-1 do begin if self[i].ID=-1 then zqryMain.SQL.Text:='UPDATE WARENVERKAUF1 SET KDNR=:KNR, NAME =:NAM, VORNAME=:VNA, FIRMA=:FIR, PRODUKT=:PRO, ANZAHL=:ANZ, PREIS=:PRE WHERE ID=:ID' else zqryMain.SQL.text:='INSERT INTO WARENVERKAUF1(KDNR,NAME,VORNAME,FIRMA,PRODUKT,ANZAHL,PREIS) VALUES(:KNR, :NAM, :VNA, :FIR, :PRO, :ANZ, :PRE)'; zqryMain.params.parseSQL(zqryMain.sql.text, True); if self[i].ID=-1 then begin zqryMain.Params.ParamValues['ID']:=self[i].ID; zqryMain.params.ParamValues['KNR']:=self[i].KDNR; zqryMain.params.paramValues['NAM']:=self[i].Name; zqryMain.params.paramValues['VNA']:=self[i].Vorname; zqryMain.params.ParamValues['FIR']:=self[i].Firma; zqryMain.Params.ParamValues['PRO']:=self[i].Produkt; zqryMain.Params.ParamValues['ANZ']:=self[i].Anzahl; zqryMain.params.paramValues['PRE']:=self[i].Preis; zqryMain.ExecSQL; end else begin zqryMain.params.ParamValues['KNR']:=self[i].KDNR; zqryMain.params.paramValues['NAM']:=self[i].Name; zqryMain.params.paramValues['VNA']:=self[i].Vorname; zqryMain.params.ParamValues['FIR']:=self[i].Firma; zqryMain.Params.ParamValues['PRO']:=self[i].Produkt; zqryMain.Params.ParamValues['ANZ']:=self[i].Anzahl; zqryMain.params.paramValues['PRE']:=self[i].Preis; zqryMain.ExecSQL; end; end; finally zqryMain.free; end; end; end.
Delphi-Quellcode:
Ich habe auch das gesamte Programm in der jetzigen Fassung hochgeladen.
//Programm Kundenliste als ersten Versuch eine Objectlist zur Aufnahme der Daten
//für eine SQLite DB einzusetzen. //Hilfe dazu erhielt ich aus vorangegangenen Projekten in der DP vor allem von //Hobbycoder, Haentschmann und P80286, dennen ich hiermit nochmals danke. //Erstellt von EdAdvokat April 2017 unit uMainFRM; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, uFRMCustomer, uCustomerList, Vcl.ComCtrls, Data.DB, ZAbstractRODataset, ZAbstractDataset, ZDataset, ZAbstractConnection, ZConnection; type TFRMMainCustomer = class(TForm) lvCustomer: TListView; btnAdd: TButton; btnMake: TButton; btnDelete: TButton; btnAutomatic: TButton; btnClose: TButton; conMain: TZConnection; zqryMain: TZQuery; btnSaveDB: TButton; btnloadDB: TButton; edtKDNR: TEdit; edtName: TEdit; edtVorname: TEdit; edtFirma: TEdit; edtProdukt: TEdit; edtAnzahl: TEdit; edtPreis: TEdit; lblKDNR: TLabel; lblName: TLabel; lblVorname: TLabel; lblFirma: TLabel; lblProdukt: TLabel; lblAnzahl: TLabel; lblPreis: TLabel; edtTestID: TEdit; procedure btnAddClick(Sender: TObject); procedure btnMakeClick(Sender: TObject); procedure btnDeleteClick(Sender: TObject); procedure btnAutomaticClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TOBject); procedure btnCloseClick(Sender: TObject); procedure btnSaveDBClick(Sender: TObject); procedure btnloadDBClick(Sender: TObject); procedure lvCustomerClick(Sender: TObject); private { Private-Deklarationen } CustomerList: TCustomerList; procedure FuelleListView; procedure connect; procedure clearAllFields; procedure saveTableData(ID,KDNR,NAME,VORNAME,FIRMA,PRODUKT,ANZAHL,PREIS:string ); public { Public-Deklarationen } end; var FRMMainCustomer: TFRMMainCustomer; implementation {$R *.dfm} procedure TFRMMainCustomer.btnAutomaticClick(Sender: TObject); var r: integer; I: Integer; KDN, KDN1, Name, Vorname, Firma, Produkt: string; KDNR, Anzahl: Integer; Preis: Currency; begin Customerlist.Clear; Randomize; for I := 0 to 999 do begin r:=Random(10); case r of 0: Name:='Lehmann'; 1: Name:='Krausnig'; 2: Name:='Karlsberg'; 3: Name:='Ludwig'; 4: Name:='Antonia'; 5: Name:='Delphenhorst'; 6: Name:='Erinig'; 7: Name:='Fiedler'; 8: Name:='Gurrlig'; 9: Name:='Henzener'; end; r:=Random(10); case r of 0: Vorname:='Dieter'; 1: Vorname:='Klaus'; 2: Vorname:='Paul'; 3: Vorname:='Helga'; 4: Vorname:='Bernd'; 5: Vorname:='Friedel'; 6: Vorname:='Gustaf'; 7: Vorname:='Heinz'; 8: Vorname:='Joachim'; 9: Vorname:='Manfred'; end; r:=Random(10); case r of 0: KDN:='11'; 1: KDN:='12'; 2: KDN:='13'; 3: KDN:='14'; 4: KDN:='15'; 5: KDN:='16'; 6: KDN:='17'; 7: KDN:='18'; 8: KDN:='19'; 9: KDN:='20'; end; r:=Random(10); case r of 0: KDN1:='21'; 1: KDN1:='22'; 2: KDN1:='23'; 3: KDN1:='24'; 4: KDN1:='25'; 5: KDN1:='26'; 6: KDN1:='27'; 7: KDN1:='28'; 8: KDN1:='29'; 9: KDN1:='30'; end; r:=Random(10); case r of 0: Firma:='Schulbedarf'; 1: Firma:='Schule&mehr'; 2: Firma:='Hausmeisterserv.'; 3: Firma:='Lernen KG'; 4: Firma:='Lehrbuch Co.'; 5: Firma:='Möbel KG'; 6: Firma:='Hefte/Bücher'; 7: Firma:='Buch4you'; 8: Firma:='Lernen4all'; 9: Firma:='Bedarf Schule'; end; r:=Random(10); case r of 0: Produkt:='Stühle'; 1: Produkt:='Tische'; 2: Produkt:='Hefte'; 3: Produkt:='Blöcke'; 4: Produkt:='Bilder'; 5: Produkt:='Kreide'; 6: Produkt:='Bücher'; 7: Produkt:='Tafeln'; 8: Produkt:='Werkzeug'; 9: Produkt:='Mappen'; end; KDNR:=strtoint(KDN[1]+KDN1[1]+format('%.6d',[i])); Anzahl:=Random(20); r:=Random(10000); Preis:=r/100; CustomerList.AddCustomer(KDNR, Name, Vorname, Firma, Produkt, Anzahl, Preis ); end; FuelleListView; end; procedure TFRMMainCustomer.btnCloseClick(Sender: TObject); begin close; end; procedure TFRMMainCustomer.btnAddClick(Sender: TObject); var Customer: TCustomer; begin //Eingabeformular mit Defaultwerten bestücken FRMCustomer.edtKDNR.Text:=''; FRMCustomer.edtName.Text:=''; FRMCustomer.edtName.Text:=''; FRMCustomer.edtVorname.text:=''; FRMCustomer.edtFirma.text:=''; FrmCustomer.edtProdukt.Text:=''; FrmCustomer.edtAnzahl.text:=''; FRMCustomer.edtPreis.text:=''; if frmCustomer.ShowModal=mrOK then begin Customer:=TCustomer.Create; //Das Object Customer erzeugen. Customer.KDNR:=strtoint(frmCustomer.edtKDNR.Text); //Customer wird befüllt Customer.Name:=FRMCustomer.edtName.Text; Customer.Vorname:=FRMCustomer.edtVorname.text; Customer.Firma:=FRMCustomer.edtFirma.text; Customer.Produkt:=FRMCustomer.edtProdukt.text; customer.Anzahl:=strtoint(FRMCustomer.edtAnzahl.text); Customer.Preis:= StrToCurr(FRMCustomer.edtPreis.Text); CustomerList.Add(Customer); //Übergabe an CustomerList FuelleListView; end; end; procedure TFRMMainCustomer.btnDeleteClick(Sender: TObject); begin if lvCustomer.Selected<>nil then begin //Hier löschen wir das Object aus der ObjectListe //Durch die Eigenschaft OwnObjects, die zu jeder TObjectList gehört, //kümmert sich die ObjectListe selber darum, das entsprechende Object Customer //frei zugehen. Brauchen wir also nicht selber mache. //Ansonsten gilt grundsätzlich, was ich selber erzeuge gebe ich auch selber wieder frei CustomerList.Delete(lvCustomer.Selected.Index); FuelleListView; end; end; procedure TFRMMainCustomer.btnloadDBClick(Sender: TObject); begin CustomerList.LoadFromDB(conMain); FuelleListView; end; procedure TFRMMainCustomer.btnSaveDBClick(Sender: TObject); begin CustomerList.SavetoDB(conMain); end; procedure TFRMMainCustomer.btnMakeClick(Sender: TObject); begin if lvCustomer.Selected<>nil then begin //Über den Index kann man nun auf jedes Object in der ObjektListe zugreifen //Damit bestücken wir das Formular mit den Werten aus den Eigenschaften des Objects frmCustomer.edtKDNR.Text:=inttostr(CustomerList[lvCustomer.Selected.Index].KDNR); frmCustomer.edtName.Text:=CustomerList[lvCustomer.Selected.Index].Name; frmCustomer.edtVorname.Text:=CustomerList[lvCustomer.Selected.Index].Vorname; fRMCustomer.edtFirma.Text:=CustomerList[lvCustomer.Selected.Index].Firma; frmCustomer.edtProdukt.text:=CustomerList[lvCustomer.Selected.Index].Produkt; frmCustomer.edtAnzahl.Text:=IntToStr(Customerlist[lvCustomer.Selected.Index].Anzahl); frmCustomer.edtPreis.Text:=CurrToStr(Customerlist[lvCustomer.Selected.Index].Preis); if FRMCustomer.ShowModal=mrOK then begin //Object erzeugen nicht nötig, da es bereits besteht. Zugriff also möglich //für die Übertragung der Daten aus dem Formular CustomerList[lvCustomer.Selected.Index].KDNR:=strtoint(frmCustomer.edtKDNR.Text); CustomerList[lvCustomer.Selected.Index].Name:=frmCustomer.edtName.Text; CustomerList[lvCustomer.Selected.Index].Vorname:=FRMCustomer.edtVorname.Text; CustomerList[lvCustomer.Selected.Index].Firma:=FRMCustomer.edtFirma.text; CustomerList[lvCustomer.Selected.Index].Produkt:=FRMCustomer.edtProdukt.text; CustomerList[lvCustomer.Selected.Index].Anzahl:=strtoint(FRMCustomer.edtAnzahl.text); CustomerList[lvCustomer.Selected.Index].Preis:=strtocurr(FRMCustomer.edtPreis.Text); FuelleListView; end; end; end; procedure TFRMMainCustomer.clearAllFields; begin with FRMMainCustomer do begin edtKDNR.Clear; edtName.Clear; edtVorname.Clear; edtFirma.Clear; edtProdukt.Clear; edtAnzahl.Clear; edtPreis.Clear; end; end; procedure TFRMMainCustomer.connect; begin conMain.LibraryLocation:=ExtractFilePath(application.ExeName)+'sqlite3.dll'; conMain.Database:=ExtractFilePath(application.ExeName)+'WarenVK.sqlite'; conMain.Connected:=true; zqryMain.SQL.Clear; zqryMain.Params.Clear; zqryMain.SQL.Text:='SELECT * FROM WARENVERKAUF1'; zqryMain.Open; while not zqryMain.Eof do begin saveTableData(zqryMain.FieldByName('ID').AsString,zqryMain.FieldByName('KDNR').AsString,zqryMain.FieldByName('Name').AsString, zqryMain.FieldByName('Vorname').AsString,zqryMain.FieldByName('Firma').AsString,zqryMain.FieldByName('Produkt').AsString,zqryMain.FieldByName('Anzahl').AsString, zqryMain.FieldByName('Preis').AsString); zqryMain.Next end; zqryMain.Close; end; procedure TFRMMainCustomer.FormCreate(Sender: TObject); begin CustomerList:=TCustomerList.Create; connect; clearAllFields; end; procedure TFRMMainCustomer.FormDestroy(Sender: TOBject); begin CustomerList.Free; end; procedure TFRMMainCustomer.FuelleListView; var li: TListItem; I: Integer; begin lvCustomer.Items.BeginUpdate; Try //ListView mit Daten aus der ObjectList befüllen. lvCustomer.Items.Clear; for I := 0 to CustomerList.Count-1 do begin li:=lvCustomer.Items.Add; li.Caption:=inttostr(CustomerList[i].ID); // li.SubItems.Add(inttostr(CustomerList[i].KDNR)); // li.SubItems.Add(CustomerList[i].Name); li.SubItems.Add(CustomerList[i].Vorname); li.SubItems.Add(CustomerList[i].Firma); li.SubItems.Add(CustomerList[i].Produkt); li.SubItems.Add(inttostr(CustomerList[i].Anzahl)); li.SubItems.Add(FormatCurr('#0.00 €', CustomerList[i].Preis)); end; Finally lvCustomer.Items.EndUpdate; End; end; procedure TFRMMainCustomer.lvCustomerClick(Sender: TObject); var CurrentCustomerID : string; begin if lvCustomer.SelCount>=1 then begin CurrentCustomerID:=lvCustomer.Selected.Caption; // zqryMain.SQL.Clear; zqryMain.Params.Clear; zqryMain.SQL.Text:='SELECT * FROM WARENVERKAUF1 WHERE ID = :CID'; zqryMain.ParamByName('CID').AsString := CurrentCustomerID; // zqryMain.Open; edtKDNR.text:=zqryMain.FieldByName('KDNR').AsString; edtName.text:=zqryMain.FieldByName('Name').AsString; edtVorname.Text:=zqryMain.FieldByName('Vorname').AsString; edtFirma.text:=zqryMain.FieldByName('Firma').asstring; edtProdukt.text:=zqryMain.FieldByName('Produkt').AsString; edtAnzahl.text:=zqryMain.FieldByName('Anzahl').AsString; edtPreis.Text:=zqryMain.FieldByName('Preis').AsString; zqryMain.Next; // zqryMain.close; end; end; procedure TFRMMainCustomer.saveTableData(ID, KDNR, NAME, VORNAME, FIRMA, PRODUKT, ANZAHL, PREIS: string); var item:TListItem; begin Item:=lvCustomer.Items.Add; item.Caption:=ID; item.SubItems.Add(KDNR); // item.SubItems.Add(Name); item.SubItems.Add(Vorname); item.SubItems.Add(Firma); item.SubItems.Add(Produkt); item.SubItems.Add(Anzahl); item.SubItems.Add(Preis); end; end. Mein Debuggerversuch hat ergeben, dass vermutlich in der WiniNet.dll eine Kollision mit meinem Programm auftritt. Es ist die procedure TListHelper.Check.InsertRange, die dazu führt, dass die Meldung "Argument außerhalb des Bereiches" auftritt. Dies geschieht, wenn ich nach Programmaufruf versuche einen Datensatz zu löschen oder ihn zu bearbeiten. Rufe ich loadfromDB auf kann ich einen Datensatz bearbeiten und löschen. Auch die Verschieberei nach links in der Anzeige ist in diesem Fall nicht mehr aufgetreten. Blöd ist jetzt nur, dass beim Aufruf von SaveToDB ein Rödeln einsetzt und sich das Programm festfährt d.h. es dauert etwa 3 Minuten bis der Speicherungsprozess beendet ist. Ob die Methode SaveToDB wirklich so ok ist, oder sind da andere Unstimmigkeiten im Wege? Noch ein Wort zu Ralf: Danke für Deine Hinweise. Die werde ich in Ruhe ansehen, doch habe Verständnis dafür, dass ich auf diesem Gebiet so etwas von neu und unbeleckt bin, dass ich mich erst einmal darauf konzentrieren möchte, das das ganze zum vernünftigen Laufen kommt. Vermutlich habe ich an zu vielen Stellschrauben gedreht, dass nun das Speichern in die DB wieder Probleme macht. Den Debuggerversuch habe ich so durchgeführt, dass ich einen Haltepunkt gesetzt habe und dann die entsprechenden Handlungen im Programm selbst ausgeführt habe um dann mit F7 Schritt für Schritt weiter zu gehen. Da kam ich an dem o.g. Punkt an. Was ich daraus ableiten muss, weis ich leider nicht.
Norbert
|
![]() |
Registriert seit: 22. Feb 2017 1.017 Beiträge |
#8
Die Sache ist auch ganz einfach.
In der procedure connect öffnest du deine Datenbank und machst das Select über die Tabelle. Dort rufst du auch die Methode saveTableData auf, die wiederum die Daten auf deinem Listview ausgibt. Fertig. Wenn du dann über den Button Bearbeiten ein Item der ObjectList holen willst, geht das nicht, weil du da auch nie was reingeschrieben hat. Die ist nämlich leer. Die Vorgehensweise ist auch nicht so schlau. Besser wäre es (ich glaube so hatte ich es dir auch gezeigt) die Daten erst mal nur in die ObjectList einzulesen. Die entsprechende Methode "AddCustomer" gibt es in der CustomerList ja schon. Und wenn dann das Query abgearbeitet ist, also nach dem zqryMain.Close, dann mit FuelleListView den Inhalt der CustomerList in die Listview schreiben zu lassen. Und die Krönung wäre es noch, wenn die die Query-Abfrage noch in eine Methode der CustomerList übernimmst und die Objecte auch dort anlegen lässt. Die Connection könntest du als Parameter der Methode übergeben. Gruß Hobbycoder [Edit]: Grad gesehen, die Laderoutine gibt es in der CustomerList ja auch schon. Sie heißt LoadFromDB(...); Schaut die mal in der Mainform die proceudre btnloadDBClick an. Dort machst du es richtig. Und wenn man auf den Button "DB laden" klickt kann man auch editieren, weil dann die Customerlist auch Daten hat. Schmeiß das ganze Query mal aus der OnCreate raus und füge statt dessen mal btnloadDBClick(self) ein. Voila...dann geht's. In den Proceduren der Buttons Bearbeiten, Neu, löschen ... machst du es ja richtig. Und dadurch, dass du im OnCreate nur die Listview bestückt hast, hast du nicht mehr gemerkt, dass die ObjectList nicht geladen wurde. Fehler die mach zu Anfang gerne macht. Mit der Zeit kommt die Erfahrung und solche Fehler passieren dir nicht mehr. Im Übrigen, lass dich durch die vielen (richtigen) Hinweise nicht entmutigen. Sie sind gut gemeint. Ich würde dir aber raten erst einmal bei deinem jetzigen Code zu bleiben. Sicherlich kann man das anders auch noch schöner und besser machen. Aber wenn du jetzt anfängst alles immer wieder umzubauen, dann verwirrt dich das mehr, als alles andere. Besser, sein Ziel erst mal, wenn auch unschön, zu erreichen. Wenn es dann erst mal soweit läuft, dann entweder langsam umbauen, oder noch besser, mit dem hinzugewonnenen Wissen und der Erfahrung noch mal ganz neu aufbauen. Meine ersten Gehversuche in Delphi vor 20 Jahren sahen noch viel schlimmer aus. Geändert von Hobbycoder (18. Apr 2017 um 13:30 Uhr) |
![]() |
Registriert seit: 9. Dez 2010 Ort: Mönchengladbach 1.740 Beiträge Delphi 6 Enterprise |
#9
Bei Start des Programmes füllst du in der Connect-Funktion über SaveTableData die ListView.
Die CustomerList ist aber noch leer. Somit funktionieren die Delete und Make funktionen nicht. (Edit: also im Prinzip das, was Hobbycode auch sagt). Folgende Änderung reicht aber schon:
Delphi-Quellcode:
procedure TFRMMainCustomer.connect;
begin conMain.LibraryLocation:=ExtractFilePath(application.ExeName)+'sqlite3.dll'; conMain.Database:=ExtractFilePath(application.ExeName)+'WarenVK.sqlite'; conMain.Connected:=true; //neu CustomerList.LoadFromDB(conMain); FuelleListView; //alt kann weg, die ganze Fkt. SaveTableData kann mMn weg //zqryMain.SQL.Clear; //zqryMain.Params.Clear; //zqryMain.SQL.Text:='SELECT * FROM WARENVERKAUF1'; //zqryMain.Open; //while not zqryMain.Eof do //begin //saveTableData(zqryMain.FieldByName('ID').AsString, // zqryMain.FieldByName('KDNR').AsString, // zqryMain.FieldByName('Name').AsString, // zqryMain.FieldByName('Vorname').AsString, // zqryMain.FieldByName('Firma').AsString, // zqryMain.FieldByName('Produkt').AsString, // zqryMain.FieldByName('Anzahl').AsString, zqryMain.FieldByName('Preis').AsString); //zqryMain.Next //end; //zqryMain.Close; end;
Ralph
|
![]() |
Registriert seit: 28. Apr 2008 Ort: Stolberg (Rhl) 6.659 Beiträge FreePascal / Lazarus |
#10
Leider bleibt alles beim alten, denn weiterhin kommt nach dem Programmaufruf und dem Versuch einen Datensatz zu löschen oder zu bearbeiten die Meldung "Argument außerhalb des Bereiches"
Also nutze bitte den Debugger um die Stelle zu finden, die diese Meldung erzeugt! und nach dem Aufruf von LoadFromDB und bearbeiten verschieben sich die Spalten nach links (Name steht unter KDNR Vorname unter Name usw) Da muss doch irgendwo ein Fehler mit der Spaltenzuordnung sein, den ich einfach nicht finden kann.Wenn sich die ganze Sache verschoben hat, kann ich jedoch den Datensatz bearbeiten und auch löschen. Im Listview ist dann nur ID nicht mehr sichtbar und die Tabelle ist wie erwähnt nach links gerückt.
Wenn Du an genau einem Ort (Procedure/Funktion) Deine Liste Befüllst, dann hast Du auch den Überblick was da geschieht. Bei der Suche drehe ich mich im Kreis.
Gruß K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |