Discussion:
Übergabe eines Array via public property
(zu alt für eine Antwort)
c***@web.de
2007-05-18 18:35:48 UTC
Permalink
Hallo,

ich möchte gerne ein Array an eine Userform via properties übergeben.
Leider funktioniert das nicht so wie ich erwarte.
Meine Versuche:

1.) in Routine, die übergeben soll wurde zuerst
alles mit Redim errArr(..) as String deklariert
(... sterht für irgendeinen Wert; ab und an
wurde preserver verwendet ;-))

Ergebnis:
"Datenfeld muss als Referenz übergeben werden"
wurde gemeckert

2.) anstelle String wurde alles mit Variant deklariert

Ergebnis:
Diesmal giert VBA nicht nach RyRef. Aber
bei der Zuweisung an ein Listenfeld via For-Each
zickte VBA seltsamerweise mit derv Forschleife

Auszug aus dem Code nach der Umstellung auf Variant):

In der UsaForm:

Private m_errArray() As Variant
'####### Schnittstelle Zeilenzähler Terminplaner (Haupttabelle)
Public Property Get errArray() As Variant
errArray = m_errArray
End Property
Public Property Let errArray(errCollection As Variant)
m_errArray = errCollection
End Property
....
sub uf_ini() ' bin faul ;-)
dim x as variant
for each x in errArray
me.lbxMeckerFenster.additem x
next x

In der rufenden ruthine:

....
frmMeckerFenster.errArray =errArray
.....

so.
Hat da jemand eine Idee (aber bitte keine globalen Variablen, die mag
ich absolut nicht :-)) ?

Merci für Eure Mühe

Gruß ChFa
Reiner Wolff
2007-05-18 20:48:10 UTC
Permalink
Moin Christian,
Post by c***@web.de
ich möchte gerne ein Array an eine Userform via properties übergeben.
Leider funktioniert das nicht so wie ich erwarte.
1.) in Routine, die übergeben soll wurde zuerst
alles mit Redim errArr(..) as String deklariert
(... sterht für irgendeinen Wert; ab und an
wurde preserver verwendet ;-))
"Datenfeld muss als Referenz übergeben werden"
wurde gemeckert
Als ich das dann probehalber mal mit 'ByRef' deklarierte, bekam ich die
nächste Fehlermeldung.

[2. gesnippelt]
Post by c***@web.de
so.
Hat da jemand eine Idee (aber bitte keine globalen Variablen, die mag
ich absolut nicht :-)) ?
Ein bischen gegoogelt und dann die Deklaration des zu übergebenden Arrays
entsprechend angepaßt, kurzum, bei mir funktioniert zumindest folgendes:
'Code in einem Modul
Sub test()
Dim frm As New UserForm1
Dim arTest() As String

'ReDim ist hier wohl der wichtigste Gimmik
ReDim arTest(3) As String

arTest(0) = "1"
arTest(1) = "2"
arTest(2) = "3"
arTest(3) = "4"

frm.arFehlerTexte = arTest
frm.Ini
frm.Show
End Sub

'Code im UserForm1
Private carFehlerTexte() As String

Public Property Get arFehlerTexte() As String()
arFehlerTexte = carFehlerTexte
End Property

Public Property Let arFehlerTexte(ByRef errCollection() As String)
carFehlerTexte = errCollection
End Property

Public Sub Ini()
Dim x As Variant
For Each x In carFehlerTexte
Me.ListBox1.AddItem x
Next x
End Sub

Ich hoffe, das funktioniert bei Dir genauso.

HTH
Gruß aus Kiel
Reiner
--
Es gibt Zeiten, wo einem alles gelingt. Aber das braucht niemanden zu
beunruhigen. Sie gehen sehr schnell vorüber...
c***@web.de
2007-05-19 20:23:11 UTC
Permalink
Hallo Reiner,

