Office Forum
www.Office-Loesung.de
Access :: Excel :: Outlook :: PowerPoint :: Word :: Office :: Wieder Online ---> provisorisches Office Forum <-
Wert aus Textfeld in Variable
zurück: Open.Recordset-Fehler weiter: Lotus Notes via VBA (Access) ansteuern Unbeantwortete Beiträge anzeigen
Neues Thema eröffnen   Neue Antwort erstellen     Status: Antwort Facebook-Likes Diese Seite Freunden empfehlen
Zu Browser-Favoriten hinzufügen
Autor Nachricht
mannheimer sprachendienst
Access Fortgeschrittener


Verfasst am:
10. Feb 2012, 16:08
Rufname:

Wert aus Textfeld in Variable - Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Hi, irgendwie werd ich einfach nicht fündig.

Ich versuche in meiner Datenbank den Wert aus einem Textfeld in eine Variable zu schreiben und irgendwie will das nicht hinhauen. Der gibt mir dann immer folgenden Fehler:
Zitat:
Laufzeitfehler '2465'
Anwendungs- oder objektdefinierter Fehler
Hier mein Code:
Code:
    Dim strUser As String

    strUser = Forms!MeinFormular.MeinTextfeld
Ich hoffe ihr könnt mir da helfen
MissPh!
Office-VBA-Programmiererin


Verfasst am:
10. Feb 2012, 16:16
Rufname:
Wohnort: NRW


AW: Wert aus Textfeld in Variable - AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Hallo,

an den beiden Codezeilen lässt sich nicht erkennen. In welchem Kontext wird das ausgeführt, welches Formular wird da angesprochen und wie heißt es wirklich?
Wenn es sich um das aktuelle Formular handelt, solltest du "Me" verwenden.

_________________
Gruß MissPh!
mannheimer sprachendienst
Access Fortgeschrittener


Verfasst am:
10. Feb 2012, 16:23
Rufname:

AW: Wert aus Textfeld in Variable - AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Das Formular ist im Hintergrund geöffnet.

Hier der komplette Code mit Kontext:
Code:
Private Sub btn_his_ab_Click()
    Dim strUser As String
   
    strUser = Forms!frm_menue.txt_menue_benutzername
  ' Datum und AB anfügen
    If IsNull(Me.AP_Historie) Then Me.AP_Historie = Me.AP_Historie & strUser & Format(Now, "dd.mm.yyyy hh:mm") & ": AB" Else Me.AP_Historie = Me.AP_Historie & vbCrLf & strUser & Format(Now, "dd.mm.yyyy hh:mm") & ": AB"
  ' Datum in letzter Kontakt schreiben
    Me.AP_letzter_Kontakt = Now()
  ' Anrufe zählen
    Forms!frm_akquise.txt_count_alle = Forms!frm_akquise.txt_count_alle + 1
    Forms!frm_akquise.txt_count_wv = Forms!frm_akquise.txt_count_wv + 1
  ' Formular schließen
    DoCmd.Close acForm, Me.Name
End Sub
MissPh!
Office-VBA-Programmiererin


Verfasst am:
10. Feb 2012, 16:30
Rufname:
Wohnort: NRW

AW: Wert aus Textfeld in Variable - AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Sehe ich das richtig, dass du es hier mit drei verschiedenen Formularen zu tun hast: "frm_menue", "frm_akquise" und "Me"?

Bist du sicher, dass der Fehler aus der ersten Zuweisung resultiert, die Meldung macht irgendwie keinen Sinn.
Allerdings passt der Text auch nicht zur Fehlernummer - kannst du das bitte noch einmal überprüfen?!

_________________
Gruß MissPh!
mannheimer sprachendienst
Access Fortgeschrittener


Verfasst am:
10. Feb 2012, 16:36
Rufname:


AW: Wert aus Textfeld in Variable - AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Es handelt sich in der Tat um 3 Formulare.
Vorher hat es einwandfrei funktioniert und wenn ich der Variable einen Wert gebe, funktioniert es auch.
Code:
    Dim strUser As String

    strUser = "test"
Und der Fehler steht wirklich so wie ich es geschrieben habe


screena.jpg
 Beschreibung:
 Dateigröße:  12.8 KB
 Angeschaut:  826 mal

screena.jpg


MissPh!
Office-VBA-Programmiererin


Verfasst am:
10. Feb 2012, 16:44
Rufname:
Wohnort: NRW

