AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Kundenliste

Ein Thema von EdAdvokat · begonnen am 14. Apr 2017 · letzter Beitrag vom 22. Apr 2017
Antwort Antwort
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.658 Beiträge
 
Delphi 12 Athens
 
#1

AW: Kundenliste

  Alt 16. Apr 2017, 06:47
Ich hatte es doch geschrieben: sobald auch nur ein Datensatz enthalten ist, wird Eof nie eintreten, solange Du Deine Datenmenge nicht mit Next auf den nächsten Datensatz positionierst.
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
  Mit Zitat antworten Zitat
EdAdvokat

Registriert seit: 1. Mai 2016
Ort: Berlin
419 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: Kundenliste

  Alt 16. Apr 2017, 19:11
Hallo zusammen, es ist mein erstes Projekt dieser Dimension und ich komme einfach nicht weiter und verzweifele, da ich bereits 2 Tage vergeblich den Fehler in diesem kleinen Übungsprogramm suche.
Nach dem Aufruf des Programms wird die SQLLite-Tabelle in einem Listview (auch mit ID!)exakt angezeigt und auch die TEdit-Felder sind parallel dazu zu sehen. Will ich jedoch einen Datensatz daraus löschen oder bearbeiten (entspr. Methoden per ButtonClick) kommt die Meldung
"Argument außerhalb des Bereiches". Will ich einen Datensatz hinzufügen oder auch mit DBSpeichern kommt: "Operation bei geschlossener Datenmenge nicht ausführbar" .
Nach dem Aufruf von Bearbeiten rückt die Anzeige im Listview nach links d.h. das Feld ID wird nun mit der KDNR belegt. Also die ID ist nicht mehr sichtbar und dafür in der Spalte wird die Kundennummer angezeigt und folgend Name bei KDNR usw.
Ich habe bereits alles versucht, was mir eingefallen ist, doch ich kam zu keinem vernünftigen Ergebnis.
Die Anzeige der Daten in den Edit-Feldern im FRMMain ist ebenfalls weg. Es wird wohl irgendwo was unterschlagen, vermutlich die ID.
Wo könnte ich suchen oder was müßte ich tun? Debugger.. na ja brachte mich nicht weiter, da mir wohl die Erfahrung fehlt.
Es ist für mich wirklich völliges Neuland und ich habe mich wirklich bemüht, doch jetzt stehe ich in dieser Sache vermutlich vor dem Aus, doch ich glaube es ist nur ein verdammter Denkfehler von mir.
Sollte sich jemand erbarmen, mir einen Tipp zu geben, wäre ich sehr dankbar. Anbei das Programm in der jetzigen Fassung und die beiden entscheidenen units:
Delphi-Quellcode:
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);
  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 }

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;
und weiter
Delphi-Quellcode:
//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);
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].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';
    // WHERE ID='+#39+ID+#39;
    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.
ich wäre sehr dankbar für eine Meinungsäußerung, damit ich das ganze nicht wirklich in die Tonne treten muss.
Angehängte Dateien
Dateityp: rar customerList2.rar (4,02 MB, 1x aufgerufen)
Norbert
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#3

AW: Kundenliste

  Alt 17. Apr 2017, 10:55
Hallo EdAdvokat
nicht in die Tonne kloppen, aber den Editor schließen und mit Papier und Bleistift ein Konzept erstellen.
Was willst Du?
Kundendaten verwalten.
was sind Kundendaten und was verstehst Du unter Verwalten?
Ich würde es jetzt so angehen, das das Verwalten in Delpi programmiert wird, also Du zunächst anzeigen willst. Dann vorhandene Daten ändern und neue Daten erfassen. Benötigst Du hierfür eine Darstellung oder drei unterschiedliche? Usw.
Nur solange es eben geht, vermeide es ein konkretes Feld (Name,Ort etc.) zu nutzen.
Der andere, nicht der erste oder zweite, ist es die Daten zu definieren und der DB eine Struktur zu geben.
Es ist für die die Daten vollkommen unerheblich wie die Benutzeroberfläche aussieht, und für die Oberfläche ist es egal wie sie an die Daten kommt. Wenn Du z.B. durch eine Datenmenge scrollen willst, ist das meiner Meinung nach eine Aufgabe der Oberfläche, genauso kannst Du aber jeden Datensatz einzeln abrufen, das wäre dann das Design der Schnittstelle.

So solltest Du Dir langsam erarbeiten was Du willst, bzw. was Dein Programm leisten soll.
Und wenn Du das Konzept erstellt hast, dann kannst Du daran gehen zu coden.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
EdAdvokat

Registriert seit: 1. Mai 2016
Ort: Berlin
419 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: Kundenliste

  Alt 17. Apr 2017, 12:47