Danke für Deine Hilfe. Dein Code hat funktioniert und mich
erleuchtet ;-). Aber ich möchte noch ein paar Sachen dazutun bzw.
ändern.

Alsoooo

Sub test()
' mein Umbau nach dem ersten Test ergab,
' dass man diese Zeilen nicht benötigt:
' Dim frm As New UserForm1
' Dim arTest() As String

'ReDim ist hier wohl der wichtigste Gimmik - Richtig!!!
ReDim arTest(0) As String ' Mein Trick zu _
erkennen ob ein Fehler _
auftrat oder nicht
Dim i as byte
for i=1 to 4
arTest(0) = i
' Jetzt wird das Feld um 1 Feld vergrößert
' Behaltet dabei den ersten Wert
ReDim Preserve arTest(ubound(aetest)+1))
next i
UserForm1.arFehlerTexte = arTest
' frm.Ini --> warum nich nötig kommt später
UserForm1.Show
End Sub

'Code im UserForm1
' das m_ ist halt übliche schreibweise :-)
Private m_carFehlerTexte() As String

' in der Deklaration sehe ich meinen Fehler: String anstelle String ()
Public Property Get arFehlerTexte() As String()
arFehlerTexte = m_carFehlerTexte
End Property

Public Property Let arFehlerTexte(ByRef errCollection() As String)
m_carFehlerTexte = errCollection
End Property

' Und jetzt kommt der dicke Hund!!!!!
private sub UserForm_Activate()
<Listboxfüllen mit Schleife>
end sub

UserForm_Initialize() funktioniert nämlich nicht !!!! Dann meckert er
eine For-Schleife an!!

Ok Reiner, dann mal viel Merci und Spass

Gruss von Chris aus dem finstersten Teil von Neukölln ;-)
Reiner Wolff
2007-05-19 22:02:12 UTC
Permalink
Moin Christian
Post by c***@web.de
Danke für Deine Hilfe. Dein Code hat funktioniert und mich
erleuchtet ;-).
Das freut mich. Danke für die Rückmeldung.
Post by c***@web.de
Aber ich möchte noch ein paar Sachen dazutun bzw.
ändern.
Alsoooo
Sub test()
' mein Umbau nach dem ersten Test ergab,
' Dim frm As New UserForm1
Ja, Du kannst auch immer direkt auf UserForm1 verweisen.
Es gibt da allerdings durchaus Unterschiede. ZB kannst Du auf diese Weise
das Formular auch in mehreren Instanzen darstellen und trotzdem auf die
richtige Instanz zugreifen.
Aus diesem und anderen Erfahrungen, benutze ich - wenn ich dran denke -
dafür eine FormularVariable ;-)
Post by c***@web.de
' Dim arTest() As String
Er meckert zwar nicht, aber ein Array als erstes direkt mit ReDim zu
deklarieren, finde ich schon komisch.
Post by c***@web.de
'ReDim ist hier wohl der wichtigste Gimmik - Richtig!!!
ReDim arTest(0) As String ' Mein Trick zu _
erkennen ob ein Fehler _
auftrat oder nicht
Dim i as byte
for i=1 to 4
arTest(0) = i
' Jetzt wird das Feld um 1 Feld vergrößert
' Behaltet dabei den ersten Wert
ReDim Preserve arTest(ubound(aetest)+1))
Warum vergrößerst Du das Array, wenn Du sowieso nur in das erste Element
etwas hinein schreibst?
Post by c***@web.de
next i
UserForm1.arFehlerTexte = arTest
' frm.Ini --> warum nich nötig kommt später
Ok, der Kommentar kommt dann auch später ;-)
Post by c***@web.de
UserForm1.Show
End Sub
'Code im UserForm1
' das m_ ist halt übliche schreibweise :-)
Private m_carFehlerTexte() As String
Ja, "üblich" würdest Du dann aber das c (für KlassenVariable) wieder
wegnehmen ;-)
Post by c***@web.de
' in der Deklaration sehe ich meinen Fehler: String anstelle String ()
Public Property Get arFehlerTexte() As String()
arFehlerTexte = m_carFehlerTexte
End Property
Public Property Let arFehlerTexte(ByRef errCollection() As String)
m_carFehlerTexte = errCollection
End Property
' Und jetzt kommt der dicke Hund!!!!!
private sub UserForm_Activate()
<Listboxfüllen mit Schleife>
end sub
Das Activate-Ereignis hatte ich kurz angedacht, da es aber mehrfach
aufgerufen werden könnte, wenn der Benutzer das Formular zwischendurch
deaktiviert und danach wieder aktiviert, fand ich das für die
Initialisierung nicht sinnvoll.
Post by c***@web.de
UserForm_Initialize() funktioniert nämlich nicht !!!!
Stimmt, deswegen hatte ich eine eigene Public-Prozedur eingebaut.
Das Initialize-Ereignis wird nämlich bereits aufgerufen, bei der Zuweisung
der Array-Property. Allerdings direkt bevor das Array zugewiesen wird.
Post by c***@web.de
Dann meckert er eine For-Schleife an!!
Wie wo was?
Die Fehlermeldung kenne ich so überhaupt nicht.
Er dürfte an der Stelle anmeckern, dass in der For-Schleife ein leeres
Array nicht benutzt werden kann.

