Discussion:
acDialog für instanzierte Formulare
(zu alt für eine Antwort)
Georg Matejka
2009-07-08 16:41:17 UTC
Permalink
Hallo,
um in einem Formular Informationen abzufragen und nach dem Schließen des
Formulars mit der gleichen Methode fortzusetzen, gibt es den Parameter
'acDialog' beim Öffnen des Formulars:

DoCmd.OpenForm "frm_Test", , , , , acDialog

Wie kann ich das für instanzierte Formulare machen?

Bisherige Lösung:
Set objForm = new Form_frm_Test
objForm.Visible = True
Do While objForm.Visible
DoEvents
Loop

Damit kann man den Ablauf des Programms am lauter werdenden Lüfter
nachvollziehen ;-/ - finde ich nicht optimal.

Für Kontextmenüs habe ich eine Lösung, die u.a. die Api-Methoden
"GetMessage" und "DispatchMessage" kombiniert: Nachdem das Kontextmenü
angezeigt wurde, wird

GetMessage typMsg, lngHwndParent, WM_COMMAND, WM_LBUTTONUP

aufgerufen, was die Fortsetzung der Methode aufhält, bis der Benutzer
auf das Kontextmenü reagiert hat.

Jetzt müsste es doch eine Methode (bzw. Konfiguration für GetMessage)
geben, die die Ausführung aufhält, solange es mein instanziertes Fenster
gibt. Ich habe schon länger herumexperimentiert, aber noch keine Lösung
ohne Schleife gefunden.
Weiß jemand...?

Georg

Für alle Fälle: Xp prof. / Access 2003
Mark Doerbandt
2009-07-08 21:15:47 UTC
Permalink
Hallo, Georg,
Post by Georg Matejka
um in einem Formular Informationen abzufragen und nach dem Schließen des
Formulars mit der gleichen Methode fortzusetzen, gibt es den Parameter
DoCmd.OpenForm "frm_Test", , , , , acDialog
Wie kann ich das für instanzierte Formulare machen?
Set objForm = new Form_frm_Test
objForm.Visible = True
Do While objForm.Visible
DoEvents
Loop
hast Du mal versucht

objForm.Modal = True
objForm.PopUp = True
objForm.Visible = True
' (ungetestet)
?

Gruss - Mark
--
Informationen fuer Neulinge in den Access-Newsgroups unter
http://www.doerbandt.de/Access/Newbie.htm

Bitte keine eMails auf Newsgroup-Beiträge senden.
Jörg Ostendorp
2009-07-09 09:18:25 UTC
Permalink
Hallo Georg,
Post by Georg Matejka
um in einem Formular Informationen abzufragen und nach dem Schließen des
Formulars mit der gleichen Methode fortzusetzen, gibt es den Parameter
DoCmd.OpenForm "frm_Test", , , , , acDialog
Wie kann ich das für instanzierte Formulare machen?
Set objForm = new Form_frm_Test
objForm.Visible = True
Do While objForm.Visible
DoEvents
Loop
Probier es mal mit einem zusätzlichen "Sleep 1" (API-Sub) vor oder nach dem
Doevents.

Viele Grüße
Jörg Ostendorp
--
Access-FAQ: www.donkarl.com
Josef Poetzl
2009-07-09 09:41:31 UTC
Permalink
Hallo!

Georg Matejka schrieb:
[...]
Post by Georg Matejka
Set objForm = new Form_frm_Test
objForm.Visible = True
Do While objForm.Visible
DoEvents
Loop
Ich würde den Code nach objForm.Visible = True auslaufen lassen und
bei Bedarf auf das Schließenereignis von frm_Test reagieren.

Prinzip (Luftcode):

private withevents m_TestForm as Form_frm_Test

private sub starteForm1CommandButton_Click()
oeffneTestForm
msgbox "diese Msgbox wir noch ausgeführt!"
end sub

private sub oeffneTestForm()
set m_TestForm = new Form_frm_Test
m_TestForm.Modal = True
m_TestForm.Visible = True
end sub

'Auf Ereignis reagieren:
private sub m_TestForm_Close()
msgbox "nun geht's weiter im Code"
end sub


Anm.: Wenn ein Dialog-Fenster benötigt wird, komme ich normalerweise
mit Docmd.OpenForm aus, da ich bisher einen Dialog nie mehrmals
benötigte. Mehrere Instanzen eines Formulars verwende ich eher für
Aufgabenstellungen, in denen der Anwender unterschiedliche Datensätze
im Detail nebeneinander betrachten will. Dafür benötige ich allerdings
die Funktionalität eines Dialog-Fensters nicht.