Hallo K-H, es hört sich alles so einfach an. Ich finde einfach keinen Ansatzpunkt, den blöden Fehler oder die Fehler im Programm einzugrenzen geschweige denn sie zu beheben.
Doch nun zu Deinem Vorschlag, die Sache konzeptionell anzugehen. Ich möchte für mich beispielhaft eine Kundenliste über ein Eingabeformular mit Editfeldern erstellen, diese Daten dann in einem Listview und auch in Edit's eines Hauptformulars anzeigen lassen.
Diese Daten sollen in einer SQLite-3 Datenbanktabelle gespeichert werden.
Es soll möglich sein, neue Datensätze hinzuzufügen, die bestehenden Daten zu bearbeiten (ggf. zu korrigieren oder neue hinzuzufügen) und auch Datensätze zu löschen. Die Tabelle soll folgende Felder haben: ID, KDNR, Name, Vorname, Firma, Produkt, Anzahl, Preis.
All dies soll mittels Objectlist umgesetzt werden.
Da ich davon ausgehe, dass es nicht unbedingt erforderlich ist, die hinzugefügten/veränderten/gelöschten Daten explicit zu speichern oder aufzurufen, könnte auf die Methoden SavetoDB und LoadFromDB verzichtet werden.
Das sind also meine Vorstellungen und insoweit (außer den noch enthaltenen SavetoDB/LoadFromDB-Methoden) bereits im vorhandenen Projekt umgesetzt.
Bis hierher d'accord ?
Wie weiter? Ich habe mich an das Bestehende mühseelig herangearbeitet, was heißen soll über mehrere Schritte vergangener Projekte ohne Datenbankanbindung und mit einer Datenspeicherung per record in eine dat-Datei über den Hinweis auf eine objectlist hin zu dieser ersatzweise zum record und mit einer SQLite-3 Anbindung (beispielsweise).
Stand der Dinge: Hauptformular mit Listview und TEdit-Feldern (nur so für mich, um zu sehen, dass man die Daten auch so darstellen könnte) und Buttons für Aufruf eines Unterformulars "Hinzufügen" mit Editfeldern für KDNR, Name, Vorname, Firma, Produkt, Anzahl, Preis.
Dann weiter im Hauptformular bearbeiten-Methodenaufruf und Löschen-Methodenaufruf. Das war es eigentlich schon.
In der jetzigen Fassung sind also noch die beiden Methoden LoadFromDB und SaveToDB sowie die Möglichkeit 100 Datensätze automatisch zu erzeugen enthalten. Diese 3 wären sicher entbehrlich.
Der Aufruf des Programms läßt im Listview erkennen, dass die Daten mit ID,KDNR,Name,Vorname,Firma,Produkt,Anzahl,Preis exakt erscheinen.
Das war es schon mit den positiven Überraschungen. Denn Hinzufügen ruft zwar das Unterformular auf und ich kann neue Daten eingeben und das Formular schließen. Dann erscheint nur der neue Datensatz und nach dem Neuaufruf des Programms ist dieser jedoch nicht
enthalten. Er wurde also nicht gerspeichert.Bei Aufruf von bearbeiten und löschen erscheint: "Argument außerhalb des Bereiches", was immer das auch bedeuten soll.
Das ist der Stand der Dinge.
Norbert
  Mit Zitat antworten Zitat
Hobbycoder

Registriert seit: 22. Feb 2017
1.002 Beiträge
 
#5

AW: Kundenliste

  Alt 17. Apr 2017, 13:23
Im Grunde bist du doch schon recht weit. Nur die SaveToDB-Routine läuft noch nicht so, wie du es dir vorgestellt hast (wenn ich das richtig verstanden habe).

Es gibt ja grundsätzlich 2 Möglichkeiten mit Daten in einer DB zu arbeiten.
1. Mit laufender Verbindung zu der Tabelle, z.B. über ein geöffnetes TQuery oder TTable und über ein DataSource das ganze an Datensensitive Componenten zu binden z.B: DBEdit, DBCompobox, etc.
Dann kann man über Query.Edit einen Datensatz editieren. Die angebundenen Controls erhalten dann automatisch die Möglichkeit deren Daten zu ändern. Und über Query.POst btw. Query.Cancel das Editieren zu beenden. Gleiches würde z.B. über Query.Append mit neuen Datensätzen gehen.
Wie das dann genau unter Zeos aussieht, müsstest du dir erarbeiten