Gruß aus Kiel
Reiner
--
In jedem von Menschen geführten Unternehmen sucht
sich die Arbeit die niedrigste Stufe der Hierarchie.
c***@web.de
2007-05-20 11:00:27 UTC
Permalink
Moin Reiner
Post by Reiner Wolff
Es gibt da allerdings durchaus Unterschiede. ZB kannst Du auf diese Weise
das Formular auch in mehreren Instanzen darstellen und trotzdem auf die
richtige Instanz zugreifen.
Aus diesem und anderen Erfahrungen, benutze ich - wenn ich dran denke -
dafür eine FormularVariable ;-)
Das durchschaue ich derzeit noch nicht, wel ich noch zu sehr
sequentiell als OO denke.
(PS: kennst Du Richtung OO eine gute Grundlage fürs Selbsstudium?)
Post by Reiner Wolff
Post by c***@web.de
arTest(0) = i
Warum vergrößerst Du das Array, wenn Du sowieso nur in das erste Element
etwas hinein schreibst?
Da hast Du unbesehen Recht:
arTest(ubound(arTest)= i

ist richtig. Danach erst erhöhe ich den Speicher
Post by Reiner Wolff
Ja, "üblich" würdest Du dann aber das c (für KlassenVariable) wieder
wegnehmen ;-)
oops - ich war auf _ fixiert, also c_ ;-))))
Post by Reiner Wolff
Das Activate-Ereignis hatte ich kurz angedacht, da es aber mehrfach
aufgerufen werden könnte, wenn der Benutzer das Formular zwischendurch
deaktiviert und danach wieder aktiviert, fand ich das für die
Initialisierung nicht sinnvoll.
Das passiert nicht. Ich nutze die Form nur als eine etwas
konfortablere MsgBox
Aber der Hinweis ist nicht ganz unwichtig ..............
Post by Reiner Wolff
Stimmt, deswegen hatte ich eine eigene Public-Prozedur eingebaut.
Für die Zukunft zu merken.
Post by Reiner Wolff
Das Initialize-Ereignis wird nämlich bereits aufgerufen, bei der Zuweisung
der Array-Property. Allerdings direkt bevor das Array zugewiesen wird.
Aha, das wußte ich noch nicht.
Post by Reiner Wolff
Post by c***@web.de
Dann meckert er eine For-Schleife an!!
Er dürfte an der Stelle anmeckern, dass in der For-Schleife ein leeres
Du hast das schon oben mit Deinem Initialize-Ereignis erklärt..