mfg
Josef

PS:
@Mark: "objForm.PopUp = True" funktioniert nach dem Instanzieren nicht
mehr. Das kann nur in der Entwurfsansicht eingestellt werden.
--
EPT: (Access Error Prevention Table) http://access.joposol.com/
FAQ: (Access-FAQ von Karl Donaubauer) http://www.donkarl.com/
Mark Doerbandt
2009-07-09 09:48:49 UTC
Permalink
Hallo, Josef,
Post by Josef Poetzl
@Mark: "objForm.PopUp = True" funktioniert nach dem Instanzieren nicht
mehr. Das kann nur in der Entwurfsansicht eingestellt werden.
Danke, deshalb schrieb ich extra "ungetestet", weil ich nicht sicher
war. Die Herleitung kam nur von acDialog, weil das ja die beiden
Properties setzt.

Btw: Deine Argumentation ist natürlich treffend, denn wer sollte
mehrere modale Dialoge instanziieren wollen?

Gruss - Mark
Jörg Ostendorp
2009-07-09 10:14:47 UTC
Permalink
Hallo Mark + Josef,
Post by Mark Doerbandt
Btw: Deine Argumentation ist natürlich treffend, denn wer sollte
mehrere modale Dialoge instanziieren wollen?
Ich hätte es jetzt eher so verstanden, dass es nicht um eine
Mehrfachinstanzierung geht sondern einfach um eine Vorliebe beim
Programmieren. Den Wunsch, Formulare typsicher zu instanzieren anstatt mit
Strings rumzuhampeln (Provokation! ;-)) kann ich durchaus nachvollziehen.

Gruß Jörg
--
Access-FAQ: www.donkarl.com
Josef Poetzl
2009-07-09 11:22:22 UTC
Permalink
Hallo!
Post by Jörg Ostendorp
Ich hätte es jetzt eher so verstanden, dass es nicht um eine
Mehrfachinstanzierung geht sondern einfach um eine Vorliebe beim
Programmieren. Den Wunsch, Formulare typsicher zu instanzieren anstatt mit
Strings rumzuhampeln (Provokation! ;-)) kann ich durchaus nachvollziehen.
Mir würde es "bereits" ausreichen, wenn man bei DoCmd.OpenForm
einstellen kann, dass man eine neue Instanz haben will und dann als
Rückgabewert die Referenz bekommt. :-)

| dim abcForm as Form_ABC
| set abcForm = Docmd.OpenForm("ABC", ... , acNewInstance)

die Variante
| set abcForm = new Form_ABC(Parameter1, Parameter2, ...)
ist unter VBA/VB6 vermutlich etwas schwierig umzusetzen. ;-)


mfg
Josef
--
EPT: (Access Error Prevention Table) http://access.joposol.com/
FAQ: (Access-FAQ von Karl Donaubauer) http://www.donkarl.com/
Georg Matejka
2009-07-09 10:30:27 UTC
Permalink
Post by Josef Poetzl
Hallo!
[...]
Post by Georg Matejka
Set objForm = new Form_frm_Test
objForm.Visible = True
Do While objForm.Visible
DoEvents
Loop
Dieses meine Beispiel funktioniert nur, solange, das Formular geöffnet
ist. Wird es geschlossen und das Schliessen im Form_Unload nicht auf
Ausblenden umgebogen, krachts. Mit der Api-Funktion IsWindow(hwnd)
funktioniert es dafür.
Post by Josef Poetzl
Ich würde den Code nach objForm.Visible = True auslaufen lassen und
bei Bedarf auf das Schließenereignis von frm_Test reagieren.
Damit kann ich nicht in der das Formular aufrufenden Methode mit der auf
den Formularaufruf folgenden Anweisung fortsetzen.

Das ist imho dann sinnvoll, wenn ich mit frm_Test auf einen bestimmte
Konstellation (zB. einen Fehler) in der aufrufenden Methode reagieren
möchte. Sobald ich auf ein Ereignis reagiere(n muss), wird der Code
zwangsläufig zweigeteilt.

Mit DoCmd.OpenForm ... ,acDialog kann ich das Formular auch nicht
Customizen, weil der Code ja mit der das Formular ladenden Anweisung
stehen bleibt. Bis jetzt habe ich mir damit beholfen, entsprechende
Anweisungen in OpenArgs mitzugeben.

Hätte das Formular nun eine von mir erstellte .Database-Property, wären
auch die OpenArgs überfordert und ich müsste auf eine globale Variable
umsteigen. (...)
Post by Josef Poetzl
Anm.: Wenn ein Dialog-Fenster benötigt wird, komme ich normalerweise
mit Docmd.OpenForm aus, da ich bisher einen Dialog nie mehrmals
benötigte.
Ja. Amen. Ich im Prinzip auch. Mit oben genannten Ausnahmen.