AW: Wert aus Textfeld in Variable - AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Gehe mal in den VBA-Editor, lass dir den Direktbereich anzeigen und gib dort folgendes ein:
Code:
?accesserror(2465)
Was siehst du? Wink

Es hat ja offensichtlich etwas mit dem Zugriff auf das Formular-Steuerelement zu tun. Was ist das Besondere daran?
Handelt es sich um drei voneinander unabhängige Hauptformulare? Was löst den Code aus?
Warum drückst du in Formular A auf einen Knopf, um Daten aus Formular B in Formular C zu schreiben? Was steckt dahinter?

Sorry, lauter scheinbar unsinnige Ansätze, aber irgendwie müssen wir das Problem ja einkreisen.
Oder kannst du dazu vielleicht eine Beispiel-DB hochladen, um den Fehler vorzuführen?

_________________
Gruß MissPh!
mannheimer sprachendienst
Access Fortgeschrittener


Verfasst am:
10. Feb 2012, 17:36
Rufname:

AW: Wert aus Textfeld in Variable - AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Ich lade anbei die Beispieldatenbank hoch!

Das Problem ist eigentlich entstanden, da ich eine Benutzerverwaltung haben möchte. Nun habe ich in das Menü den Benutzernamen reingeschrieben wil ich mit den globalen Variablen etc. nicht klarkomme.

Benutzername Test und PW: test

Du klickst auf den Ansprechpartner im Ufo doppelt und dann AB!

Die Datenbank ist aber noch nicht vollständig!!!!!



test.zip
 Beschreibung:

Download
 Dateiname:  test.zip
 Dateigröße:  81.66 KB
 Heruntergeladen:  12 mal

MissPh!
Office-VBA-Programmiererin


Verfasst am:
10. Feb 2012, 17:49
Rufname:
Wohnort: NRW

AW: Wert aus Textfeld in Variable - AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Autsch - das Feld heißt benutzer, nicht benutzername!

Und wenn du es mit "Forms!frm_menue!txt_menue_benutzername" angesprochen hättest, hättest du auch eine gescheite Fehlermeldung bekommen, nämlich
Zitat:
Neue Datenbank kann das in Ihrem Ausdruck angesprochene Feld 'txt_menue_benutzername' nicht finden.
Razz
(hoffentlich lesen Christan und alle weiteren !-Verweigerer dies mit!!)

_________________
Gruß MissPh!
mannheimer sprachendienst
Access Fortgeschrittener


Verfasst am:
10. Feb 2012, 17:54
Rufname:

AW: Wert aus Textfeld in Variable - AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Ohjeee, danke
MissPh!
Office-VBA-Programmiererin


Verfasst am:
10. Feb 2012, 17:59
Rufname:
Wohnort: NRW

Re: AW: Wert aus Textfeld in Variable - Re: AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Nachtrag:
MissPh! - 10. Feb 2012, 16:49 hat folgendes geschrieben:
...hättest du auch eine gescheite Fehlermeldung bekommen
und zwar mit derselben Fehlernummer!

Hast du das mal wie vorgeschlagen im Direktfenster getestet? Das hätte dir einen Tipp geben können... Wink

_________________
Gruß MissPh!
Gast



Verfasst am:
10. Feb 2012, 18:39
Rufname:

AW: Wert aus Textfeld in Variable - AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

nee... ich hatte nur die Fehlermeldung mit F1 nachgeschlagen
Bitsqueezer
Office-VBA-Programmierer


Verfasst am:
11. Feb 2012, 20:28
Rufname:

AW: Wert aus Textfeld in Variable - AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Hallo MissPh,

da muß ich Dich wohl korrigieren (zum Thema "!").

1. der Code in der Beispieldatenbank war nicht kompiliert, also konnte der Compiler auch nichts melden (sonst wäre das hier sofort aufgefallen, das spuckt der Compiler bereits als Fehler aus):
Code:
Private Sub Form_Dirty(Cancel As Integer)
    Me.Query   ' Fehlermeldung beim Compilieren
End Sub
2. nimmt man die Zeile raus, kommt keine weitere Fehlermeldung bei der folgenden Zeile, die Du offenbar meinst:
Code:
    Forms!frm_menue.txt_menue_benutzername
Du meinst ja, der Compiler hätte hier meckern müssen, weil offenbar die "."-Syntax verwendet wurde, aber das ist ein Irrtum.

Hier wurde die "Forms"-Collection verwendet, über die "!"-Kurzform. Und damit ist alles, was nach dem "!" kommt, für den Compiler uninteressant (drum sagte ich ja in dem anderen Thread, daß alles, was nach "!" kommt, vom Compiler ignoriert wird).

