DBGrid mit DBLookupCombo als Editor

Rund um die LCL und andere Komponenten
Antworten
charlytango
Beiträge: 842
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

DBGrid mit DBLookupCombo als Editor

Beitrag von charlytango »

Hi,

Der Einbau einer DBLookupCombo als Editor in einen DBgrid hat nach einigem Suchen geklappt.
Aber da scheint es noch Haken und Ösen zu haben

gegeben sei eine Tabelle 'zahlung' mit den Feldern 'Betrag' und 'zahlungsart', wobei die zahlungsart als Code eingetragen wird.

Dazu gibt es die Tabelle DCODE mit den Feldern 'Code' und 'Codetext'
'Code' ist die zahlungsart die in die Tabelle 'Zahlung' eingetragen werden soll, 'Codetext' ist der Klartext dazu.

Als Editor fungiert ein DBLookupcombo der im Edit-Fall mit Hilde des Events OnSelectEditor wie folgt eingeblendet wird.

Code: Alles auswählen

procedure TForm1.DBGrid1SelectEditor(Sender: TObject; Column: TColumn;
  var Editor: TWinControl);
begin
  if DBLookupComboBox1.DataField=Column.FieldName then begin
    DBLookupComboBox1.BoundsRect:=DBGrid1.SelectedFieldRect;
    Editor:=DBLookupComboBox1;
    DBLookupComboBox1.Visible:=true;
  end;
end;


Klappt soweit, allerdings würde ich auch gerne im Browse-Modus des DBGrids den Klartext und nicht den Code angezeigt bekommen.
Vermutlich war ich da blind, denn sowas klappt sicher - bitte einen kräftigen Schubs in die richtige Richtung ;)

Was mich allerdings nachdenklich stimmt ist, wenn ich das DBLookupcombo auf ReadOnly stelle (damit der user den Klartext nicht editieren kann) bekomme ich eine Fehlermeldung:
Operation not allowed, dataset SQLQuery_Data is not in an edit or insert mode

Ohne ReadOnly klappt alles und mit ReadOnly geht nix mehr ?

Testcode liegt bei. (einfach Checkbox klicken zum Testen)

Bitte um Hilfe in diesen beiden Punkten
Dateianhänge
Grideditor.zip
Testapp für DBGrid mit DBLookupCombo als Editor
(330.92 KiB) 143-mal heruntergeladen

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: DBGrid mit DBLookupCombo als Editor

Beitrag von Michl »

charlytango hat geschrieben:Was mich allerdings nachdenklich stimmt ist, wenn ich das DBLookupcombo auf ReadOnly stelle (damit der user den Klartext nicht editieren kann) bekomme ich eine Fehlermeldung
So sollte es dann gehen:

Code: Alles auswählen

procedure TForm1.DBGrid1SelectEditor(Sender: TObject; Column: TColumn;
  var Editor: TWinControl);
begin
  if DBLookupComboBox1.DataField=Column.FieldName then begin
    DBLookupComboBox1.BoundsRect:=DBGrid1.SelectedFieldRect;
    Editor:=DBLookupComboBox1;
    DBLookupComboBox1.Visible:=true;
    SQLQuery_Data.Edit// <-- Eingefügt
  end;
end;   


charlytango hat geschrieben:Klappt soweit, allerdings würde ich auch gerne im Browse-Modus des DBGrids den Klartext und nicht den Code angezeigt bekommen.
Ich arbeite viel mit Joins, Subselects und anderen Relationen, führe Insert, Update und Co händisch aus und weiß daher nicht, wie es sonst gemacht wird.

Ich würde es so lösen:

Code: Alles auswählen

  SQLQuery_Data.SQL.Text :=
    'SELECT za.betrag, dc.codetext as zahlweise ' +
    'FROM zahlung AS za, dcode AS dc ' +
    'WHERE (za.zahlungsart = dc.code);';     
Da die Datenbankkomponenten keine komplexen Selects updaten können, würde ich dies nun händisch machen.

Vielleicht weiß ja af0815 oder ein anderer Datenbankguru hier mehr.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6197
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: DBGrid mit DBLookupCombo als Editor

Beitrag von af0815 »

Wenn man in der Query doppelklickt, dann kann man die Felder einfügen. Dort hat man auch die Möglichkeit die fieldkind auf Lookup zustellen. Damit sollte es auch im Grid angezeigt werden, wie mit dem Lookup beim Editieren. Aber Achtung die Lookup-table muß bereits aktiv sein bzw. richtig mit SQL bestückt sein, bevor man die Query mit dem lookup aktiv setzt, ansonsten gibt es ärger.

Ich habe schon länger nichts damit gemacht :-) Bin etwas eingerostet in den spezialitäten wie lookups, löse das meiste durchs programm (oder Framework).

Andreas
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

charlytango
Beiträge: 842
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: DBGrid mit DBLookupCombo als Editor

Beitrag von charlytango »

Danke erstmal f die Hinweise.

Just for The Records:

Damit der user den Text der DBDropdownCombo nicht ändern kann, muss man ihren Style ändern -- ReadOnly ist da falsch.

Code: Alles auswählen

DBLookupComboBox1.Style := csDropDownList;


Für die Anzeige des Klartextes im Grid wäre mein Zugang, dass ich die Anzeige mit dem Join von von Michl mache und die DBDropdowncombo direkt im SQLQuery updaten lasse. Geht nicht -- bei Queries mit Joins scheint das Dataset in einen ReadOnly-Modus zu gehen und damit ist editieren auch nicht möglich.

grml...

was mich im Moment ärgert ist dass ich keine schnelle Lösung für ein Allerweltsproblem finde - der Wunsch einen Klartext anzuzeigen und dahinter den Code zu schreiben ist ja nix Extravagantes.

wp_xyz
Beiträge: 4864
Registriert: Fr 8. Apr 2011, 09:01

Re: DBGrid mit DBLookupCombo als Editor

Beitrag von wp_xyz »

Hast du den Vorschlag von af0815 mit den Lookup-Feld ausprobiert? Da brauchst du gar keine LookupCombo, die ist schon im Grid eingebaut, wenn das Feld als Lookup-Feld erkannt wird.

Im Anhang findest du eine lauffähige Variante deines Programms mit dem Lookup-Feld für die Spalte Zahlungsart. Leider ist es in Lazarus etwas hakelig, ein Lookup-Feld einzurichten. Es ist schon eine Zeit her, seitdem ich das mit Delphi gemacht habe, aber ich meine mich zu erinnern, da ging das ganz flüssig.

Wichtig: Um im Designmode die DB öffnen zu können, muss der Datenbankname mit absolutem Pfad in der Connection eingetragen sein, sonst sucht die IDE relativ zum Lazarus-Verzeichnis; du solltest das später, wenn alles eingerichtet ist, wieder auf relativ zurücksetzen oder den Pfad erst zur Laufzeit eintragen. Genauso solltest du im ObjectInspector Connection auf Connected=false und die Queries auf Active=false setzen und erst zur Laufzeit wieder reaktivieren.

Das Lookup-Feld wird zusätzlich zu den durch die SQL-Anweisung der Query definierten Felder im feldeditor erzeugt (Rechtsklick auf Query, Neues feld, FieldType = ftLookup). Die zu setzenden Properties sind relativ selbsterklärend (LookupDataset, LookupKeyFields, LookupResultField). Einige Zeit grübeln musste ich über FieldName und KeyFields: FieldName ist der Name des erzeugten Lookup-Feldes, darf nicht derselbe sein wie der des Original-feldes, sonst spielt das Grid verrückt. KeyFields ist der Name des Feldes der Query, aus dem die Original-Werte (vor dem Lookup) stammen (hier: zahlungsart).

Im Grid richtest du zum Schluss für die anzuzeigenden Felder Columns ein.

P.S. Lazarus weiß zur Designzeit eigentlich, in welchem Ordner die exe des Programms landen wird und könnte den relativen Pfad zur DB auch richtig auflösen. Scheint mir ein Bug zu sein.
Dateianhänge
_sqlite_dblookupcombo.zip
(207.18 KiB) 158-mal heruntergeladen
Zuletzt geändert von wp_xyz am Sa 5. Nov 2016, 18:08, insgesamt 1-mal geändert.

charlytango
Beiträge: 842
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: DBGrid mit DBLookupCombo als Editor

Beitrag von charlytango »

ich hab kurz reingesehen --- chapeau...sehr seidige Lösung

Ich werde mir das gleich morgen reinziehen und versuchen es bei mir einzubauen.
Wiewohl ich befürchte dass das nicht 1:1 für mein TMemDataset laufen wird.

In diesem Fall geht es um einen Buchungswizared, der Zahlungen unterschiedlichen Typs (Bar, Bankomat, Teilzahlungen etc) in einem TMemdataset entgegen nimmt und dann pro zeile etwas komplexer mit SQL Inserts und Updates verbucht.
Bin gespannt was da noch auf mich lauert 8)

charlytango
Beiträge: 842
Registriert: Sa 12. Sep 2015, 12:10
OS, Lazarus, FPC: Laz stable (2.2.6, 3.x)
CPU-Target: Win 32/64, Linux64
Wohnort: Wien

Re: DBGrid mit DBLookupCombo als Editor

Beitrag von charlytango »

Hi,

Neuaufnahme des Themas damit eine Lösung im Forum auch gemeinsam gefunden wird.
Die aktuelle Aufgabe ist nach wie vor ein Lookup-Feld in einen DBGrid einzubauen -- nur diesmal zur Laufzeit.
Auch nach erheblichem Rechercheaufwand bringe ich es nicht hin.

IDE Bug ?
Die Version von wp_xyz funktioniert hervorragend, aber beim Nachbau musste ich bemerken dass ich in der IDE kein Lookupfeld
anlegen konnte. Die zum Speichern nötigen Buttons waren deaktiviert (Möglicherweise ein Bug?)
Das zuständige Dataset war dabei in der IDE nicht aktiv.
Einfache Datenfelder ließen sich nach Warnung dass die Feldauswahl nicht möglich ist, anlegen. Das Lookup-Feld hingegen nicht.
Meine Vermutung ist, dass eine Datenverbindung bestehen müsste, was ich in meiner IDE-Umgebung nicht habe.


Alleine deswegen brauche ich Einstellungen im Code, zudem sind künftig die Einstellungen in der IDE imho aufwendiger als z.B. einen Codeschnipsel zu kopieren und die Feldnamen anzupassen.


Ich habe zu Testzwecken versucht das programm von wp_xyz so abzuwandeln dass die in der IDE erzeugten Felder gelöscht und per code neu angelegt werden.

Mittlerweile bin ich mir sicher dass auch einiges bei der Definition der Felder fehlt, es klappt einfach nicht.

Die Feld-Attribute habe ich aus dem .lfm File übernommen.

Code: Alles auswählen

procedure TForm1.FormCreate(Sender: TObject);
var
  fld: TField;
begin
  SQLite3Connection1.DatabaseName := 'test.sqlite3'//alter Code von wp_xyz
  SQLite3Connection1.Connected := True;               //alter Code von wp_xyz
 
  // Alle zu Designtime definierten Felder in SQLQuery_Data löschen
 
  if SQLQuery_Data.Active then SQLQuery_Data.Close;
  SQLQuery_Data.Fields.Clear;
 
 
  //Felder per Code neu aufbauen
 
  fld := TCurrencyField.Create(nil);
  with fld do
  begin
    FieldKind := fkData;
    FieldName := 'Betrag';
    Index := 0;
    LookupCache := False;
    ProviderFlags := [pfInUpdate, pfInWhere];
    ReadOnly := False;
    Required := False;
    //Dataset := dsData; // this automatically adds the field to the Dataset's Fields collection.
                                    // irgendwo gefunden, keine Ahnung ob das stimmt
  end;
  SQLQuery_Data.Fields.Add(fld);
 
  fld := TStringField.Create(nil);
  with fld do
  begin
    DisplayWidth := 20;
    FieldKind := fkData;
    FieldName := 'zahlungsart';
    Index := 1;
    LookupCache := False;
    ProviderFlags := [pfInUpdate, pfInWhere];
    ReadOnly := False;
    Required := False;
    Size := 5;
    //Dataset := dsData; // this automatically adds the field to the Dataset's Fields collection.
  end;
  SQLQuery_Data.Fields.Add(fld);
 
  fld := TStringField.Create(nil);
  with fld do
  begin
    DisplayLabel := 'Zahlungsart';
    DisplayWidth := 20;
    FieldKind := fkLookup;
    FieldName := 'luZahlungsart';
    Index := 2;
    KeyFields := 'zahlungsart';
    LookupCache := True;
    LookupDataSet := SQLQuery_Code;
    LookupKeyFields := 'code';
    LookupResultField := 'codetext';
    ProviderFlags := [pfInUpdate, pfInWhere];
    ReadOnly := False;
    Required := False;
    //Dataset := dsData; // this automatically adds the field to the Dataset's Fields collection.
  end;
  SQLQuery_Data.Fields.Add(fld);
 
  SQLQuery_Data.FieldDefs.Update;   //Keine Ahnung ob das hier nötig ist ????
 
  //Queries öffnen
  SQLQuery_Code.Open;   //alter Code von wp_xyz
  SQLQuery_Data.Open;   //alter Code von wp_xyz
 
end;


Symptom ist eine Access Violation und ein leeres SQLQuery_Data.

sierdolg
Beiträge: 66
Registriert: Mi 24. Okt 2012, 15:50

Re: DBGrid mit DBLookupCombo als Editor

Beitrag von sierdolg »

Servus beisammen,

zwar vier Jahre später, aber es ist nach wie vor aktuell...

Schon seit Jahren versuche ich immer wieder mal, eine bessere Lösung für Nachschlagefelder als DBLookupCombo( auf einer Spalte mit Fremdschlüsselwerten) zu finden, das sich schlicht und ergreifend so verhält wie beispielsweise das Dropdown hinter "Suchzeitraum begrenzen:" auf der Seite http://www.lazarusforum.de/search.php. Oder so wie

Worauf es nur ankommt: Wenn man im Edit anfängt zu tippen, soll in der Dropdownliste der erste zur Eingabe passende Eintrag automatisch den Fokus erhalten. (Ich hätte das hinter der Eigenschaft Autoselect von TDBLookupComboBox vermutet, bleibt dies völlig ohne Effekt). Nun bin ich auf die TRxDBLookupCombo gestoßen, die genau das kann (aus dem Package "rx", das sich mittlerweile per OPM installieren läßt).
Oder wie einw auf "Listenfeld" eingestellte Feldspalte "Tabellen-Steuerelement" von LibreOffice Base.

Nachdem in besagtem Package auch ein leistungsfähigeres TRxDBGrid steckt, hätte ich angenommen, daß dieses in einer als mit FieldKind:=fkLookup vorbereiteten Spalte auch seine RxDBLookupCombo als als Eingabehilfe anbietet, doch leider erscheint auch hier nur die "normale" DBLookupComboBox, die gerade bei längeren Listen ohne Autoselect nur sehr mühsam zu benutzen ist.

:?:
Gibt es eine Möglichkeit, die beiden zu verbinden, um ein ergonomisch nutzbares DBGrid mit Listenauswahlfeldern zu erhalten? Oder kennt andere Alternativen? Jeder Hinweis wäre willkommen!

ErnstVolker
Beiträge: 326
Registriert: Di 17. Feb 2009, 10:44
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: DBGrid mit DBLookupCombo als Editor

Beitrag von ErnstVolker »

Guten Morgen Sierdolg,

vielleicht hilft Dir mein Vorschlag weiter. Wenn Du aus dem OnlinePackageManager den DBGridController installierst, dann hast Du den gewünschten Effekt, dass Du ähnlich der rxLookupCombobox bzw. der Suchfunktion auf der Forumstartseite ein Zeichen eingibst und nach Einträgen in der Listbox gesucht werden.

Beim compilieren des Package kam bei mir die Meldung, dass eine Unit nicht gefunden wurde. Ich habe die Zeile in meiner Naivität zur Programmierung einfach mal auskommentiert und die Komponente ließ sich installieren. Man muß im Quelltext dem Controller das Grid zuweisen auf das man ihn anwenden möchte. Bei mir (mittlerweile Linux Manjaro KDE-Desktop) geht es nicht im Objektinspektor.

Allen einen schönen Tag!

Viele Grüße
Volker

Antworten