Mehrere Instanzen eines Formulars verwende ich eher für
Post by Josef Poetzl
Aufgabenstellungen, in denen der Anwender unterschiedliche Datensätze
im Detail nebeneinander betrachten will. Dafür benötige ich allerdings
die Funktionalität eines Dialog-Fensters nicht.
w.o.

Fazit: Es wird wohl bei Instanzierung + Schleife oder acDialog bleiben.
Prinzipiell auf die Idee mit dem Code aufhalten bin ich mit dem von mir
oft verwendeten Api-Kontextmenü gekommen, wo eben per Api darauf
gewartet wird, dass das Kontextmenü bearbeitet wurde.
Ich gehe (noch immer) davon aus, dass Access bei acDialog intern einen
ähnlichen Mechanismus benutzt, den müsste man halt kennen.

Danke für eure Hilfe,
Georg

Ps. - zu späteren Postings:
Umgekehrt geht es übrigens schon:
- Formular mit Docmd.OpenForm ... acDialog öffnen
- Formular im Form_Open-Ereignis mit Api SetWindowPos zentrieren
- Nun ist das Formular nicht mehr gebunden + (!) der Code steht an der
Docmd.OpenForm-Stelle.
-> D.h. ich kann Verschiedenes ausserhalb des Formulars ausführen und
nach dem Schliessen geht's mit der auf Docmd.OpenForm folgenden
Anweisung weiter.
Josef Poetzl
2009-07-09 11:14:20 UTC
Permalink
Hallo!
Post by Georg Matejka
Mit DoCmd.OpenForm ... ,acDialog kann ich das Formular auch nicht
Customizen, weil der Code ja mit der das Formular ladenden Anweisung
stehen bleibt. Bis jetzt habe ich mir damit beholfen, entsprechende
Anweisungen in OpenArgs mitzugeben.
Hätte das Formular nun eine von mir erstellte .Database-Property, wären
auch die OpenArgs überfordert und ich müsste auf eine globale Variable
umsteigen. (...)
Nicht unbedingt. ;-)

Ich hatte einmal den Bedarf auf Ereignisse eines Formulars zu
reagieren, das über acDialog geöffnet wurde.
=> Referenz wird benötigt um Withevents einsetzen zu können.
DoCmd.Openform gibt aber keine Referenz zurück daher war ein Umweg
erforderlich.

Mein Lösungsansatz:
Eine globale Variable für die Übergabe der Referenz einer
instanzierten Klasse.
In der Klasse selbst gibt es eine Eigenschaft, der die Referenz auf
das Dialog-Formular übergeben wird.

Code-Schnipsel:

Aufruf:
Set g_TempRef = Me
DoCmd.OpenForm .... acDialog
Set g_TempRef = Nothing

im Dialog-Formular:
If Not (g_TempRef Is Nothing) Then
Set g_TempRef.LoginForm = Me
End If

in der Klasse:
Private WithEvents m_LoginForm As Form_frmLogin
Public Property Set LoginForm(ByRef ref As Form)
Set m_LoginForm = ref
'=> ab jetzt kann auf die Ereignisse reagiert werden
End Property
Post by Georg Matejka
Fazit: Es wird wohl bei Instanzierung + Schleife oder acDialog bleiben.
Schleifen mit DoEvents & Co. mag ich überhaupt nicht.
Post by Georg Matejka
Prinzipiell auf die Idee mit dem Code aufhalten bin ich mit dem von mir
oft verwendeten Api-Kontextmenü gekommen, wo eben per Api darauf
gewartet wird, dass das Kontextmenü bearbeitet wurde.
Ich gehe (noch immer) davon aus, dass Access bei acDialog intern einen
ähnlichen Mechanismus benutzt, den müsste man halt kennen.
Dieser Ansatz wäre durchaus eine Möglichkeit, die ich mir vorstellen
könnte. Ich bin allerdings weder ein API- noch Subclassing-Experte und
daher können wir nur hoffen, dass sich noch jemand (=Jörg?) meldet,
der das widerlegen bzw. die Hoffnung auf Erfolg geben kann. :-)

BTW:
... irgendwie ist bei mir "Jörg" und "API" verknüpft. Woher kommt das
nur? :-)