Hintergrund ist, daß die eigentlich "normale" Schreibweise für diesen Weg so aussieht:
Code:
    Forms("frm_menue").txt_menue_benutzername
Auch diese Schreibweise wird vom Compiler ignoriert! Grund ist, daß die Forms-Auflistung eine ganz normale Collection ist, nur daß sie von Access selbst verwaltet wird. Eine Collection ist ein Container, der beliebige Objekte aufnehmen kann, theoretisch könnte in der gleichen Collection eine String-Variable ebenso hinzugefügt werden wie ein Report oder ein eigenes Objekt aus einem eigenen Klassenmodul oder sonst irgendein Objekt. Da die Forms-Collection von Access verwaltet wird, gelangen dort "nur" Formulare hinein. Es ist also eine von Access typisierte Collection, Access weiß, daß alle Objekte in der Forms-Collection nur Formulare sein können - aber auch nicht mehr.

Im Gegensatz zu VBA wurde Access selbst in einer objektorientierten Programmiersprache geschrieben, und da gibt es Vererbung. Die sieht so aus, daß jedes Objekt mit dem allgemeinen Basisobjekt "Object" beginnt, das ja auch in VBA zur Verfügung steht. "Form" ist auch ein Klassenmodul (keins, das in VBA zu sehen ist, aber in C# oder C++, in dem Access vermutlich geschrieben wurde) und bringt von Haus aus die bekannten Eigenschaften und Methoden mit. Aber "Form" ist ein allgemeines Klassenmodul, das die Basis für jede spezielle Implementierung eines Formulars ist. Da Access die "Forms"-Collection bereits auf "Form" typisiert hat (also nur Objekte dieses Typs in diese Collection gelangen können), kann VBA alle zu der Basisklasse gehörenden Eigenschaften und Methoden zur Verfügung stellen. Du kannst also im Direktfenster von VBA schreiben:
Code:
Forms("Test").
und sofort klappt das IntelliSense-Fenster auf und zeigt Dir alle Eigenschaften und Methoden an, die jedem Formular gemeinsam sind. Aber eben nur die. Ein eigenes Objekt wie ein Textcontrol etwa kann hier nicht angezeigt werden, weil es zu der speziellen Implementierung des Formulars "frm_menue" gehört. Also genauer formuliert: Das in VBA/im Formulareditor erzeugte Klassenmodul "frm_menue" basiert auf dem Klassenmodul "Form", es erbt automatisch alle allgemeinen Methoden und Eigenschaften. Deswegen stehen Dir in VBA sofort Methoden wie "Me.Requery" zur Verfügung, denn wenn es ein "blankes" Klassenmodul wäre, müßtest Du eine Public Sub "Requery" selbst schreiben und ausprogrammieren.

Da es eine typisierte Collection ist und Access den Typ "Form" kennt, gibt es auch eine Compilermeldung, wenn Du die (sinnfreie) Zeile in den Code schreibst:
Code:
Forms("Test").CommandBeforeExecute
Wenn Du compilierst, gibt es eine Fehlermeldung.

Schreibst Du aber:
Code:
Forms("Test").Mickymaus
gibt es keine Fehlermeldung. Warum? Weil Access nur alles checkt, was zu der allgemeinen "Form"-Klasse gehört, "Mickymaus" kennt Access nicht, läßt dies aber ohne Prüfung zu, da dies eine "Public Sub Mickymaus" sein könnte, die in der speziellen Implementierung "frm_menu" enthalten sein könnte. Ebenso würde hier jeder eigene Controlname zugelassen werden, daher funktioniert auch
Code:
Forms!frm_menue.txt_menue_benutzername
bzw.
Code:
Forms("frm_menue").txt_menue_benutzername
In dieser Schreibweise kann der Compiler nicht einmal unterscheiden, ob es sich bei "txt_menue_benutzername" um ein Control oder eine Public Sub/Function/Property handelt. Darum erhältst Du auch keine weitere IntelliSense-Unterstützung, wenn Du nach "txt_menue_benutzername" einen Punkt schreibst. Wenn VBA den Typ erkennen würde, dann würde es nun alle allgemeinen Methoden und Eigenschaften der Basisklasse "Textbox" anzeigen. Da es aber ebensogut z.B. eine Public Sub sein könnte, kann VBA hier nicht weiterhelfen.

Die Punktschreibweise ist also nicht alleine durch das Schreiben von "." abgesichert, sondern durch Typisierung der Objekte. Compilersicherer Code entsteht nicht durch ".", sondern durch korrekte Formulierung.

Die korrekte Formulierung hier wäre also, das spezielle Klassenmodul als Typ anzugeben, dann findet man in IntelliSense sowohl den korrekten Control-Namen wie auch weitere IntelliSense-Unterstützung nach einem weiteren Punkt. Also zum Beispiel so:
Code:
Form_frm_menue.txt_menue_benutzer.
Jetzt zeigt IntelliSense mir alle allgemeinen Eigenschaften und Methoden der Textbox-Klasse an. Und jetzt ist der Code auch compilersicher, denn wenn ich manuell "benutzername" schreibe und compiliere, erhalte ich eine Fehlermeldung vom Compiler, daß dieser Controlname unbekannt ist. Ebensogut würde "Form_frm_menue.Mickymaus" als Fehler erkannt und ausgeworfen werden. Der Unterschied ist, daß mit der Angabe von "Form_frm_menue" die Basisklasse nun nicht mehr das allgemeine "Form" ist, sondern die spezielle Klasse "Form_frm_menue", das heißt, der Compiler überprüft alle allgemeinen Eigenschaften und Methoden der Form-Klasse, aber auch alle speziellen aus der "frm_menue"-Klasse.

Trotzdem ist auch diese Schreibweise eigentlich nicht "sauber". Denn die Angabe von "Form_frm_menue" bezieht sich nicht auf eine Instanz eines Objektes, sondern auf den Code des Klassenmoduls. Im objektorientierten VB.NET etwa würde man solche Methoden und Eigenschaften als "Shared" deklarieren müssen, damit man sie auf diese Weise ansprechen kann (das ist sozusagen eine Mischung aus Standardmodul und Klassenmodul, die es in VBA so nicht gibt). Access schaut bei so einer Formulierung selbst in die Forms-Collection und wenn es dort ein Formular mit diesem Namen gibt, dann wird dessen Instanz auf diese Weise verwendet. Das ist quasi "getürkt" und versagt seinen Dienst spätestens dann, wenn man Formulare nicht mit DoCmd.OpenForm öffnet, was nur exakt eine Instanz zuläßt, sondern wenn man Formulare als echte Objektinstanzen beliebiger Menge öffnet, so daß es x Objekte des Typs "frm_menue" gibt. Jetzt kann man auf diese Weise die spezielle Objektinstanz nicht mehr ansprechen, da "Form_frm_menue" nur nach dieser einen Instanz schaut.

Also wie wäre es richtig? Indem man eine Objektvariable des Klassenmodultyps deklariert und diese mit dem gesuchten Objekt aus der Forms-Collection versieht. Also so:
Code:
    Dim objFrmMenue As Form_frm_menue

    Set objFrmMenue = Forms("frm_menue")
    strUser = objFrmMenue.txt_menue_benutzer
Dieser Code wäre auch für jede andere Collection verwendbar, in die man Formulare des Typs "frm_menue" hineinstellt. Er ist compilersicher und typsicher. Und man erhält volle IntelliSense-Unterstützung, die das Leben als Programmierer viel einfacher macht.

Wie gesagt, wenn es um die allgemeine Forms-Collection geht, dann spielt es keine Rolle, ob man es so macht oder mit der getricksten Kurzfassung "Form_frm_menue". Beides funktioniert, beides ist typsicher und compilersicher.

Wenn man nun das Formular "frm_menue" mehrfach öffnen möchte, dann geht das zum Beispiel so (z.B. in einem Standardmodul):
Code:
Public colMenueForms As Collection

Public Sub TestMenues()
    Dim i As Long
    Dim objFrmMenue As Form_frm_menue

    Set colMenueForms = New Collection
    For i = 1 To 10
        Set objFrmMenue = New Form_frm_menue
        objFrmMenue.Visible = True
        colMenueForms.Add objFrmMenue, objFrmMenue.Name & i
    Next i
End Sub
Schreibe ich jetzt folgende Zeile im Direktfenster:
Code:
    Form_frm_menue.Detailbereich.BackColor = RGB(255, 255, 255)
passiert gar nix. Denn wenn man alternativ schreibt
Code:
    Forms("frm_menue").BackColor = RGB(255, 255, 255)
meldet VBA, daß es kein Formular namens "frm_menue" in der Forms-Collection gibt. Trotzdem stehen alle Formulare in dieser Collection, das kann man schnell prüfen, wenn man sich den Inhalt im Überwachungsfenster anzeigen läßt oder eingibt:
Code:
    Forms(3).BackColor = RGB(255, 255, 255)
Eines der 10 hat nun eine neue Farbe. Grund ist, daß in der Basisklasse "Form" automatisch jede neue Instanz in die Forms-Auflistung aufgenommen wird. Da die Forms-Collection eine Collection ist und einen eindeutigen String-Key benötigt, verwendet Access per Default immer den Formularnamen. Darum geht auch Forms("frm_menue"). Aber der Key wird nur verwendet, solange man DoCmd.OpenForm verwendet. Wenn man x Formulare auf die beschriebene Weise öffnet, kann der Name nicht mehr funktionieren, der wäre nun nicht mehr eindeutig. Also erzeugt Access intern einen eigenen Key, von dem ich allerdings auch nicht weiß, wie der lautet. Da man eine Collection aber immer mit Key und Indexnummer ansprechen kann, kann man mit "Forms(3)" auf jeden Fall auf eine Instanz zugreifen. Hier ist aber nicht sicher, welche das ist, also nimmt man einfach eine eigene Collection wie in dem Beispiel und schon hat man einen genauen Key. Daher funktioniert es nun so:
Code:
    colMenueForms("frm_menue1").Detailbereich.BackColor = RGB(255, 0, 255)
Jetzt wird exakt Formular 1 (i=1 in der Schleife) einen Magenta-Hintergrund haben. Aber wenn Du das ausprobierst, stellst Du wieder fest, daß nach ")." keine IntelliSense-Unterstützung mehr kommt, im Gegensatz zu der Forms-Auflistung.

Grund ist, daß eine in VBA definierte Collection keine typsichere Collection ist. Hier kannst Du grundsätzlich alles hineinpacken, es gingen also ohne weiteres folgende Zeilen:
Code:
    Dim strTest As String

    colMenueForms.Add strTest
Wenn Du Dir im Überwachungsfenster nun die Collection "colMenueForms" anschaust, siehst Du, daß alle Items vom Typ "Variant" sind, wobei die Items 1-10 vom Untertyp "Object/Form_frmMenue" sind, während Item 11 nun "Variant/String" ist. Eine Collection "frißt" eben alles, was man ihr gibt, mit und ohne Key. Da ich hier keinen Key mehr angegeben habe, könnte ich nur mit "colMenueForms(11)" auf den String zugreifen.

Die typsichere Verwendung MIT IntelliSense-Unterstützung, die auch compilersicher ist, ist dann so wie oben beschrieben. Beispiel:
Code:
Public Sub ZeigeNamen()
    Dim i As Long
    Dim objFrmMenue As Form_frm_menue
   
    For i = 1 To 10
        Debug.Print colMenueForms(i).Name
    Next i
    For Each objFrmMenue In colMenueForms
        Debug.Print objFrmMenue.Name
    Next i
End Sub
Die erste Schleife holt aus der Collection jedes Objekt vom allgemeinen Typ "Variant/Object". Sie ist nicht typsicher und nicht compilersicher, trotz ".". Die zweite Variante weist dem Objekt "objFrmMenue" während der Schleife wieder den korrekten Klassenmodultyp "Form_frm_menue" zu, damit ist ".Name" sowohl in IntelliSense zu sehen, als auch vom Compiler prüfbar. Schreibe ich in beiden Schleifen manuell ".Name1" dahinter, wird der zweite Code einen Compilerfehler produzieren, der erste nicht, da "Object" eben alles beinhalten kann und nicht prüfbar ist.

Die Vererbung von Klassen, die Access selbst intern verwendet, kann man bei Objekten aus dem Applikations-Objektmodell auch ausnutzen, da man Objekte auf verschiedene Arten typisieren kann und so unterschiedliche Compilerunterstützung erhält.

Es wäre also ebenso so möglich:
Code:
Public Sub ZeigeNamen()
    Dim objFrmMenue As Object
    Dim objFrmMenue2 As Access.Form

    For Each objFrmMenue In colMenueForms
        Debug.Print objFrmMenue.Name
    Next objFrmMenue
    For Each objFrmMenue2 In colMenueForms
        Debug.Print objFrmMenue2.Name
    Next objFrmMenue2
End Sub
Im ersten Fall wird das Objekt als einfaches "Variant/Object" typisiert, damit also so allgemein, daß es jedes beliebige Objekt aufnehmen kann - Ergebnis ist, daß "Name" weder von IntelliSense gezeigt, noch vom Compiler überprüft wird. Im zweiten Fall ist es etwas spezieller auf "Form" typisiert, so daß man schon mal IntelliSense-Unterstützung hat, aber es ist immer noch eine allgemeine Klasse. In beiden Fällen würde "Name1" nicht als Fehler ausgegeben werden, denn die Objekthierarchie besagt, daß es noch Kindklassen geben kann, die spezieller implementiert sind, da deren Typ aber unbekannt ist, wird es nicht geprüft ("Object" weiß nicht, ob das letztendliche Objekt "Form" oder "Report" oder "Form_frm_menue" oder "clsMeineKlasse" oder "String" ist und "Form" weiß nicht, ob das letztendliche Objekt "frm_menue" oder "frm_login" ist).

Da man in VBA keine eigene Vererbung verwenden kann (außer in Grenzen mit Interface-Klassen), keine eigenen "Unterklassen" außer denen, die über das Access-Objektmodell vererbt werden, kann man zumindest die Vererbung, die das Objektmodell anbietet, für seine Zwecke ausnutzen. Denn wenn man wie im letzten Beispiel das Objekt nur allgemein als "Form" deklariert, dann kann man dies zum Beispiel ausnutzen, wenn die Collection 10 verschiedene Formulartypen enthält, so daß eine spezielle Typisierung nicht möglich ist. Nun kann man aber die allgemeinen Eigenschaften und Methoden verwenden, zum Beispiel so:
Code:
Public Sub SchliesseFormulare()
    Dim i As Long
    Dim lngCount As Long
    Dim objFrm As Access.Form
   
    For Each objFrm In colMenueForms
        objFrm.Visible = False
    Next objFrm
    lngCount = colMenueForms.Count
    Set colMenueForms = Nothing
    For i = 1 To lngCount
        DoCmd.Close acForm, "frm_menue"
    Next i
End Sub
Da alle Formulare über die Eigenschaft "Visible" verfügen, spielt es keine Rolle, wenn man alle Objekte in der Collection über ihre Elternklasse "Form" anspricht. Auch das ist typ- und compilersicher.
Das "Visible" macht ein Formular aber nur unsichtbar und entfernt es nicht aus der Collection. Das Formular existiert noch immer. Man kann es jederzeit wieder mit "Visible=True" sichtbar machen. Auch das Setzen der Collection auf Nothing löscht nur die Objektreferenzen aus der Collection, da dummerweise aber jedes geöffnete Formular auch in der "Forms"-Collection landet, "leben" die Objekte dort weiter, was u.U. zu Schwierigkeiten führen kann, denn außer über die Indexnummer kann man nicht auf die Objekte zugreifen, da Access einen unbekannten String-Key verwendet (wenn überhaupt). Eine "normale" Collection verfügt immer über eine "Remove"-Methode, da dies aber eine bereits typisierte Collection ist, kann man hier leider kein "Remove" verwenden, daher die zweite Schleife, die das gute alte "DoCmd.Close" verwendet, um 10 mal den Befehl zu schicken. Da der Befehl das jeweils erste gefundene Formular aus der Forms-Collection entfernt, das diesen Namen hat, werden so nun auch die "Reste" in der Forms-Collection sauber aufgeräumt, ansonsten entscheidet der Garbage Collector, wann die Formulare wirklich entsorgt werden. Eine saubere "Close"-Implementierung im Form-Objekt selbst wäre sicherlich die bessere Lösung gewesen, aber da "DoCmd" ja in erster Linie für Makros gedacht ist, hat man sich wohl so entschieden. In Excel, das ja keine Form-Objekte von Access kennt, sondern UserForm, gibt es dagegen einen Load und Unload-Befehl.

Ich hoffe, ich konnte mit diesen Ausführungen eindeutig aufzeigen, daß der "." dem "!" jederzeit überlegen und vorzuziehen ist, demgegenüber gibt es nur das permanente Argument, daß "!" performanter sei.
Hier mal ein kleiner Zeitvergleich für beide Methoden in der Beispieldatenbank oben:
Code:
Public Sub TestTime()
    Dim d As Date
    Dim x As Long
    Dim s As Variant

    d = Now
    For x = 1 To 1000000
        s = Forms!frm_menue!txt_menue_benutzer
    Next x
    Debug.Print DateDiff("s", d, Now())
    d = Now
    For x = 1 To 1000000
        s = Form_frm_menue.txt_menue_benutzer
    Next x
    Debug.Print DateDiff("s", d, Now())
End Sub
Ergebnis auf meinem 4-Kern-Prozessor (immerhin 1 Million Schleifendurchläufe !):
21 Sekunden für die erste Methode, 14 Sekunden für die zweite.

Also irgendwie ist damit auch das Performance-Argument nicht mehr haltbar. Und das Ergebnis verwundert auch nicht: Im ersten Fall wird alles nach "!" vom Compiler ignoriert. Der Code muß also zur Laufzeit geprüft werden, und zwar in jedem Schleifendurchlauf, da "!txt_menue_benutzer" bewirkt, daß dieses Control in frm_menue in der Controls-Auflistung zur Laufzeit gesucht wird, ebenso wie in jedem Schleifendurchlauf "!frm_menue" in der Forms-Auflistung gesucht wird. Die zweite Variante sucht nur typsicher nach exakt dem Objekt "frm_menue" in der Forms-Auflistung, kann dann aber direkt auf das Objekt "txt_menue_benutzer" zugreifen und muß nicht erst prüfen, ob es auch wirklich existiert - das hat der Compiler schon erledigt.

Man kann die Objektmethode noch geringfügig verbessern, denn ein Durchsuchen der Forms-Collection kann man einfach verhindern, indem man das Objekt so zuweist:
Code:
    Dim objFrmMenue As Form_frm_menue

    d = Now
    Set objFrmMenue = colMenueForms("frm_menue1")
    For x = 1 To 1000000
        s = objFrmMenue.txt_menue_benutzer
    Next x
    Debug.Print DateDiff("s", d, Now())
Wenn man das Formular "frm_menue" einmal manuell öffnet (Doppelklick) und dann die 10 zusätzlichen Formulare wie oben erzeugt, werden beide geringfügig langsamer, da es mehr Formulare in der Collection gibt. Ergebnis ist nun 22 und 15 (die Objektmethode ist also immer noch schneller), die zweite Methode mit 14 noch einen Tick schneller.

Wenn ich nun aber die 10 Formulare zuerst öffne und dann das Formular nochmal per Doppelklick, steht das Formular nun als letztes in der Forms-Collection. Die Zeiten sehen nun drastisch anders aus: Methode 1 braucht nun 41 Sekunden (ein Beweis dafür, daß eine Collection seriell durchsucht wird, bis das richtige Element gefunden wurde), während die anderen beiden Methoden immer noch bei 15 und 14 liegen.

Aber man kann natürlich auch bei der "!"-Methode ein Objekt zuweisen:
Code:
    Dim objFrmMenue As Form_frm_menue

    d = Now
    Set objFrmMenue = Forms!frm_menue
    For x = 1 To 1000000
        s = objFrmMenue!txt_menue_benutzer
    Next
    Debug.Print DateDiff("s", d, Now())
Nun braucht auch diese Methode nur noch 15 Sekunden.

Es beweist also, daß man mit der Punkt-Methode schneller und sicherer ist, während man Performance bei der "!"-Methode nur mit genauer Programmierung erreicht, aber keine Fehler vom Compiler gemeldet bekommt. Weiterhin steht für mich jedenfalls also fest, daß es in meiner Programmierung keine Ausrufezeichen geben wird.

Gruß

Christian
MissPh!
Office-VBA-Programmiererin


Verfasst am:
19. März 2012, 23:22
Rufname:
Wohnort: NRW

Re: AW: Wert aus Textfeld in Variable - Re: AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Hallo Christian,
Bitsqueezer - 11. Feb 2012, 19:28 hat folgendes geschrieben:
da muß ich Dich wohl korrigieren (zum Thema "!").

Du meinst ja, der Compiler hätte hier meckern müssen, weil offenbar die "."-Syntax verwendet wurde, aber das ist ein Irrtum.
Hier wurde die "Forms"-Collection verwendet, über die "!"-Kurzform. Und damit ist alles, was nach dem "!" kommt, für den Compiler uninteressant (drum sagte ich ja in dem anderen Thread, daß alles, was nach "!" kommt, vom Compiler ignoriert wird).
so hatte ich das nicht verstanden, Danke für die Aufklärung und deinen wieder mal alle Erwartungen übertreffenden, ausführlichen und überaus informativen Beitrag.

Ich denke, du solltest dein Talent dem Schreiben von Lehrbüchern widmen, dann brauchst du bei Bedarf und Gelegenheit nur noch auf Kapitel und Seiten-Nr. zu verweisen. Wink

_________________
Gruß MissPh!
Bitsqueezer
Office-VBA-Programmierer


Verfasst am:
20. März 2012, 08:49
Rufname:


AW: Wert aus Textfeld in Variable - AW: Wert aus Textfeld in Variable

Nach oben
       Version: Office 2007

Hallo MissPh,

danke für die Blümchen... Smile

Ich hatte schon gar nicht mehr damit gerechnet, daß auf den Artikel noch jemand antworten würde..Wink

Ich hatte auch schon mal überlegt, ob das einen Sinn machen würde, aber in der Flut von Access-Büchern, die es schon gibt, wird man eher kaum noch einen Verleger finden, der da investiert. Ich habe eher den Eindruck, in einem Forum erreicht man viel mehr Leser über eine viel längere Zeit und darüber hinaus ist es interaktiv, so daß man gemeinsam neue Wege finden kann - ich habe schließlich auch eine Menge über Foren und Ausprobieren und Lösungsversuchen von Problemen Anderer gelernt. Ein Buch ist mehr wie ein starrer Monolog mit eher wenig Feedback. Und zuletzt, verdienen kann man mit Fachbüchern auch nicht wirklich viel, muß aber sehr viel Zeit und Energie hineinstecken, damit es überhaupt angenommen und gedruckt wird.

Gruß

Christian
Neues Thema eröffnen   Neue Antwort erstellen Alle Zeiten sind
GMT + 1 Stunde

Diese Seite Freunden empfehlen

Seite 1 von 1
Gehe zu:  
Du kannst Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum nicht posten
Du kannst Dateien in diesem Forum herunterladen

Verwandte Themen
Forum / Themen   Antworten   Autor   Aufrufe   Letzter Beitrag 
Keine neuen Beiträge Access Tabellen & Abfragen: Wert von der Tabelle abziehen 1 elmar9700 892 10. Jul 2005, 22:22
stpimi Wert von der Tabelle abziehen
Keine neuen Beiträge Access Tabellen & Abfragen: Wert erhöhen um 1 in einer Abfrage 9 schwieche 5576 31. Mai 2005, 02:16
schwieche Wert erhöhen um 1 in einer Abfrage
Keine neuen Beiträge Access Tabellen & Abfragen: 2 Tabellen verbinden trotz Auto Wert ID 3 Miss Ahnungslos 7788 06. Mai 2005, 22:57
Dalmatinchen 2 Tabellen verbinden trotz Auto Wert ID
Keine neuen Beiträge Access Tabellen & Abfragen: Hochzählen ab bestimmten Wert 3 vitalik 893 06. Mai 2005, 12:47
stpimi Hochzählen ab bestimmten Wert
Keine neuen Beiträge Access Tabellen & Abfragen: Überprüfen ob Wert in Tabelle = NULL 3 Cossack 1498 18. Apr 2005, 17:52
Gast Überprüfen ob Wert in Tabelle = NULL
Keine neuen Beiträge Access Tabellen & Abfragen: WHERE Wert Is manchmal Null 1 JTR 606 11. Feb 2005, 17:50
lothi WHERE Wert Is manchmal Null
Keine neuen Beiträge Access Tabellen & Abfragen: Textfeld Abfrage 2 Sandro 712 02. Feb 2005, 11:56
Sandro Textfeld Abfrage
Keine neuen Beiträge Access Tabellen & Abfragen: Wenn Wert nicht vorhanden nimm den nächsten 2 Ogdo 788 29. Dez 2004, 12:40
Gast Wenn Wert nicht vorhanden nimm den nächsten
Keine neuen Beiträge Access Tabellen & Abfragen: Leerzeichen in Textfeld entfernen 2 Francesco 1291 17. Dez 2004, 13:46
Francesco Leerzeichen in Textfeld entfernen
Keine neuen Beiträge Access Tabellen & Abfragen: Abfrage mit sum, max Wert und verhätnis summe/max anzeigen? 1 IV 2531 04. Nov 2004, 18:14
Skogafoss Abfrage mit sum, max Wert und verhätnis summe/max anzeigen?
Keine neuen Beiträge Access Tabellen & Abfragen: Textlänge in einem Textfeld 4 brauchehilfe@office 2425 30. Okt 2004, 00:05
brauchehilfe@office Textlänge in einem Textfeld
Keine neuen Beiträge Access Tabellen & Abfragen: SQL - Abfrage ob ein Wert in der Tabelle enthalten ist 1 notausgang 1301 23. Sep 2004, 09:42
stpimi SQL - Abfrage ob ein Wert in der Tabelle enthalten ist
 

----> Diese Seite Freunden empfehlen <------ Impressum - Besuchen Sie auch: Microsoft Excel Tricks