|
![]() |
|
Registriert seit: 24. Okt 2006 Ort: Seifhennersdorf / Sachsen 5.481 Beiträge Delphi 12 Athens |
#1
Moin...
![]() Du hast es so gewollt... ![]() Ohne Gewähr auf Vollständigkeit. Vergleiche das Original mit, dem Comparer deiner Wahl, dem hier... ![]() Ansonsten benutze einen Codeformatter und die Codevervollständigung... da passieren weniger Tippfehler. (false statt False)
Delphi-Quellcode:
unit uMainWarenVK;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, Vcl.Grids, Vcl.DBGrids, Vcl.ExtCtrls, Vcl.DBCtrls, // XPManager nicht mehr notwendig! Data.DB, system.UITypes, Data.DbxSqlite, Data.FMTBcd, Data.SqlExpr; type // !!! vernüftige Namen für die Controls oder Parameter, bei Controls mit Präfix für den Typ, vorzugsweise englisch und mit CamelCase...Denglisch sieht doof aus. :-) (BearbeitenClick) TMainFrm = class(TForm) // besser lvProductList: TListView; // Die Caption kannst du, unabhängig vom Namen, separat ändern! btnClose: TButton; // besser edtCustomerNumber: TEdit; Name: TEdit; Vorname: TEdit; Firma: TEdit; Produkt: TEdit; Anzahl: TEdit; Preis: TEdit; // besser, sagt was über den Inhalt aus mmoComment: TMemo; Neu: TButton; Bearbeiten: TButton; Uebernehmen: TButton; Abbruch: TButton; loeschen: TButton; // Auch auf die Form gelegte Komponenten sollen vernüftige Namen haben und nicht die Blubb1... qryMain: TSQLQuery; connectButton: TButton; executebutton: TButton; outputMemo: TMemo; // besser conMain: TSQLConnection; procedure btnCloseClick(Sender: TObject); procedure AbbruchClick(Sender: TObject); procedure BearbeitenClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure lvProductListClick(Sender: TObject); procedure loeschenClick(Sender: TObject); procedure NeuClick(Sender: TObject); procedure UebernehmenClick(Sender: TObject); procedure connectButtonClick(Sender: TObject); procedure executebuttonClick(Sender: TObject); private // Flags gehören nicht in die public Sichtbarkeit weil nicht von außen benutzt // Name besser IsEdit: boolean; procedure ClearAllFields; procedure RefreshItems(ID, KDNr, Name, Vorname, Firma, Produkt, Anzahl, Preis: string); public end; var MainFrm: TMainFrm; implementation {$R *.dfm} procedure TMainFrm.AbbruchClick(Sender: TObject); begin IsEdit := False; uebernehmen.Enabled := False; Abbruch.Enabled := False; lvProductList.SetFocus; end; //------------------------------------------------------------------------------ // laß das weg. Macht den Code imho schlechter lesbar. Es gibt bessere !Abgrenzungen. procedure TMainFrm.BearbeitenClick(Sender: TObject); begin IsEdit := True; uebernehmen.Enabled := true; abbruch.Enabled := true; end; procedure TMainFrm.connectButtonClick(Sender: TObject); begin try // Establish the connection. // !!! Kommentare nur wenn sie wirklich was über die "Funktion" aussagen...hier nicht conMain.Connected := True; executeButton.Enabled := True; showMessage('Connection erfolgreich!'); // später die Texte in Konstanten verlagern, wenn du die Texte mehrfach verwenden und nur einmal ändern willst. except on E: EDatabaseError do ShowMessage('Fehlermeldungstext connection:' + E.Message); end; end; procedure TMainFrm.ClearAllFields; //Initialiserung // !!! zur Methode des Formulars machen. begin // auch wenn es geht... *würg* // with MainFrm do ... obsolet mit der Verlagerung der Prozedure in pivate edtCustomerNumber.Clear; Name.Clear; // Name "Name" ist schlecht vorname.Clear; Firma.Clear; Produkt.Clear; Anzahl.Clear; Preis.Clear; mmoComment.Lines.Clear; name.SetFocus; end; procedure TMainFrm.RefreshItems(ID, KDNr, Name, Vorname, Firma, Produkt, Anzahl, Preis: string); // !!! zur Methode des Formulars machen. // Name besser. Paßt nun mit dem Inhalt der proedure zusammen. var Item: TListItem; begin Item := lvProductList.Items.Add; // durch die Verlagerung ins Formular kannst du direkt darauf zugreifen. 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; procedure TMainFrm.btnCloseClick(Sender: TObject); begin Close; end; procedure TMainFrm.executebuttonClick(Sender: TObject); begin outputMemo.ClearSelection; try qryMain.SQL.Text := 'SELECT * FROM WARENVERKAUF'; qryMain.Open; // besser // Active wird automatisch gesetzt except on E: Exception do outputMemo.text := 'Fehlermeldungstext execute: ' + E.Message; end; end; procedure TMainFrm.FormCreate(Sender: TObject); begin conMain.LibraryName := ExtractFilePath(Application.ExeName) + 'sqlite3.dll'; conMain.Params.Add('DataBase=' + ExtractFilePath(Application.ExeName) + 'WarenVK.sqlite'); // !!! keine hardcodierte Pfade verwenden conMain.Connected := True; qryMain.SQL.Clear; qryMain.Params.Clear; qryMain.SQL.Text := 'SELECT ID,KDNR,NAME,VORNAME,FIRMA,PRODUKT,ANZAHL,PREIS FROM WARENVERKAUF'; // Ich bevorzuge bei SQL immer die Großschreibung. Da grenzt sich das SQL von normalen Texten ab...kannst halten wie es willst...aber dann konsequent! qryMain.Open; while not qryMain.Eof do begin RefreshItems(qryMain.FieldByName('ID').AsString, qryMain.FieldByName('KDNR').AsString, qryMain.FieldByName('NAME').AsString, // Feldname "NAME" kann in die Hose gehen...reserviertes Wort. qryMain.FieldByName('VORNAME').AsString, qryMain.FieldByName('FIRMA').AsString, qryMain.FieldByName('PRODUKT').AsString, qryMain.FieldByName('ANZAHL').Asstring, qryMain.FieldByName('PREIS').Asstring); qryMain.Next; end; qryMain.Close; IsEdit := False; end; procedure TMainFrm.lvProductListClick(Sender: TObject); var CurrentCustomerID: string; // Name besser...eindeutiger begin if lvProductList.SelCount >= 1 then begin CurrentCustomerID := lvProductList.Selected.Caption; qryMain.SQL.Clear; qryMain.Params.Clear; qryMain.SQL.Text := 'SELECT * FROM WARENVERKAUF WHERE ID = :CID'; qryMain.ParamByName('CID').AsString := CurrentCustomerID; // besser Parameter qryMain.Open; edtCustomerNumber.Text := qryMain.FieldByName('KDNR').AsString; name.Text := qryMain.FieldByName('NAME').AsString; vorname.Text := qryMain.FieldByName('VORNAME').AsString; firma.Text := qryMain.FieldByName('FIRMA').AsString; Produkt.Text := qryMain.FieldByName('PRODUKT').AsString; Anzahl.Text := qryMain.FieldByName('ANZAHL').Asstring; Preis.Text := qryMain.FieldByName('PREIS').Asstring; mmoComment.Lines.Clear; mmoComment.Lines.Add(qryMain.FieldByName('MEMO').AsString); qryMain.Close; end; end; procedure TMainFrm.loeschenClick(Sender: TObject); var CurrentCustomerID: string; // Zeichen sind nicht mehr Mangelware begin if lvProductList.SelCount >= 1 then begin if MessageDlg('Sind Sie sicher, dass Sie den Datensatz löschen wollen?', mtconfirmation, [mbyes, mbno], 0) = mrYes then begin CurrentCustomerID := lvProductList.Selected.Caption; qryMain.SQL.Clear; qryMain.Params.Clear; qryMain.SQL.Text := 'DELETE FROM WARENVERKAUF WHERE ID = :CID'; qryMain.ParamByName('CID').AsString := CurrentCustomerID; qryMain.ExecSQL; // hier ist es richtig...gibt keine Datenmenge zurück lvProductList.Selected.Delete; end; end; end; procedure TMainFrm.NeuClick(Sender: TObject); begin ClearAllFields; uebernehmen.Enabled := True; abbruch.Enabled := True; IsEdit := False; end; procedure TMainFrm.UebernehmenClick(Sender: TObject); var CurrentCustomerID: string; // Zeichen sind nicht mehr Mangelware begin qryMain.SQL.Clear; qryMain.Params.Clear; //Parameter anlegen... passiert automatisch if IsEdit then // niemals auf True prüfen begin CurrentCustomerID := lvProductList.Selected.Caption; qryMain.SQL.Text := 'UPDATE WARENVERKAUF SET KDNR=:KDNR,NAME=:NAME,VORNAME=:VORNAME,FIRMA=:FIRMA,PRODUKT=:PRODUKT,ANZAHL=:ANZAHL,PREIS=:PREIS,MEMO=:MEMO WHERE ID = :CID'; qryMain.ParamByName('CID').AsString := CurrentCustomerID; // Namensgebung der Parameter verbesserungswürdig...schlechte Unterscheidung Feldname und Parameter qryMain.ParamByName('KDNR').Text := edtCustomerNumber.Text; qryMain.ParamByName('NAME').Text := Name.Text; qryMain.ParamByName('VORNAME').Text := vorname.Text; qryMain.ParamByName('FIRMA').Text := firma.Text; qryMain.ParamByName('PRODUKT').Text := produkt.Text; qryMain.ParamByName('ANZAHL').Text := Anzahl.Text; qryMain.ParamByName('PREIS').Text := preis.Text; qryMain.ParamByName('MEMO').Text := mmoComment.Lines.Text; qryMain.ExecSQL; // Wiederverwendbarkeit RefreshItems(CurrentCustomerID, edtCustomerNumber.Text, Name.Text, vorname.Text, firma.Text, produkt.Text, Anzahl.Text, Preis.Text); end else begin qryMain.SQL.Text := 'INSERT INTO WARENVERKAUF(KDNR,NAME,VORNAME,FIRMA,PRODUKT,ANZAHL,PREIS,MEMO) VALUES (:KDNR,:NAME,:VORNAME,:FIRMA,:PRODUKT,:ANZAHL,:PREIS,:MEMO)'; qryMain.ExecSQL; //LastID qryMain.SQL.Clear; qryMain.Params.Clear; qryMain.SQL.Text := 'SELECT LAST_INSERT_ROWID() AS ID FORM WARENVERKAUF'; qryMain.Open; CurrentCustomerID := qryMain.FieldByName('ID').AsString; qryMain.Close; // Wiederverwendbarkeit RefreshItems(CurrentCustomerID, edtCustomerNumber.Text, Name.Text, vorname.Text, firma.Text, produkt.Text, Anzahl.Text, Preis.Text); end; IsEdit := False; uebernehmen.Enabled := False; abbruch.Enabled := False; lvProductList.SetFocus; end; end. Geändert von haentschman ( 8. Apr 2017 um 12:34 Uhr) |
![]() |
Registriert seit: 1. Mai 2016 Ort: Berlin 419 Beiträge Delphi 10.2 Tokyo Professional |
#2
Ich danke dir für die Hinweise und Korrekturen und werde mir das alles genau einziehen. In deiner Version sind wundersam auch die bei mir aufgetretenen unicode-Probleme nicht mehr festzustellen. Woran lag das wohl? Jedenfalls erhalte ich jetzt alle Namen in deutscher Sprache. Wenn ich zu einzelnen Punkten deiner Hinweise nochmals Fragen habe, melde ich mich. Noch immer bin ich daran interessiert, eine Beispiellösung dazu zu erhalten, wie man das Ergebnis einer gesonderten Berechnung zB. a+b jeweils in TEdits dann in das Datenbankfeld übernimmt. Habe es mit einer Zuweisung DBEdit:=edit1.text... versucht, doch da stört ihn das die Datenbank nicht geöffnet sei... Wie macht man sowas richtig????
Erst einmal vielen Dank und ich werde wieder studieren ![]()
Norbert
|
![]() |
Registriert seit: 24. Okt 2006 Ort: Seifhennersdorf / Sachsen 5.481 Beiträge Delphi 12 Athens |
#3
Moin...
![]() ![]() Ich danke dir für die Hinweise und Korrekturen und werde mir das alles genau einziehen.
![]() ![]() ![]() In deiner Version sind wundersam auch die bei mir aufgetretenen unicode-Probleme nicht mehr festzustellen. Woran lag das wohl?
![]() ![]() ![]() Wie macht man sowas richtig????
![]() 2. In der Datenbank die Felder mit vernüftigen Namen anlegen. (Stichwort: reservierte Wörter, Präfix für Tabellennamen und Feldnamen...da hast du das Problem nicht (z.B. F_CUSTOMER_NAME)) 3. In der Datenbank die Felder mit den zu speicherenden Datenbanktypen anlegen. (nicht nur string) 4. Normalisierung der Datentabellen ![]() ![]() wie man das Ergebnis einer gesonderten Berechnung zB. a+b jeweils in TEdits dann in das Datenbankfeld übernimmt.
Delphi-Quellcode:
...besser mit dem Datensatz komplett speichern.
Query.SQl.Text := 'UPDATE xxxxx (F_SUM) VALUES (:SUM) WHERE F_BLUBB = :MID'; // F_SUM muß bestehen
Query.ParamByName(MID).AsInteger := FMyID; Query.ParamByName(SUM).AsFloat := StrToFloat(edtLinks.Text) + StrToFloat(edtRichts.Text); // !!! Mit den Edits zu rechnen ist schlechter Stil. Besser: Die Eingaben auf Gültigkeit prüfen, zusammenrechnen und in einer Variablen "zwischenspeichern". Dann erst das Ergebnis dem SQL übergeben. Query.ExecSQL; ![]() Dazu kommt noch die Prüfung auf Gültigkeit der eingegebenen Werte dazu. Siehe: ![]() ...wer hat den gesagt das Programmieren langweilig ist. ![]() Geändert von haentschman ( 8. Apr 2017 um 13:40 Uhr) |
![]() |
Registriert seit: 1. Mai 2016 Ort: Berlin 419 Beiträge Delphi 10.2 Tokyo Professional |
#4
Hallo Haenschmann, vielen vieln Dank für Deine Hilfe für mich alten Zausel. Ich werde mir all das ganz in Ruhe durchsehen und nachvollziehen. Natürlich ist es wichtig, die richtige Syntax zu wählen und ich werde mich natürlich noch mehr bemühen, dies zu beherzigen. Das Programmchen war jedoch ein Experimentalentwurf. Was das unicode-Problem angeht glaube ich den Übeltäter eingegrenzt zu haben. Du hast den Inhalt der Methode "übernehmen" völlig anders angelegt und vermutlich sind die ftString das Problem. Egal jetzt funktioniert es.
Nun einige Fragen: 1. Ist der connect-Button mit der Methode überhaupt nötig, wenn doch ohnehin beim Aufruf des Programms die Verbindung zur Datenbank hergestellt wird. 2. ist ebenso der execute-Button mit der Methode nötig, da ohnehin alles bereits läuft? 3. Du schreibst, dass an gleicher Stelle das ein active Setzen nicht notwenig sei, das dies automatisch geschieht:
Delphi-Quellcode:
Wieso und wo wird es automatisch auf active gesetzt? In FormCreate mit:
qryMain.SQL.Text := 'SELECT * FROM WARENVERKAUF';
qryMain.Open; // besser // Active wird automatisch gesetzt
Delphi-Quellcode:
?
conMain.Connected := True;
qryMain.SQL.Clear; Sicher ergeben sich noch einige weitere Fragen, denn ich bin erst vor gut 30 Min. nach Hause gekommen und wollte unbedingt gleich antworten und nochmals meinen Dank für Deine Bemühungen aussprechen. Ich habe mir all das im Selbstudium, aus Büchern (leider schon gut 10-15 Jahre alt) Youtube-Videos und anderen Tutorials angeeignet. So schleichen sich natürlich auch einige Unsauberkeiten ein. Ich war jedoch froh, dass ein Andreas Hiller eine Folge von Beispieltutorials in Fragen SQLite-Datenbank Anwendungen vorgetragen hat. Ich habe so glaube ich mit Deinen Hinweisen wieder einen großen Schritt nach vorn gemacht.
Norbert
|
![]() |
Registriert seit: 24. Okt 2006 Ort: Seifhennersdorf / Sachsen 5.481 Beiträge Delphi 12 Athens |
#5
Moin...
![]() ![]() natürlich noch mehr bemühen, dies zu beherzigen.
![]() ![]() 1. Codevervollständigung (besser als die eingebaute) 2. SourceHighlight Erweiterung (die bunten Striche) Da sieht man sofort in welcher "Ebene" man ist. 3. Cleaner 4. CodeFormatter ...usw. ![]() Ist der connect-Button mit der Methode überhaupt nötig, wenn doch ohnehin beim Aufruf des Programms die Verbindung zur Datenbank hergestellt wird.
![]() ![]() ist ebenso der execute-Button mit der Methode nötig, da ohnehin alles bereits läuft?
![]() ![]() ![]() ![]() Du schreibst, dass an gleicher Stelle das ein active Setzen nicht notwenig sei, das dies automatisch geschieht:
![]() ![]()
Delphi-Quellcode:
try
qryMain.SQL.Text := 'SELECT * FROM WARENVERKAUF'; // Im Open/ExecSQL wird die Query INTERN geschlossen und am Ende wieder INTERN auf Active := True gesetzt. qryMain.Open; except on E: Exception do outputMemo.text := 'Fehlermeldungstext execute: ' + E.Message; end;
Delphi-Quellcode:
Nochmal der Hinweis auf das E-Book:
procedure TMainFrm.FormCreate(Sender: TObject);
begin conMain.LibraryName := ExtractFilePath(Application.ExeName) + 'sqlite3.dll'; conMain.Params.Add('DataBase=' + ExtractFilePath(Application.ExeName) + 'WarenVK.sqlite'); // !!! keine hardcodierte Pfade verwenden conMain.Connected := True; //qryMain.SQL.Clear; // nicht notwendig...passiert intern //qryMain.Params.Clear; // nicht notwendig...passiert intern qryMain.SQL.Text := 'SELECT ID,KDNR,NAME,VORNAME,FIRMA,PRODUKT,ANZAHL,PREIS FROM WARENVERKAUF'; // Ich bevorzuge bei SQL immer die Großschreibung. Da grenzt sich das SQL von normalen Texten ab...kannst halten wie es willst...aber dann konsequent! qryMain.Open; while not qryMain.Eof do begin RefreshItems(qryMain.FieldByName('ID').AsString, qryMain.FieldByName('KDNR').AsString, qryMain.FieldByName('NAME').AsString, // Feldname "NAME" kann in die Hose gehen...reserviertes Wort. qryMain.FieldByName('VORNAME').AsString, qryMain.FieldByName('FIRMA').AsString, qryMain.FieldByName('PRODUKT').AsString, qryMain.FieldByName('ANZAHL').Asstring, qryMain.FieldByName('PREIS').Asstring); qryMain.Next; end; // qryMain.Close; // braucht nicht wirklich geschlossen zu werden. (Ausnahmen bestätigen die Regel (keine Anzeige der Daten)) Mit der nächsten "Ausführung" passiert eh ein Close. IsEdit := False; end; ![]() Geändert von haentschman ( 9. Apr 2017 um 07:50 Uhr) |
![]() |
Themen-Optionen | Thema durchsuchen |
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 |
LinkBack |
![]() |
![]() |