mfg
Josef
--
EPT: (Access Error Prevention Table) http://access.joposol.com/
FAQ: (Access-FAQ von Karl Donaubauer) http://www.donkarl.com/
André Minhorst
2009-07-10 12:24:15 UTC
Permalink
Moin zusammen,
Post by Josef Poetzl
set m_TestForm = new Form_frm_Test
m_TestForm.Modal = True
m_TestForm.Visible = True
kann da eigentlich jemand bestätigen, dass ein so erzeugtes Formular nicht
über

Forms!Formularname

referenziert werden kann?

Es klappt auch nicht über Forms("Formularname").

Zwar lässt sich, wenn man den Index dieses Formulars kennt, eine Referenz
etwa über Forms(1) herstellen. Forms(1).Name gibt dann auch "Formularname"
aus.

Aber Forms(Forms(1).Name).Name liefert wieder einen Fehler (2450, kann
Formular nicht finden).

Der fehlerfreie Zugriff ist nur über Form_Formularname möglich.

Merkwürdig ...

Ciao
André
--
http://www.access-entwicklerbuch.de
http://www.access-im-unternehmen.de
Mark Doerbandt
2009-07-10 12:47:31 UTC
Permalink
Hallo, André,
Post by André Minhorst
kann da eigentlich jemand bestätigen, dass ein so erzeugtes Formular nicht
über
Forms!Formularname
referenziert werden kann?
Es klappt auch nicht über Forms("Formularname").
Zwar lässt sich, wenn man den Index dieses Formulars kennt, eine Referenz
etwa über Forms(1) herstellen. Forms(1).Name gibt dann auch "Formularname"
aus.
Aber Forms(Forms(1).Name).Name liefert wieder einen Fehler (2450, kann
Formular nicht finden).
Der fehlerfreie Zugriff ist nur über Form_Formularname möglich.
interessant, kann ich bestätigen.

Sub TestForm()
Dim F As Form
Set F = New Form_Test
' F.Modal = True ' egal ob mit oder ohne
F.Visible = True
' Debug.Print Forms!Test.Name ' geht nicht
' Debug.Print Forms("Test").Name ' geht nicht
Debug.Print Forms(0).Name ' geht
Set F = Nothing
End Sub

Interessanterweise steht das Formular im Watchfenster in Forms mit dem
korrekten Namen "Test" drin.

Gruss - Mark
Josef Poetzl
2009-07-10 12:44:53 UTC
Permalink
Hallo!
Post by André Minhorst
Post by Josef Poetzl
set m_TestForm = new Form_frm_Test
m_TestForm.Modal = True
m_TestForm.Visible = True
kann da eigentlich jemand bestätigen, dass ein so erzeugtes Formular nicht
über
Forms!Formularname
referenziert werden kann?
Das kann ich bestätigen. :-)
Post by André Minhorst
Es klappt auch nicht über Forms("Formularname").
Zwar lässt sich, wenn man den Index dieses Formulars kennt, eine Referenz
etwa über Forms(1) herstellen. Forms(1).Name gibt dann auch "Formularname"
aus.
Du kannst das Formular aber auch über das druchlaufen der Auflistung
suchen:

set m_TestForm = new Form_frm_Test
For Each frm In Forms
If frm.Name = "frm_Test" Then
MsgBox "gefunden: " & frm.hwnd
Exit For
End If
Next
Post by André Minhorst
Aber Forms(Forms(1).Name).Name liefert wieder einen Fehler (2450, kann
Formular nicht finden).
Klar, das entspricht ja auch nicht anderem als Forms("Formularname")
Der Name des Forms einer Instanz ändert sich nicht, nur weil mehrere
Instanzen davon existieren.
Post by André Minhorst
Der fehlerfreie Zugriff ist nur über Form_Formularname möglich.
Da musst du aber aufpassen!
| set frm = Form_Formularname
erzeugt ebenso eine Instanz des Formulars, falls noch keine existiert.
Außerdem kannst du damit auch eine Formular-Instanz des Formulars
"Formularname" erwischen, die als Unterformular verwendet wird.
Post by André Minhorst
Merkwürdig ...
... oder doch erklärbar? :-)

Beispiel:
| set m_TestForm1 = new Form_frm_Test
| set m_TestForm2 = new Form_frm_Test

Welches Formular sollte nun über Forms("frm_Test") gefunden werden?

Und damit man nicht in so eine Falle tappt, kommt zur Sicherheit
nichts. Diese Variante finde ich gar nicht so schlecht, da ich den
Zugriff über die Forms-Auflistung sowieso nicht benötigte, wenn das
Formular mittels New instanziert wurde.