2. So wie du es jetzt hast. Daten komplett in eine ObjectList einlesen. Dann Objekte Bearbeiten, löschen oder hinzufügen und wieder komplett speichern.
Doch beim Speichern stellt sich dann aber die Frage: Ist der Datensatz nun neu oder ist er nur editiert? Davon ist nämlich abhängig, ob du beim Speichern über SQL das mit Insert oder mit Update machst.
Ich mache das immer folgerndermaßen. Man kann eigentlich in der SQL-DB in den Tabellen ein Datenfald mit Autoincrement versehen. Oft auch Lfdnr (laufende Nummer) oder ID benannt. Jeder Datensatz erhält darüber eine eindeutige Nummer innerhalb seiner Tabelle. Diese Nummer wird nicht noch einmal vergeben, auch wenn der Datensatz gelöscht wird. Und sie wird automatisch vergeben, also braucht/darf sie beim Insert nicht angegeben werden.
So, nun würde ich in den Objecten diese ID als Integer mit aufnehmen und beim LoadFromDB mit laden. Außerdem würde ich den Objecten eine Constructor spendieren in dem diese ID mit -1 vorbelegt ist.
Delphi-Quellcode:
Type
Tblabla=class
  private
    FID: Integer;
    procedure SetID(value: Integer);
  public
    constructor Create;
  published
    property ID: Integer read FID write SetID;
end;

constructor Tblabla.Create;
begin
  inherited;
  self.FID:=-1;
end;
Nun erhält jedes neue Object der Objectliste in ID den Wert -1.
Beim LoadFromDB wird ja auch für jeden Datensatz ein Object erzeugt, aber genau dort wird auch die ID aus der DB geladen, also hat ID dann der autoincrement-wert aus der DB und nicht mehr -1.

Wenn du nun in der Objektliste ein neues Object anlegst, bekommt es aber automatisch als ID erst einmal -1.
Jetzt kannst du bei SaveToDB anhand der ID wunderbar unterscheiden, ob ein Insert oder ein Update notwendig ist:
Delphi-Quellcode:
Procedure TblablaList.SaveToDB(....);
begin
  for i:=0 to blablaList.Count-1 do
  begin
    if blablaList[i].ID=-1 then
      q.sql.text:='Insert into Kundenliste (Name, Vorname) VALUES (:name, :Vorname)' eise
      q.sql.text:='Update Kundenliste SET Name=:name, Vorname=:Vorname where ID=:id';
   ....
  end;
end;
Möglicherweise hilft dir das etwas weiter.
Gruß Hobbycoder
  Mit Zitat antworten Zitat
EdAdvokat

Registriert seit: 1. Mai 2016
Ort: Berlin
419 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#6

AW: Kundenliste

  Alt 17. Apr 2017, 15:36
Danke zunächst. Habe hoffentlich richtig Deine Hinweise umgesetzt:
Delphi-Quellcode:
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;
und weiter:
Delphi-Quellcode:
constructor TCustomer.Create;
begin
  inherited;
  self.FID:=-1;
end;
Methode SaveToDB:
Delphi-Quellcode:
procedure TCustomerList.SavetoDB(con: TZConnection);
var
  zqryMain: TZQuery;
  i: Integer;
  CustomerListe: TCustomerList;
begin
  zqryMain:=TZQuery.Create(nil);
  try
    zqryMain.connection:=con;
    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);
for i:=0 to self.count-1 do
begin
  if CustomerListe[i].ID=(-1) then
  zqryMain.SQL.text:='INSERT INTO WARENVERKAUF1(KDNR,NAME,VORNAME,FIRMA,PRODUKT,ANZAHL,PREIS) VALUES(:KNR, :NAM, :VNA, :FIR, :PRO, :ANZ, :PRE)else
  zqryMain.SQL.Text:='UPDATE WARENVERKAUF1 SET KDNR=:KNR, NAME =:NAM, VORNAME=:VNA, FIRMA=:FIR, PRODUKT=:PRO, ANZAHL=:ANZ, PREIS=:PRE WHERE ID=: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;
  zqryMain.Next;
end;
finally
  zqryMain.free;
end;
end;
Ist das bis hierher exakt?
Ergebnis ist jedoch weiterhin, bei löschen und bearbeiten kommt "Argument außerhalb des Bereiches".
Nachdem ich LoadFromDB aufgerufen habe kann ich einen Datensatz bearbeiten, jedoch nach OK verschiebt sich die Listview-Ansicht nach links dh. Die Anzeige für die ID wird mit der KDNR und die der KDNR mit Name... belegt. Also alles wie gehabt.
Norbert

Geändert von EdAdvokat (17. Apr 2017 um 15:49 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.658 Beiträge
 
Delphi 12 Athens
 
#7

AW: Kundenliste

  Alt 17. Apr 2017, 15:43
Beim Ändern von Daten ist das Next wieder überflüssig, welcher nächste Datensatz sollte das auch sein?
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
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es 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

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:32 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz