Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Wie definiere ich ein Lookup-Feld für eine TQuery? (https://www.delphipraxis.net/60561-wie-definiere-ich-ein-lookup-feld-fuer-eine-tquery.html)

MPirnstill 9. Jan 2006 11:22

Datenbank: MS-SQL-Server • Version: 2000 • Zugriff über: Delphi 2.0 - BDE

Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Hi Leute!

Ich versuche mein Problem mal neue zu beschreiben, da es bei meinem letzten Thread leider nicht zum Erfolg geführt hat.

Problem:
Ich versuche ein Lookup-Feld für eine TQuery (wird auch zur Laufzeit erzeugt) während der Laufzeit zu erzeugen.

Query ist zu diesem Zeitpunkt bereits erzeugt, dann

Delphi-Quellcode:
with FQry do
begin
  if State <> dsInactive then
    close;
  RequestLive := True;
  ParamByName('Verfahren').asInteger := FVerfahren;
  ParamByName('Pruef_ID').asString  := FPruef_ID;
  Open;
  .
  .
Jetzt weise ich noch ein DisplayFormat zu. So weit, so gut. Und dann möchte ich ein Lookup-Feld zu erzeugen

Delphi-Quellcode:
  TBooleanField(FieldByName('Vorsitz')).DisplayValues := 'V.; ';
  FieldDefs.Add('myLookupFeld', ftString, 50, False);
  .
  .
Bis hier scheint es auch zu funktionieren. Ich konnte mir beim debuggen, den Eintrag in FieldDefs anzeigen lassen.

Delphi-Quellcode:
  TStringField(FieldByName('myLookupFeld')).OnGetText := myLookupFeldGetText;
Wenn ich jetzt versuche, mit vorstehender Anweisung die Daten bereit zu stellen (bei onGetText Zugriff auf andere Query), kennt Delphi 'myLookupFeld' nicht.

Was mache ich hier falsch? Oder besser wie kann ich es richtig machen?
Ich möchte keinen JOIN in meiner SQL-Anweisung verwenden, da ich die Query update-fähig haben möchte.

Gruß

shmia 9. Jan 2006 12:33

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Mit FieldDefs liegst du falsch. Du musst das Property Fields[] um ein Feld erweitern.
Delphi-Quellcode:
type
   TDataSetCracker = class(TDataSet); // Zugriff auf protected Member ermöglichen
function AddLookupField(ADataSet: TDataSet; AFieldClass: TFieldClass; const AFieldName: string; const AFieldSize: Integer = 0): TField;
   procedure CreateAllFields(DS: TDataSet);
   begin
      with TDataSetCracker(DS) do
      begin
         DestroyFields;
         FieldDefs.Update;
         CreateFields;
      end;
   end;
begin
   Result := nil;

   // Falls keine Felder im DataSet sind werden alle vorhandenen Felder angelegt.
   // Falls Felder vorhanden sind, so darf "CreateAllFields" nicht aufgerufen
   // werden, da die vorhandenen Felder nicht mehr gelöscht werden dürfen.
   if ADataSet.FieldCount = 0 then
      CreateAllFields(ADataSet);

   // Falls das LU Field schon existiert wird nix mehr gemacht.
   if ADataSet.FindField(AFieldName) <> nil then
      Exit;

   // LU Field anlegen, wenn weitere Eigenschaften des Feldes gesetzt
   // werden sollen, kann dies über den Rückgabewert gemacht werden.
   Result := AFieldClass.Create(ADataSet);
   Result.Name := ADataSet.Name + Copy(AFieldClass.ClassName,2,666) + AFieldName;
   Result.FieldName := AFieldName;
   Result.Size := AFieldSize;
   Result.FieldKind := fkLookup;
   Result.DataSet := ADataSet;
end;
Nach dem Öffnen der Query:
Delphi-Quellcode:
with AddLookupField(Fqry, TStringField, 'Landname', 35) do
begin
   LookupDataset := FqryLookup;
   LookupKeyfields := 'LandId';
   LookupResultField := 'Landname_deutsch';
end;

MPirnstill 9. Jan 2006 12:48

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Zitat:

Zitat von shmia
Delphi-Quellcode:
function AddLookupField(ADataSet: TDataSet; AFieldClass: TFieldClass; const AFieldName: string; const AFieldSize: Integer = 0): TField;
   procedure CreateAllFields(DS: TDataSet);
   begin
      with TDataSetCracker(DS) do
      begin
         DestroyFields;
         FieldDefs.Update;
         CreateFields;
      end;
   end;
begin
.
.
end;

Hey! Vielen Dank für deine Antwort!

Ich wollte es gleich ausprobieren, aber beim übertragen fiel mir "TDataSetCracker" auf. Was ist das für ein Type? :?:
Bei Delphi 2.0 (auch bei D7) finde ich darüber nichts in der Hilfe und aus deinem Code-Snipet kann ich leider auch nicht erkennen was für ein Typ dies ist.

Gruß

shmia 9. Jan 2006 12:54

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Zitat:

Zitat von MPirnstill
Ich wollte es gleich ausprobieren, aber beim übertragen fiel mir "TDataSetCracker" auf. Was ist das für ein Type? :?:

Tja, hatte ich vergessen; ist nun aber oben nachgetragen. :|

MPirnstill 9. Jan 2006 13:31

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
@shmia

Ich habe das jetzt eingebaut, aber bei der Anweisung:
Delphi-Quellcode:
  Result.DataSet := ADataSet;
bekomme ich immer die Fehlermeldung:
Zitat:

Operation bei geöffneter Datenmenge nicht ausführbar
Hat ja auch recht, "with AddLookupField .. do"
wird ja erst nach dem öffnen von "FQry" ausgeführt.

Mache ich da noch etwas falsch?

Ach ja, "CreateAllFields" habe ich erstmal auskomentiert, da die die Befehle "DestroyFields" und "CreateFields" unbekannt sind. Irgendwie scheint das mit dem Zugriff auf die Protected-Methoden von TDataSet noch nicht zu funktionieren. Vielleicht kennt TDataset diese Methoden unter Delphi 2.0 noch nicht oder sie heißen anders.
Aber hier dran kann der o.a. Fehler doch nicht liegen, oder?

Gruß

shmia 9. Jan 2006 13:53

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Zitat:

Zitat von MPirnstill
Ach ja, "CreateAllFields" habe ich erstmal auskomentiert, da die die Befehle "DestroyFields" und "CreateFields" unbekannt sind. Irgendwie scheint das mit dem Zugriff auf die Protected-Methoden von TDataSet noch nicht zu funktionieren. Vielleicht kennt TDataset diese Methoden unter Delphi 2.0 noch nicht oder sie heißen anders.
Aber hier dran kann der o.a. Fehler doch nicht liegen, oder?

Doch, das scheint mir das Problem zu sein. :-(
Wenn du den Sourcecode hast, kannst du ja nachprüfen, ob es in Unit db.pas die virtuellen
Methoden TDataSet.CreateFields und TDataSet.DestroyFields gibt. (sie müssten protected sein)
Mein Sourcecode ist mit Delphi 5 getestet.

MPirnstill 9. Jan 2006 14:15

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Die stehen bei Delphi 2.0 leider unter "Private".

MPirnstill 9. Jan 2006 14:21

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Aber ich kann mir nicht vorstellen, daß das Problem sein soll. Wenn ich es im Debug-Modus durch gehe, ist
Delphi-Quellcode:
aDataSet.FieldCount > 0
und deshalb wird diese interne Prozedur garnicht aufgerufen.

marabu 9. Jan 2006 14:23

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Hallo Micha,

wenn du sonst keine Probleme mit dem Code hast, dann würde ich die Funktion CreateAllFields() einfach komplett weglassen. Damit hast du dann wieder das Verhalten, welches auch der Feld-Editor zeigt: du musst selbst entscheiden, ob du alle oder nur ausgewählte Felder persistent machen möchtest. Borland ist übrigens der Meinung, dass persistente Felder grundsätzlich im Feld-Editor erzeugt werden sollten. Keine Ahnung warum das für dich inakzeptabel ist.

Grüße vom marabu

MPirnstill 9. Jan 2006 14:32

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Zitat:

Zitat von marabu
Hallo Micha,

wenn du sonst keine Probleme mit dem Code hast, dann würde ich die Funktion CreateAllFields() einfach komplett weglassen. Damit hast du dann wieder das Verhalten, welches auch der Feld-Editor zeigt: du musst selbst entscheiden, ob du alle oder nur ausgewählte Felder persistent machen möchtest. Borland ist übrigens der Meinung, dass persistente Felder grundsätzlich im Feld-Editor erzeugt werden sollten. Keine Ahnung warum das für dich inakzeptabel ist.

Grüße vom marabu

Das ist für mich nicht inakzeptabel, aber meine Query wird in einer von mir geschriebenen Klasse dynamisch erzeugt. Ich versuche lediglich, anstatt einer Adress-ID einen Namen anzuzeigen, dabei aber die Update-Fähigkeit der Query zu erhalten, was ja bedeutet, daß nur eine Tabelle in der SQL-Anweisung angesprochen werden darf.

Wenn du einen einfacheren Weg weiß, teile mir diesen doch bitte mit. Ich bin für neue Vorschläge offen.

Das weglassen von "CreateAllFields" ist ja auch nicht das Problem, aber das was ich unter #5 beschrieben hab. und das kann ich nicht so einfach weglassen.

Gruß

marabu 9. Jan 2006 15:05

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Ich habe leider kein D2 zum Testen parat, aber unter D7 habe ich mir ein kleines Testprojekt erstellt, bei dem ich die Anrede (Herr oder Frau) über eine Lookup-Tabelle auswähle. Die Lookup-Tabelle und auch die Query sind zu Beginn inaktiv und werden erst nach der Erstellung des Lookup-Feldes aktiviert.

Delphi-Quellcode:
procedure TDataForm.FormCreate(Sender: TObject);
begin
  CreateLookupField;
  Database.Connected := true;
  Anreden.Open;
  QKontakte.Open;
end;

procedure TDataForm.CreateLookupField;
var
  f: TStringField;
begin
  f := TStringField.Create(QKontakte);
  with f do
  begin
    Name := QKontakte.Name + FieldName;
    Size := 50;
    DisplayLabel := 'Anrede';
    DisplayWidth := 21;
    FieldName := 'ANREDE';
    FieldKind := fkLookup;
    LookupDataSet := Anreden;
    KeyFields := 'ANR_ID';
    LookupKeyFields := 'ID';
    LookupResultField := 'PHRASE';
    DataSet := QKontakte; // Feld in Feldliste aufnehmen
    Index := 2; // Feld an gewünschte Stelle verschieben
  end;
end;
Ich habe den thread erst jetzt genau durchgelesen. Andreas hat klar erkannt, wenn du die Query dynamisch erstellst, dann müssen alle Felder per Code persistent gemacht werden. Ohne eine Routine wie CreateAllFields() kannst du gar nicht anfangen zu testen.

Nachtrag: Wahrscheinlich ist es nur ein ganz kleiner Fehler im Code von Andreas - vor dem Aufruf vom FieldDefs.Update muss noch FieldDefs.Updated auf false gesetzt werden - der dir den Erfolg verweigert. Und ganz zum Schluss wirst du die Schlüsselfelder noch verstecken wollen.

marabu

MPirnstill 10. Jan 2006 08:13

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Zitat:

Zitat von marabu
Ich habe den thread erst jetzt genau durchgelesen. Andreas hat klar erkannt, wenn du die Query dynamisch erstellst, dann müssen alle Felder per Code persistent gemacht werden. Ohne eine Routine wie CreateAllFields() kannst du gar nicht anfangen zu testen.

marabu

Hallo Marabu,

du hast jetzt in deinem Beispiel diese 'CreateAllFields()' auch nicht verwendet.

Ich habe jetzt jedenfalls mal versucht dein Beispiel in mein Programm einzubauen. Wenn ich dann den 'Open' für meine Query ausführe, bekomme ich die Fehlermeldung
Zitat:

Feld 'ID_Mitglied' nicht gefunden.
So heißt mein 'KeyField' in 'FQry'. Und da ich mit '*' selektiere müßte es eigentlich da sein.

Ist dies jetzt z.B. so ein Fall, daß die anderen Felder nicht mit 'CreateAllFields' erzeugt wurden? :?:

Ich habe beim Testen vorm 'Open' nachgesehen, in der FieldDefs-Liste sind alle 16 Spalten meiner Tabelle, aber in der Fields-Liste steht nur das Lookup-Feld. Wenn ich das jetzt richtig interpretiere, muß ich vorm erzeugen des Lookup-Feldes noch
Zitat:

- vor dem Aufruf vom FieldDefs.Update muss noch FieldDefs.Updated auf false gesetzt werden -
Die Eigenschaft 'FieldDefs.Updated' kennt Delphi unter 2.0 anscheined noch nicht, hab mal einfach
Delphi-Quellcode:
FQry.FieldDefs.Clear;
FQry.FieldDefs.Update;
probiert, aber der Erfolg bzw. Mißerfolg bleibt derselbe. Mein KeyField 'ID_Mitglied' kennt Delphi nicht.

Gruß

MPirnstill 10. Jan 2006 08:47

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Hallo nochmal!

Wie komme ich denn jetzt an diese Methoden (DestroyFields, CreateFields) des TDataSet.

Zitat:

Ohne eine Routine wie CreateAllFields() kannst du gar nicht anfangen zu testen.
Ich habe, wie gesagt, in der Unit DB.PAS nachgesehen, dort sind die unter Delphi 2.0 leider in Private deklariert und nicht in Protected. Kann ich die einfach verschieben oder würde das böse viel durcheinander bringen? :?:

Gruß

shmia 10. Jan 2006 08:52

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Zitat:

Zitat von MPirnstill
Ich habe, wie gesagt, in der Unit DB.PAS nachgesehen, dort sind die unter Delphi 2.0 leider in Private deklariert und nicht in Protected. Kann ich die einfach verschieben oder würde das böse viel durcheinander bringen? :?:

Du kannst die Unit in dein Projektverzeichnis kopieren und zum Projekt hinzufügen.
Danach kannst du DB.PAS ändern.
Von der Orginalen Datei würde ich die Finger lassen !
Auf die Verwendung von Packages musst du dann aber verzichten.
Hat Delphi 2 überhaupt schon Packages ? Lange her...

MPirnstill 10. Jan 2006 09:11

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Hallo shmia,

hab die Unit DB.PAS rüberkopiert in mein Projektverzeichnis und meinem Projekt hinzugefügt.
Die 'uses'-Anweisung in meiner Source bleibt aber unverändert, oder?

Hab die beiden Methoden in der Interface-Section von Private nach Protected verschoben, aber der Delphi-Compiler meckert nach wie vor, das DestroyFields und CreateFields undefinierte Bezeichner sind. Das mit dem TDatasetCracker hab ich auch noch so in meiner Source wie du es in deinem Beispiel geschrieben hast. :gruebel: :wall:

Ich glaub bald ich bin zu blöd für diese Welt. :wink:

Hast du noch Vorschläge was ich machen könnte, das der Delphi-Compiler die Methoden erkennt, oder evtl. einen anderen Weg? :?:

Gruß

MPirnstill 10. Jan 2006 09:21

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Bin jetzt noch mal einen Schritt weiter gegangen und habe die beiden Methoden sogar unter Public verschoben, aber der gleiche Fehler. Ich glaube fast, daß Delphi sich immer noch die Original Unit DB.PAS zieht.

Gruß

MPirnstill 10. Jan 2006 11:18

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Tja, irgendwie hab ich das Gefühl ich bin wieder allein mit meinem Problem! :cry:

Es funzt zwar nich, aber trotzdem vielen Dank an euch. Muß ich mir irgendwie was anderes einfallen lassen.

Gruß

marabu 10. Jan 2006 17:12

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Micha,

ich war im Keller und habe D2 gefunden. Installiert habe ich es dann auch noch. Das Demo-Projekt im Anhang ist dabei heraus gekommen. Die Quintessenz ist - es geht, aber anders als wir dachten. D2 ist halt nicht D5 oder D7.

Grüße vom marabu

MPirnstill 11. Jan 2006 07:13

Re: Wie definiere ich ein Lookup-Feld für eine TQuery?
 
Zitat:

Zitat von marabu
Hallo Micha,

ich war im Keller und habe D2 gefunden. Installiert habe ich es dann auch noch. Das Demo-Projekt im Anhang ist dabei heraus gekommen. Die Quintessenz ist - es geht, aber anders als wir dachten. D2 ist halt nicht D5 oder D7.

Grüße vom marabu

Hallo marabu,

ich bin der Meinung:
Zitat:

Das war Spitze!
:thumb:
um das mal mit den Worten eines längst verstorbenen Showmasters zu sagen.

Ich hatte gestern Nachmittag eine ähnliche, aber sehr unelegante, Lösung funden. Ich hatte mir die Felddefinitionen im Programm definiert um die persistenten Felder anzulegen und das ist ja doppelt-gemoppelt und außerdem eine große Fehlerquelle falls man mal die Tabelle ändern sollte.

Das du extra noch mal den Dinosaurier, welche ich hier tagtäglich quäle (oder er mich), aus dem Keller gekrammt und installiert hast, ist einfach Wahnsinn. Ich komme davon (D2) leider nicht los, da dieses alte Projekt an dem ich hier arbeit sehr viele Quickreports hat und deswegen die Umstellung zu aufwendig wäre (bekomme einfach nicht die Zeit dafür). Sonst würde ich ja auch mit eine neueren Version arbeiten.
:cheers: :cheers: :cheers: :cheers: :cheers: :cheers: :cheers:
Super-spitzenmäßig! Tausend Dank, nochmal!
:cheers: :cheers: :cheers: :cheers: :cheers: :cheers: :cheers:


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:56 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