mfg
Josef
--
EPT: (Access Error Prevention Table) http://access.joposol.com/
FAQ: (Access-FAQ von Karl Donaubauer) http://www.donkarl.com/
André Minhorst
2009-07-10 12:54:48 UTC
Permalink
Moin Josef,
Post by Josef Poetzl
Post by André Minhorst
Post by Josef Poetzl
set m_TestForm = new Form_frm_Test
m_TestForm.Modal = True
m_TestForm.Visible = True
kann da eigentlich jemand bestätigen, dass ein so erzeugtes Formular nicht
über
Forms!Formularname
referenziert werden kann?
Das kann ich bestätigen. :-)
Danke!
Post by Josef Poetzl
Post by André Minhorst
Es klappt auch nicht über Forms("Formularname").
Zwar lässt sich, wenn man den Index dieses Formulars kennt, eine Referenz
etwa über Forms(1) herstellen. Forms(1).Name gibt dann auch "Formularname"
aus.
Du kannst das Formular aber auch über das druchlaufen der Auflistung
set m_TestForm = new Form_frm_Test
For Each frm In Forms
If frm.Name = "frm_Test" Then
MsgBox "gefunden: " & frm.hwnd
Exit For
End If
Next
Das habe ich mittlerweile getan und mir eine Funktion geschrieben, die den
aktuellen Index zurückliefert, damit ich doch über die Forms-Auflistung auf
das Formular zugreifen kann.
Post by Josef Poetzl
Post by André Minhorst
Merkwürdig ...
... oder doch erklärbar? :-)
| set m_TestForm1 = new Form_frm_Test
| set m_TestForm2 = new Form_frm_Test
Welches Formular sollte nun über Forms("frm_Test") gefunden werden?
Und damit man nicht in so eine Falle tappt, kommt zur Sicherheit
nichts. Diese Variante finde ich gar nicht so schlecht, da ich den
Zugriff über die Forms-Auflistung sowieso nicht benötigte, wenn das
Formular mittels New instanziert wurde.
Die Erklärung hilft, danke.

Hintergrund des Problems ist eine Validierungsklasse, die nicht nur IsNull,
IsNumeric, IsTrue et cetera prüfen, sondern auch Ausdrücke annehmen soll,
die auf dem zu prüfenden Steuerelement basieren.

Beispiel: Prüfen, ob ein eingegebener Wert schon in der Zieltabelle
enthalten ist, um Duplikate zu vermeiden:

IsNull(DLookup("Wert", "tblWerte", "Wert = '" & Me!Wert & "'"))

Me hätte ich von der Validierungsklasse aus einfach durch
Forms!Formularname ersetzt, was aber ja wegen oben geschildertem nicht
funkioniert. Form_Formularname will Eval nicht auswerten. Bleibt nun die
Lösung, über Wert.Parent.Name den Formularnamen zu holen, alle Formular zu
durchlaufen, den Index zu merken und Folgendes durch Eval zu schicken:

IsNull(DLookup("Wert", "tblWerte", "Wert = '" & Forms(i)!Wert & "'")

Klappt so, Problem also gelöst.

Ciao
André
--
http://www.access-entwicklerbuch.de
http://www.access-im-unternehmen.de
Josef Poetzl
2009-07-10 13:05:19 UTC
Permalink
Hallo!

André Minhorst schrieb:
[...]
Post by André Minhorst
Hintergrund des Problems ist eine Validierungsklasse, die nicht nur IsNull,
IsNumeric, IsTrue et cetera prüfen, sondern auch Ausdrücke annehmen soll,
die auf dem zu prüfenden Steuerelement basieren.
Beispiel: Prüfen, ob ein eingegebener Wert schon in der Zieltabelle
IsNull(DLookup("Wert", "tblWerte", "Wert = '" & Me!Wert & "'"))
Me hätte ich von der Validierungsklasse aus einfach durch
Forms!Formularname ersetzt, was aber ja wegen oben geschildertem nicht
funkioniert.
... und außerdem bei Unterformularen nicht funktionieren würde.
Post by André Minhorst
Form_Formularname will Eval nicht auswerten. Bleibt nun die
Lösung, über Wert.Parent.Name den Formularnamen zu holen, alle Formular zu
IsNull(DLookup("Wert", "tblWerte", "Wert = '" & Forms(i)!Wert & "'")
Klappt so, Problem also gelöst.
Das kommt mir etwas fehleranfällig vor.
Muss es unbedingt über eval laufen?

mfg
Josef
--
EPT: (Access Error Prevention Table) http://access.joposol.com/
FAQ: (Access-FAQ von Karl Donaubauer) http://www.donkarl.com/
André Minhorst
2009-07-10 13:23:21 UTC
Permalink
Hi Josef,
Post by Josef Poetzl
Post by André Minhorst
Form_Formularname will Eval nicht auswerten. Bleibt nun die
Lösung, über Wert.Parent.Name den Formularnamen zu holen, alle Formular zu
IsNull(DLookup("Wert", "tblWerte", "Wert = '" & Forms(i)!Wert & "'")
Klappt so, Problem also gelöst.
Das kommt mir etwas fehleranfällig vor.
Muss es unbedingt über eval laufen?
der Ablauf sieht so aus:

Das Formular wird geöffnet. Im Ereignis Beim Laden legt es ein
Validierungsobjekt an, das unter anderem eine Collection mit weiteren
Objekten enthält, die jede einer der vorzunehmenden Validierungen
entspricht - mit Angabe des Steuerelements, der Art der Validierung
(IsNull, IsTrue, IsNumeric, oder halt einen benutzerdefinierten Ausdruck).

Diese in der Collection gespeicherten Objekte implementieren auch das
Ereignis, bei dem die Validierung durchgeführt werden soll, hier
BeforeUpdate.

Es steht also fest, welches Steuerelement validiert werden soll, wann dies
geschehen soll (BeforeUpdate), was geprüft werden soll (IsNull et cetera),
aber nicht, mit welchem Wert, denn der wird ja erst zur Laufzeit vom
Benutzer eingegeben.

IsNull und andere triviale Validierungsfunktionen sind fest in der
Validierungsklasse verankert, aber ich kann schlecht alle übrigen
benutzerdefinierten Ausdrücke vorab implementieren. Und wenn zum Beispiel
der Ausdruck IsNull(DLookup("Wert", "tblWerte", "Wert =
'[AktuellerSteuerelementinhalt]'")) geprüft werden soll, wobei ich erst zur
Laufzeit [AktuellerSteuerelementinhalt] kenne, sehe ich keinen anderen Weg,
als diesen Ausdruck durch den aktuellen Ausdruck im String
"IsNull(DLookup..." auszutauschen und dann per Eval auszuwerten.

Oder übersehe ich eine Alternative?

Ciao
André
--
http://www.access-entwicklerbuch.de
http://www.access-im-unternehmen.de
Josef Poetzl
2009-07-13 12:50:16 UTC
Permalink
Hallo André!
Post by André Minhorst
Post by André Minhorst
IsNull(DLookup("Wert", "tblWerte", "Wert = '" & Forms(i)!Wert & "'")
[...]
Post by André Minhorst
Das Formular wird geöffnet. Im Ereignis Beim Laden legt es ein
Validierungsobjekt an, das unter anderem eine Collection mit weiteren
Objekten enthält, die jede einer der vorzunehmenden Validierungen
entspricht - mit Angabe des Steuerelements, der Art der Validierung
(IsNull, IsTrue, IsNumeric, oder halt einen benutzerdefinierten Ausdruck).
[...]
Post by André Minhorst
IsNull und andere triviale Validierungsfunktionen sind fest in der
Validierungsklasse verankert, aber ich kann schlecht alle übrigen
benutzerdefinierten Ausdrücke vorab implementieren. Und wenn zum Beispiel
der Ausdruck IsNull(DLookup("Wert", "tblWerte", "Wert =
'[AktuellerSteuerelementinhalt]'")) geprüft werden soll, wobei ich erst zur
Laufzeit [AktuellerSteuerelementinhalt] kenne, sehe ich keinen anderen Weg,
als diesen Ausdruck durch den aktuellen Ausdruck im String
"IsNull(DLookup..." auszutauschen und dann per Eval auszuwerten.
Oder übersehe ich eine Alternative?
Nur den Wert statt dem Form-Bezug einsetzen, um ihn dann mit Eval
auszuwerten, reicht nicht aus?
Nicht vergessen sollte man dann allerdings die Variante, dass nur
Steuerelemente bzw. Datenfelder ohne Formularbezug im Prüfausdruck
angegeben werden.

Ansonsten:
Falls es sich dabei um Gültigkeitsregeln für Steuerelemente handelt:
Wäre es denkbar, dass du zur Laufzeit im Steuerelement die
Gültigkeitsregeln einstellst. Dann müsste damit das
Access-Standardverhalten nutzbar werden.

Wenn ich dein Vorhaben richtig verstanden habe, geht es einerseits um
die Vereinfachung bei der Einstellung von Gültigkeitsregeln und eine
zentralisierte Abarbeitung. Das zwingt imo nicht unbedingt dazu, dass
man die eingebauten Gültigkeitsprüfungen komplett ersetzt.

mfg
Josef
--
EPT: (Access Error Prevention Table) http://access.joposol.com/
FAQ: (Access-FAQ von Karl Donaubauer) http://www.donkarl.com/
André Minhorst
2009-07-14 10:06:50 UTC
Permalink
Hi Josef,
Post by Josef Poetzl
Post by André Minhorst
Post by André Minhorst
IsNull(DLookup("Wert", "tblWerte", "Wert = '" & Forms(i)!Wert & "'")
[...]
Post by André Minhorst
Das Formular wird geöffnet. Im Ereignis Beim Laden legt es ein
Validierungsobjekt an, das unter anderem eine Collection mit weiteren
Objekten enthält, die jede einer der vorzunehmenden Validierungen
entspricht - mit Angabe des Steuerelements, der Art der Validierung
(IsNull, IsTrue, IsNumeric, oder halt einen benutzerdefinierten Ausdruck).
[...]
Post by André Minhorst
IsNull und andere triviale Validierungsfunktionen sind fest in der
Validierungsklasse verankert, aber ich kann schlecht alle übrigen
benutzerdefinierten Ausdrücke vorab implementieren. Und wenn zum Beispiel
der Ausdruck IsNull(DLookup("Wert", "tblWerte", "Wert =
'[AktuellerSteuerelementinhalt]'")) geprüft werden soll, wobei ich erst zur
Laufzeit [AktuellerSteuerelementinhalt] kenne, sehe ich keinen anderen Weg,
als diesen Ausdruck durch den aktuellen Ausdruck im String
"IsNull(DLookup..." auszutauschen und dann per Eval auszuwerten.
Oder übersehe ich eine Alternative?
Nur den Wert statt dem Form-Bezug einsetzen, um ihn dann mit Eval
auszuwerten, reicht nicht aus?
aktuell verwende ich einen Platzhalter [MyValue], der zur Validierzeit mit
dem Wert des betroffenen Steuerelements gefüllt wird.

Wie ich Ausdrücke mit anderen Steuerelementen handhabe, weiß ich allerdings
noch nicht, mal sehen.
Post by Josef Poetzl
Nicht vergessen sollte man dann allerdings die Variante, dass nur
Steuerelemente bzw. Datenfelder ohne Formularbezug im Prüfausdruck
angegeben werden.
Wäre es denkbar, dass du zur Laufzeit im Steuerelement die
Gültigkeitsregeln einstellst. Dann müsste damit das
Access-Standardverhalten nutzbar werden.
Wenn ich dein Vorhaben richtig verstanden habe, geht es einerseits um
die Vereinfachung bei der Einstellung von Gültigkeitsregeln und eine
zentralisierte Abarbeitung. Das zwingt imo nicht unbedingt dazu, dass
man die eingebauten Gültigkeitsprüfungen komplett ersetzt.
Eingebaute Gültigkeitsregeln (also etwa die Prüfung auf eine gültige Zahl
im Zahlenfeld) sowie benutzerdefinierte Gültigkeitsregeln übergeht die
Validierungsklasse. Das geschieht bewusst, damit die Anwendung die über die
benutzerdefinierte Validierung definierten Meldungen anzeigen kann.

In der Praxis sieht das nun so aus:

Zunächst wird eine Objektvariable für die Validierungsklasse deklariert:

Dim objValidation As clsValidation

Diese wird in Form_Load gefüllt, und außerdem legt man dort die einzelnen
Validierungen fest. Hier sind das zwei Validierungen, die durch die
Validated-Methode weiter unten beim Klicken des Schließen-Buttons ausgelöst
werden:

Private Sub Form_Load()
Set objValidation = New clsValidation
With objValidation
.AddFormValidation Me.txtProjekt, eIsNull, "Fehlende Eingabe",
"Bitte geben Sie eine Projektbezeichnung an."
.AddFormValidation Me.cboKundeID, eIsNull, "Fehlende Auswahl",
"Bitte wählen Sie einen Kunden aus."
End With
End Sub

Beim Klick auf den OK-Button wird dann validiert und schließlich das
Formular unsichtbar gemacht (oder geschlossen, je nach Anforderung):

Private Sub cmdOK_Click()
If objValidation.Validated = True Then
Me.Visible = False
End If
End Sub

Es gibt auch noch eine Methode AddControlValidation, die eine Validierung
vor Aktualisierung des Steuerelementinhalts auslöst und die Aktualisierung
gegebenenfalls mit Cancel = True beendet.

Ciao
André
--
http://www.access-entwicklerbuch.de
http://www.access-im-unternehmen.de
Josef Poetzl
2009-07-14 10:52:48 UTC
Permalink
Hallo!
Post by André Minhorst
aktuell verwende ich einen Platzhalter [MyValue], der zur Validierzeit mit
dem Wert des betroffenen Steuerelements gefüllt wird.
Wie ich Ausdrücke mit anderen Steuerelementen handhabe, weiß ich allerdings
noch nicht, mal sehen.
Für nur einen Vergleich würde ein Vergleichsoperator und die
Referenzübergabe des anderen Steuerelements ausreichen.
Was macht man aber bei:
| [Wert von A] >= [Wert von B] * [Wert von C]

Ohne Eval wird es vermutlich nicht laufen. Als Platzhalter würde ich
[xxx] ansehen und diesen Eintrag ("xxx") in der Control-Auflistung
suchen.

[...]
Post by André Minhorst
Post by Josef Poetzl
Wenn ich dein Vorhaben richtig verstanden habe, geht es einerseits um
die Vereinfachung bei der Einstellung von Gültigkeitsregeln und eine
zentralisierte Abarbeitung. Das zwingt imo nicht unbedingt dazu, dass
man die eingebauten Gültigkeitsprüfungen komplett ersetzt.
Eingebaute Gültigkeitsregeln (also etwa die Prüfung auf eine gültige Zahl
im Zahlenfeld) sowie benutzerdefinierte Gültigkeitsregeln übergeht die
Validierungsklasse. Das geschieht bewusst, damit die Anwendung die über die
benutzerdefinierte Validierung definierten Meldungen anzeigen kann.
Ich dachte an das Setzen der Gültigkeitsregel durch die
Validierungsklasse, damit Access das Prüfen übernehmen kann.
Die Standardmeldung müsste doch eigentlich abfangbar sein, oder?
Z. B. auf Form.Error reagieren und statt der Standardmeldung die
Meldung der Validierungsklasse anzeigen.

Ob das gut und stabil funktioniert, weiß ich nicht. Das ist von mir
nur angedacht und nicht durchdacht. ;-)

mfg
Josef
--
EPT: (Access Error Prevention Table) http://access.joposol.com/
FAQ: (Access-FAQ von Karl Donaubauer) http://www.donkarl.com/
André Minhorst
2009-07-15 13:28:48 UTC
Permalink
Hallo Josef,
Post by Josef Poetzl
Post by André Minhorst
aktuell verwende ich einen Platzhalter [MyValue], der zur Validierzeit mit
dem Wert des betroffenen Steuerelements gefüllt wird.
Wie ich Ausdrücke mit anderen Steuerelementen handhabe, weiß ich allerdings
noch nicht, mal sehen.
Für nur einen Vergleich würde ein Vergleichsoperator und die
Referenzübergabe des anderen Steuerelements ausreichen.
| [Wert von A] >= [Wert von B] * [Wert von C]
Ohne Eval wird es vermutlich nicht laufen. Als Platzhalter würde ich
[xxx] ansehen und diesen Eintrag ("xxx") in der Control-Auflistung
suchen.
genau das denke ich auch, daher verwende ich dort nun Eval.
Post by Josef Poetzl
[...]
Post by André Minhorst
Post by Josef Poetzl
Wenn ich dein Vorhaben richtig verstanden habe, geht es einerseits um
die Vereinfachung bei der Einstellung von Gültigkeitsregeln und eine
zentralisierte Abarbeitung. Das zwingt imo nicht unbedingt dazu, dass
man die eingebauten Gültigkeitsprüfungen komplett ersetzt.
Eingebaute Gültigkeitsregeln (also etwa die Prüfung auf eine gültige Zahl
im Zahlenfeld) sowie benutzerdefinierte Gültigkeitsregeln übergeht die
Validierungsklasse. Das geschieht bewusst, damit die Anwendung die über die
benutzerdefinierte Validierung definierten Meldungen anzeigen kann.
Ich dachte an das Setzen der Gültigkeitsregel durch die
Validierungsklasse, damit Access das Prüfen übernehmen kann.
Die Standardmeldung müsste doch eigentlich abfangbar sein, oder?
Z. B. auf Form.Error reagieren und statt der Standardmeldung die
Meldung der Validierungsklasse anzeigen.
Ob das gut und stabil funktioniert, weiß ich nicht. Das ist von mir
nur angedacht und nicht durchdacht. ;-)
Ich will ja gerade die Gültigkeitsregeln übergehen, damit ich selbst über
die Validierungsklasse und die Festlegung der Validierungsregeln die
Reihenfolge und das Aussehen der erscheinenden Validierungsmeldungen
festlegen kann.

Das klappt so auch ganz gut.

Ciao
André
--
http://www.access-entwicklerbuch.de
http://www.access-im-unternehmen.de
Loading...