![]() |
Label, Editfeld und DBlookupListbox
Hi,
folgendes Problem (es geht um 2 Tables : Artikel und Warengruppen) : Ich habe hier ein Label, ein Editfeld, sowie eine Listbox. Folgendes soll gemacht werden : Nach Eingabe der Art.Nr. soll das Label mit der Warengruppe des Artikels beschriftet werden und die Nr. soll als Vorgabewert im Editfeld stehen. Sobald dieses betreten wird, soll die Box aufgehen.
Code:
Das da geht nicht : "Invalid Variant conversion". Das liegt an dem ID = :ID. Wie macht man das denn jetzt richtig? Aus Der Warengruppen-Table soll die Bez. der WG gesucht werden, deren ID gleich der ID_WG des Artikels ist.
ArtDS.Active := false;
ArtDs.SelectSQL.Text := 'SELECT * FROM ART8 WHERE NR = ' + ArtNrEdit.Text; ArtDS.Active := true; WGDS.active := false; WGDS.SelectSQL.Text := 'SELECT * FROM WG8 WHERE ID = :ID_WG'; WGDS.active := true; Label3.Caption := WGDS.FieldByName ('BEZ').value; Edit1.Text := WGDS.FieldByName ('NR').value; Um überhaupt etwas zu sehen, habe ich das :ID_WG durch einen statischen Wert ersetzt. Dann läuft alles richtig. Dann noch etwas mit der Box. Wie gesagt, soll diese nur sichtbar sein, falls sich der Cursor in dem EditFeld befindet. Setze ich sie aber in dem Edit1Exit enabled und visible auf false, dann kann ich mit der Maus ja keinen Eintrag mehr auswählen, da ich zu diesem Zweck ja das Feld verlassen muß. :evil: Ich brauche also ein Unterscheidungsmerkmal, ob ich mich in dem Feld der WG-Nr. befinde, in der Listbox oder woanders (nur in diesem Fall dürfte dann visible und enabled auf false gesetzt werden). Wer weiß was dazu ? Gruß Hansa |
Hi Hansa,
ich kann leider nicht ganz nachvollziehen, was genau passieren soll. Möglicherweise kommt es in Deinem Datenbestand vor, dass das ID Feld des aktuellen Datensatzes nicht besetzt, also NULL ist. Möglicherweise stimmt das Format auch nicht überein (string, longint). Außerdem, versuchs mal mit
Delphi-Quellcode:
Zu Deiner zweiten Sache: das scheint mir usibilitytechnisch ein Knieschuss zu sein. Klar bist Du nicht im Editierfeld, wenn Du die Liste anklickst. Wahrscheinlich hab ich auch noch nicht begriffen, was dahinter steckt, kannst Du das kurz genauer erläutern? Irgendein Trick wird uns dann schon einfallen (LastFocusedObject oder so).
Label3.Caption := WGDS.FieldByName('BEZ').AString;
Edit1.Text := WGDS.FieldByName('NR').AsInteger; gruß, harrybo |
Hi harrybo,
zu 1 : Was hab ich denn da für einen Mist stehen ? :oops: Das ist mir ehrlich gesagt gar nicht aufgefallen, irgendwie hatte ich aber ein ungutes Gefühl :mrgreen: Das mit den Parametern bei SQL verstehe ich anscheinend nie. Weiß nie wo und wie die herkommen. Probier ich noch aus. zu 2 : Die Box soll verschwinden, sobald klar ist, daß das Editfeld im Moment nicht gebraucht wird. sobald es betreten wird, soll die Box aufklappen, wobei natürlich die Möglichkeit der Auswahl gegeben sein muß. Ich müßte nur rausfinden ob der Focus in einem Feld <> WGedit UND <> Listbox ist. Nur wie? Oder geht es anders? Daaaaaa fällt mir gerade etwas ein :spin: ,es gibt doch bei jedem Feld ein Tag !!!! Keine Sau benutzt das, ich auch nicht. Aber für so einen Sonderfall ist das doch geradezu prädestiniert, oder nicht? Obwohl ich glaube, daß es auch anders / einfacher geht. Gruß Hansa |
Zitat:
das ist relativ einfach zu lösen. Ich habe es eben mal mit mehreren Edits und einer ComboBox auf dem Formluar getestet. Im OnEnter vom Edit1 schreibst Du:
Delphi-Quellcode:
:lol: Das ist ja auch klar.
procedure TForm1.Edit1Enter(Sender: TObject);
begin ComboBox1.Visible := True; end; Jetzt kommt der grosse Zauber. Im OnExit des Edits schreibst Du:
Delphi-Quellcode:
ActiveControl wird nämlich gesetzt BEVOR das OnExit ausgelöst wird :P
procedure TForm1.Edit1Exit(Sender: TObject);
begin If Not (ActiveControl = ComboBox1) then begin ComboBox1.Visible := False; end; end; Und so weisst Du zu welchem Control der Anweder gewechselt hat. So, jetzt noch in das OnExit der ComboBox:
Delphi-Quellcode:
Und fertig ist der Lack...
procedure TForm1.ComboBox1Exit(Sender: TObject);
begin If Not (ActiveControl = Edit1) then begin ComboBox1.Visible := False; end; end; |
Hi,
Danke euch beiden, das geht jetzt alles einwandfrei :!: @Harrybo :
Code:
Hab Dein Beispiel abgekupfert. IntToStr hat halt noch gefehlt und "AsString" schreibt man nicht "Astring" :mrgreen: *ichnichtschimpf* 2 Min., dann ging das. Auf die Idee mit dem value kam ich folgendermaßen : Fehler in der Code-Vervollständ. :!: FieldByName tauchte da nicht auf :!: Auswendig wußte ich die genaue Syntax nicht.Label3.Caption := WGDS.FieldByName('BEZ').AsString; Edit1.Text := IntToStr (WGDS.FieldByName('NR').AsInteger); // Label3.Caption := WGDS.FieldByName ('BEZ').value; // Edit1.Text := WGDS.FieldByName ('NR').value; @Sharky : Das war genauso richtig. In 30 Min. war auch das fertig. Das war nur aufwendiger, weil ich die SQL-Statements etwas umbauen mußte. Vom Prinzip her war es kein Problem. Das geht ja runter wie Öl. Eine Frage, eine Antwort, nochmals gefragt : zweite Antwort. Und dann gehts. :dancer: Aber ich weiß immer noch nicht, woher der weiß, daß das :ID ein Parameter ist, bzw. wo der Wert herkommt. Und was ich auch nicht genau weiß, wie kriege ich die ID der ausgewählten Warengruppe in den Artikel? Ich lese immer nur, das ginge automatisch, bei mir aber nicht einfach so. Gruß Hansa |
Hi Hansa,
alles klar. Sorry mit AsString, war ein Tippfehler von mir. Ja, stimmt, FieldByName taucht in der Code-Vervollständigung nicht auf. Einfach schreiben, Klammer auf, Feldname, Klammer zu, Punkt, und es geht weiter mit der Code-Vervollständigung. Ok, IntToStr fehlte tatsächlich auch noch, war ja Gott sei Dank für Dich ein Klacks... gruß, harrybo |
Hi,
Zitat:
Gruß Hansa |
Hi,
so ganz fertig ist das ganze noch nicht, zumindest funktioniert es jetzt richtig. Aber gestern hatte ich nicht gemerkt daß hier :
Code:
das :ID noch durch eine feste Zahl ersetzt war. 8) Natürlich lief es dann, weil das die passenden Zahlen waren.
ArtDs.SelectSQL.Text := 'SELECT * FROM ART8 WHERE NR = ' + ArtNrEdit.Text;
ArtDS.Active := true; WGDS.active := false; WGDS.SelectSQL.Text := 'SELECT * FROM WG8 WHERE ID = :ID'; Jetzt habe ich das zweite Select hierdurch ersetzt :
Code:
Muß das tatsächlich so umständlich gemacht werden? Deshalb nochmals die Frage: Wie kriege ich die ID_WG aus dem ersten Select als Parameter an die zweite Übergeben ?
WGDS.SelectSQL.Text := 'SELECT * FROM WG8 WHERE ID = ' + IntToStr (ArtDS.FieldByName ('ID_WG').AsInteger);
Gruß Hansa |
Kann man nicht die ID direkt als String auslesen? Also mit .AsString, dann müsste man sich das umwandeln doch sparen können. Aber eventuell dann noch das "=" durch LIKE ersetzen, falls dann eine Fehlermeldugn kommt "Type Mismatch ..." :).
|
Hi Hansa,
Du hast recht, es geht professioneller und auch schneller in der Ausführung wenn Du mit Parametern arbeitest. Vorteil: der SQL Text muss nicht geändert werden. Einen Parameter kannst Du im Design Modus über den Objekt Inspector anlegen (Params, hast Du wahrscheinlich schon) oder per Code für Deinen Fall mit
Delphi-Quellcode:
Deinen SQL Text kannst Du nun stehen lassen als
WGDS.Params.CreateParam(ftInteger, 'ID');
Delphi-Quellcode:
Jetzt aktualisierst Du mit
WGDS.SelectSQL.Text := 'SELECT * FROM WG8 WHERE ID = :ID';
Delphi-Quellcode:
Bingo! Umformen per IntToStr ist auch nicht nötig, da es sich ja um einen echten Integer Parameter handelt.
with WGDS do try
DisableControls; if Active then Close; ParamByName('ID').Value := ArtDS.FieldByName ('ID_WG').AsInteger; // Alternativ, wenn die Abfrage genau einen Parameter hat: // Params[0].Value := ArtDS.FieldByName ('ID_WG').AsInteger; Open; finally EnableControls; end; gruß, harrybo |
Hi,
Zitat:
Etwas einfacher geht es aber schon (so wie ich es am Anfangang gemacht habe : Zitat:
WGDS.FieldValues ['ID']; Dann entfällt die Typumwandlung, bzw. wird sie intern gemacht !! Zitat:
Gruß Hansa |
@harrybo : das da drucke ich mir aus, hol es mit und lese es zum Nachtisch. :lol: Auf den ersten Blick ist das das Gesuchte!
Gruß Hansa |
Zitat:
Durch das .AsString Sagst Du deinem DataSet nämlich wie Du es haben möchtest. Ich kann z.B. folgendes machen. In der Tabelle ist das Feld NUMMER als Integer deklariert.
Code:
Zumindest geht das so bei mir.
var
i_nummer : Integer; s_nummer : String; begin i_nummer := Query1.FieldByName ('nummer').AsInteger; s_nummer := Query1.FieldByName ('nummer').AsString; end; |
Hi Sharky,
das stimmt ja alles, aber guck Dir mal die Beiträge weiter oben an. FieldValues gibt es ja auch noch :!: Gruß Hansa |
Hi,
Zitat:
Gruß Hansa |
Zitat:
|
Hi Hansa,
das liegt wahrscheinlich nicht am Unterschied zwischen FIBplus und IBX, ich wusste nur nicht, womit Du überhaupt arbeitest. Die Sache ist für Dich dann einfacher, die Queries haben automatische Parameter (siehe Object Inspector). Du brauchst den Parameter nicht zu definieren und kannst einfach zuweisen, z.B. mit
Delphi-Quellcode:
Gibt es keinen Parameter, wird er angelegt.
Query1.Params[0].Value := APar;
Hier mal eine allgemeine Funktion, die ein Dataset mit einem Parameter refreshed (IBX und Interbase). Übergeben wird das Dataset Object, der Wert des Parameters, der ID Wert auf den der Datensatzzeiger positioniert werden soll, Konstante, die sagt, was mit der laufenden Transaction passieren soll:
Delphi-Quellcode:
gruß, harrybo
procedure TDM.RequeryDS1(ADataset: TIBDataset; APar: variant; AID: longint; AType: integer);
begin with ADataset do try DisableControls; if Active then if State in [dsEdit, dsInsert] then Post; Close; if Transaction.InTransaction then case AType of c_Commit : Transaction.Commit; c_CommitRetain : Transaction.CommitRetaining; c_Rollback : Transaction.Rollback; end; if not Transaction.InTransaction then Transaction.StartTransaction; Params[0].Value := APar; Active := true; if AID > 0 then Locate(Fields[0].FieldName, AID, []); finally EnableControls; end; end; |
Hi harrybo,
wo kommt denn das RequeryDS1 hin ? Du scheinst da eine allgemeine Prozedur geschrieben zu haben. Im OI ist hierüber jedenfalls nichts zu finden. Gruß Hansa |
Hi Hansa,
ja, es ist eine selfmade Procedure, die bei mir im Datamodul und dort im Public Abschnitt, damit man von draußen Zugrif drauf hat. Da ein Datamodul meist mehrere TDataset Objekte versammelt, kann man der Procedure noch mitteilen, welchen Dataset man aktualisieren will. Der Aufruf kann dann so aussehen:
Delphi-Quellcode:
DM.dsTER ist hier ein TDataset, der Rest spricht für sich, hoffe ich (nach meinen Erfahrungen mit X-Dragon trau ich mich ja kaum noch, feste Werte irgendwo reinzuschreiben).
DM.RequeryDS1(DM.dsTER, gActDate, gActRec.TER, c_Commit);
gruß, harrybo P.S. sieht nach Master Detail aus, was Du vorhast. Da gibt es ja, zumindest bei IBX, die code-lose Variante mit zusätzlicher Datasource, die wunderbar läuft (ok, ein einziger BeforeInsert Trick). |
Hi,
Zitat:
Gruß Hansa |
Hi Hansa,
ich nehme mal folgendes Beispiel: ein Dataset soll Daten aus einer Tabelle Termine holen, und zwar für ein bestimmtes Datum (das ist der Parameter). Die Termine werden in einem Grid dargestellt. Was machen nun die Parameter?
gruß, harrybo |
Hi,
der Sinn ist schon klar. Zitat:
Zitat:
Gruß Hansa |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:16 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