Ok. Reiner. So etwas durchzudiskutieren ist doch lehrreich. Da lernt
man Dinge, die sonst nirgendwo stehen oder man sich mühevoll zusammen
suchen muss.


Merci, Gruß
Chris
Reiner Wolff
2007-05-20 12:02:13 UTC
Permalink
Moin Christian,
Post by c***@web.de
Post by Reiner Wolff
Es gibt da allerdings durchaus Unterschiede. ZB kannst Du auf diese Weise
das Formular auch in mehreren Instanzen darstellen und trotzdem auf die
richtige Instanz zugreifen.
Aus diesem und anderen Erfahrungen, benutze ich - wenn ich dran denke -
dafür eine FormularVariable ;-)
Das durchschaue ich derzeit noch nicht, wel ich noch zu sehr
sequentiell als OO denke.
(PS: kennst Du Richtung OO eine gute Grundlage fürs Selbsstudium?)
Nein, habe ich leider nicht parat.
Und wenn ich mich mal zB in VB.Net-Gruppen traue, habe ich von OO (sieht
aus wie ein WC-Reiniger) auch nicht wirklich viel Ahnung.
Post by c***@web.de
Post by Reiner Wolff
Das Initialize-Ereignis wird nämlich bereits aufgerufen, bei der Zuweisung
der Array-Property. Allerdings direkt bevor das Array zugewiesen wird.
Aha, das wußte ich noch nicht.
Wußte ich vorher auch nicht.
Aber als ich dann im Einzelschritt den TestCode durchging, stellte ich die
Aufrufreihenfolge ziemlich schnell fest ;-)
Post by c***@web.de
Ok. Reiner. So etwas durchzudiskutieren ist doch lehrreich. Da lernt
man Dinge, die sonst nirgendwo stehen oder man sich mühevoll zusammen
suchen muss.
Stümmt.
Aber damit ist das Thema wohl auch abgeschlossen ;-)

Gruß aus Kiel
Reiner
--
Nur, weil der Arzt einen Namen für deinen Zustand
findet, heißt das nicht, daß er weiß, was dir fehlt.
c***@web.de
2007-05-19 20:23:47 UTC
Permalink
Hallo Reiner,

Danke für Deine Hilfe. Dein Code hat funktioniert und mich
erleuchtet ;-). Aber ich möchte noch ein paar Sachen dazutun bzw.
ändern.

Alsoooo

Sub test()
' mein Umbau nach dem ersten Test ergab,
' dass man diese Zeilen nicht benötigt:
' Dim frm As New UserForm1
' Dim arTest() As String

'ReDim ist hier wohl der wichtigste Gimmik - Richtig!!!
ReDim arTest(0) As String ' Mein Trick zu _
erkennen ob ein Fehler _
auftrat oder nicht
Dim i as byte
for i=1 to 4
arTest(0) = i
' Jetzt wird das Feld um 1 Feld vergrößert
' Behaltet dabei den ersten Wert
ReDim Preserve arTest(ubound(aetest)+1))
next i
UserForm1.arFehlerTexte = arTest
' frm.Ini --> warum nich nötig kommt später
UserForm1.Show
End Sub

'Code im UserForm1
' das m_ ist halt übliche schreibweise :-)
Private m_carFehlerTexte() As String

' in der Deklaration sehe ich meinen Fehler: String anstelle String ()
Public Property Get arFehlerTexte() As String()
arFehlerTexte = m_carFehlerTexte
End Property

Public Property Let arFehlerTexte(ByRef errCollection() As String)
m_carFehlerTexte = errCollection
End Property

' Und jetzt kommt der dicke Hund!!!!!
private sub UserForm_Activate()
<Listboxfüllen mit Schleife>
end sub

UserForm_Initialize() funktioniert nämlich nicht !!!! Dann meckert er
eine For-Schleife an!!

Ok Reiner, dann mal viel Merci und Spass

Gruss von Chris aus dem finstersten Teil von Neukölln ;-)
Loading...