Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Variant mit Arrays füllen

341 views
Skip to first unread message

Eberhard Funke

unread,
Jul 19, 2004, 6:17:41 AM7/19/04
to
Hallo

mit:

Dim a As Variant
a = Range("A1:B5")

wird der Bereich A1:B5 in - wenn ich das richtig verstehe: EINER -
Variablen abgelegt.
Im Überwachungsfenster wird als Typ
Variant/Variant(1 to 5, 1 to 2) angezeigt.
Der Wert von z. B. B3 läßt sich mit ?a(3,2) auslesen.

Jetzt möchte ich die einzelnen Elemente (nennt man das so?) der
Variant Variablen aber nicht wie oben zuweisen, sondern z. B mit einer
Schleife einzeln einlesen, im Prinzip etwa so:

Dim a As Variant
a(i,k) = 4711 'mit z. B. i=3, k=2

D. h. der ganze Datenpacken soll wieder, wie oben, in EINER Variant
Variablen abgelegt werden.
Wie muß der Code aussehen (wenn das überhaupt geht)?

Zur Vermeidung von Mißverständnissen: ich meine nicht so etwas wie
Dim a(1 To 5, 1 To 2) As Variant
a(i, k) = 4711 'mit i=3 und k=2


--
Gruß Eberhard
XL 2000

Melanie Breden

unread,
Jul 19, 2004, 6:59:28 AM7/19/04
to
Hallo Eberhard,

Eberhard Funke schrieb:


> Jetzt möchte ich die einzelnen Elemente (nennt man das so?) der
> Variant Variablen aber nicht wie oben zuweisen, sondern z. B mit einer
> Schleife einzeln einlesen, im Prinzip etwa so:
>
> Dim a As Variant
> a(i,k) = 4711 'mit z. B. i=3, k=2
>
> D. h. der ganze Datenpacken soll wieder, wie oben, in EINER Variant
> Variablen abgelegt werden.
> Wie muß der Code aussehen (wenn das überhaupt geht)?
>
> Zur Vermeidung von Mißverständnissen: ich meine nicht so etwas wie
> Dim a(1 To 5, 1 To 2) As Variant
> a(i, k) = 4711 'mit i=3 und k=2

ich bin mir nicht sicher, ob ich dich richtig verstanden habe, aber ich versuchs mal :-)
In folgender Prozedur wird der Bereich A1:B5 über zwei Schleifen in ein Datenfeld gespeichert:

Sub Datenfeld()


Dim a(1 To 5, 1 To 2) As Variant

Dim i As Long
Dim k As Long

' Zeilen
For i = 1 To 5
'Spalten
For k = 1 To 2
a(i, k) = Cells(i, k).Value
Next k
Next i

Range("F1:G5") = a()
End Sub

--
Mit freundlichen Grüssen

Melanie Breden
- Microsoft MVP für Excel -

http://excel.codebooks.de (Das Excel-VBA Codebook)
#Excel-Auftragsprogrammierung#


Eberhard Funke

unread,
Jul 19, 2004, 2:58:50 PM7/19/04
to
Hallo Melanie

"Melanie Breden" <Melanie....@SPAMmvps.org> schrieb:

> Range("F1:G5") = a() '<----- geht auch ohne ()
>End Sub

Das ist die Datenfeld-Lösung, die ich nicht wollte [s. "Zur Vermeidung
von Mißverständnissen:..."] :-((

Ich habe irgendwo etwas von einer "Variant" Variablen gelesen. Das
soll etwas anderes sein als die Typzuweisung Dim x As Variant ???
Vielleicht können die Beispiele alles besser erklären als Worte.

Sub Variant_Array()
Dim b As Variant 'b ohne (....), vergl. Dein Code
Dim x As Integer
b = Range("A1:B5") 'B3 = 7
x = b(3, 2)
Debug.Print x '---> 7
End Sub

Ich möchte nun so, wie ich vorstehend mit
x = b(3, 2),
den Wert eines einzelnen Elementes auslesen kann, auch umgekehrt einen
Wert in b eingeben (bzw. >>b<< schrittweise mit einer Schleife
füllen):

Sub Variant_Array()
Dim b As Variant
b(3,2) = 4711
.....usw.....
End Sub

führt aber zu einem Laufzeitfehler: Typen unverträglich.

Andererseits:

Sub Variant_Array()
Dim b As Variant
b = Range("A1:B5") 'B3 = 7
Debug.Print b(3, 2) '--> 7
b(3, 2) = 4711
Debug.Print b(3,2) '---> 4711

hier funktioniert die Zuweisung b(3, 2) = 4711.
Man könnte also annehmen, daß durch
b = Range("A1:B5")
Deine Dim Anweisung:


Dim a(1 To 5, 1 To 2)

quasi "nachgeholt" wird und daß das >>b<< aus meinem Code identisch
sei mit Deinem Datenfeld >>a<<.

Aber:

Sub Variant_Array()
Dim b As Variant
Dim x As Integer
b = Range("A1:B5")
Range("F1:G5") = b '<--- = b() ergibt Fehler
End Sub

funktioniert, ergibt aber den Fehler "Index außerhalb des gültigen
Bereichs", wenn die vorletzte Zeile
Range("F1:G5") = b()
lautet.

Dein Code läuft dagegen mit und auch ohne das Klammerpaar in der
entsprechenden Zeile (oben mit Pfeil gekennzeichnet).

Also sind >>a<< und >>b<< doch nicht identisch.
'>>a<< ist ein Datenfeld, aber was ist >>b<< ?

Ich hoffe, Du kannst trotz der vielleicht umständlichen Darlegung mein
Verständnisproblem erkennen.

Melanie Breden

unread,
Jul 19, 2004, 5:18:39 PM7/19/04
to
Hallo Eberhard Funke,

Eberhard Funke schrieb:

> Das ist die Datenfeld-Lösung, die ich nicht wollte [s. "Zur Vermeidung
> von Mißverständnissen:..."] :-((

ein Versuch wars wert ;-)

> Ich habe irgendwo etwas von einer "Variant" Variablen gelesen. Das
> soll etwas anderes sein als die Typzuweisung Dim x As Variant ???
> Vielleicht können die Beispiele alles besser erklären als Worte.
>
> Sub Variant_Array()
> Dim b As Variant 'b ohne (....), vergl. Dein Code
> Dim x As Integer

hier wird der Variablen ein komplettes Datenfeld zugewiesen.

> b = Range("A1:B5") 'B3 = 7
> x = b(3, 2)
> Debug.Print x '---> 7
> End Sub
>
> Ich möchte nun so, wie ich vorstehend mit
> x = b(3, 2),
> den Wert eines einzelnen Elementes auslesen kann, auch umgekehrt einen
> Wert in b eingeben (bzw. >>b<< schrittweise mit einer Schleife
> füllen):
>
> Sub Variant_Array()
> Dim b As Variant
> b(3,2) = 4711
> .....usw.....
> End Sub

> führt aber zu einem Laufzeitfehler: Typen unverträglich.

b weiss ja noch gar nicht, dass es ein Datenfeld ist!
Um Werte einem Datenfeld hinzuzufügen, muss es vorher dimensioniert werden.
Durch das leere Klammerpaar nach der Dimensionierung wird die Variable
als dynamisches Datemnfeld gekennzeichnet und kann später im Code mit Redim
in seiner Größe verändert werden.

Sub Variant_Array1()
Dim b() As Variant
ReDim b(3, 2)
b(3, 2) = 4711
End Sub

> Andererseits:
>
> Sub Variant_Array()
> Dim b As Variant

Durch die Range-Zuweisung an die Variable weiss b, dass es ein Datenfeld
mit einer bestimmen Größe ist und kann Werte innerhalb seiner Dimensionierung
aufnehmen.

> b = Range("A1:B5") 'B3 = 7
> Debug.Print b(3, 2) '--> 7
> b(3, 2) = 4711
> Debug.Print b(3,2) '---> 4711
>
> hier funktioniert die Zuweisung b(3, 2) = 4711.
> Man könnte also annehmen, daß durch
> b = Range("A1:B5")
> Deine Dim Anweisung:
> Dim a(1 To 5, 1 To 2)
> quasi "nachgeholt" wird und daß das >>b<< aus meinem Code identisch
> sei mit Deinem Datenfeld >>a<<.

ja, das sehe ich auch so, dass die Dimensioierung nachgeholt wird.
Allerdings nicht identisch mit a(), weil a() dynamisch ist und b nicht.

> Aber:
>
> Sub Variant_Array()
> Dim b As Variant
> Dim x As Integer
> b = Range("A1:B5")
> Range("F1:G5") = b '<--- = b() ergibt Fehler
> End Sub
>
> funktioniert, ergibt aber den Fehler "Index außerhalb des gültigen
> Bereichs", wenn die vorletzte Zeile
> Range("F1:G5") = b()
> lautet.

Hier darf kein Klammerpaar bei der Ausgabe angegeben werden,
weil die Variable ohne Klammerpaar - also nicht dynamisch- deklariert wurde.

> Dein Code läuft dagegen mit und auch ohne das Klammerpaar in der
> entsprechenden Zeile (oben mit Pfeil gekennzeichnet).
>
> Also sind >>a<< und >>b<< doch nicht identisch.
> '>>a<< ist ein Datenfeld, aber was ist >>b<< ?

Es sind beides Datenfelder.
Schau dir mal diesen Code im Lokalfenster an und achte auf die Datentypen:

Sub Datenfelder()
Dim a() As Variant
Dim b As Variant


Dim i As Long
Dim k As Long

ReDim a(1 To 5, 1 To 2)


' Zeilen
For i = 1 To 5
'Spalten
For k = 1 To 2
a(i, k) = Cells(i, k).Value
Next k
Next i

b = Range("A1:B5")

Debug.Print a(2, 1)
Debug.Print b(2, 1)

Range("D1:E5") = a


Range("F1:G5") = b

End Sub

a ist von Anfang an vom Typ Variant und erhält im Codeverlauf seine genaue Dimensionierung.
b ist anfänglichVariant/Empty, erhält aber nach Zuweisung der Range Matrix den Untertyp Variant,
weil die Variable als Datenfeld verwendet wird.

> Ich hoffe, Du kannst trotz der vielleicht umständlichen Darlegung mein
> Verständnisproblem erkennen.

Ja, konnte ich erkennen und hoffe, dass es jetzt etwas lichter geworden ist ;-)

Michael Zimmermann

unread,
Jul 19, 2004, 6:00:51 PM7/19/04
to
Hallo!

Eberhard Funke:


> > > Jetzt möchte ich die einzelnen Elemente (nennt man
> > > das so?) der Variant Variablen aber nicht wie oben
> > > zuweisen, sondern z. B mit einer Schleife einzeln
> > > einlesen, im Prinzip etwa so:

Warum? Sei doch froh, daß es in einem Schritt geht. Diese
Variante ist bedeutend schneller und liefert dasselbe
Ergebnis wie schrittweises Befüllen.

Zum Verständnis:

Dim v as Variant

v ist *kein* Array. Wenn Du v aber "gewaltsam" ein Array
zuweist, wird es intern automatisch dazu konvertiert.

Dim v As Variant
Dim b() As Long 'Long-Array

Debug.Print IsArray(v) '>> False
v = b()
'oder v = b
Debug.Print IsArray(v) '>> True

Andere Array-Zuweisungen:

v = Array(1,2,3)
v = DeinRange.Value

Die Deklaration

Dim v() as Variant

macht etwas anderes. Die Variable v() ist jetzt *sofort*
ein Array, aber halt eines, dessen *Elemente* verschiedenen
Datentyps sein können (eben Variant).

Ein Variant Array kann zwar Long-Elemente aufnehmen, aber
nicht mehr als Ganzes Long-Array spielen:

Nach
Dim v() as Variant
Dim b() As Long
gibt
v() = b()
einen Kompilierfehler: "Keine Zuweisung an Datenfeld
möglich."

> Ich habe irgendwo etwas von einer "Variant" Variablen
> gelesen. Das soll etwas anderes sein als die Typzuweisung
> Dim x As Variant ??? Vielleicht können die Beispiele
> alles besser erklären als Worte.
>
> Sub Variant_Array()
> Dim b As Variant 'b ohne (....), vergl. Dein Code
> Dim x As Integer
> b = Range("A1:B5") 'B3 = 7
> x = b(3, 2)
> Debug.Print x '---> 7
> End Sub
>
> Ich möchte nun so, wie ich vorstehend mit
> x = b(3, 2),
> den Wert eines einzelnen Elementes auslesen kann, auch
> umgekehrt einen Wert in b eingeben (bzw. >>b<<
> schrittweise mit einer Schleife füllen):

Falls das wirklich sein muß - siehe meine obige Anmerkung -,
dann:

Dim v() as Variant 'oder String, Long, wenn Du weißt, was
'Dich für Zellwerte erwarten
Dim n As Long, m as Long, i as long, j as Long

n = Range("A1:B5").Rows.Count '5 (1 bis 5)
m = Range("A1:B5").Columns.Count '2 (A -B)

Redim v(1 To m, 1 To n)

For i = 1 To m '2
For j = 1 To n '5
v(i,j) = Range("A1:B5").Cells(j,i)
'Bei Cells stehen Spalten hinten!
Next j
Next i

Unterscheide hierbei statisches Datenfeld
Dim a(1 To 3) as Long
von dynamischem Datenfeld
Dim a() as Long

Letzteres muß über eine Methode, die selbst Datenfelder
liefert = Range(...).Value; = Array(...) usw. befüllt
werden.

Ein elementweises Befüllen eines dynamischen Arrays
ist *ausschließlich* nach einer ReDim-Anweisung möglich.

> Sub Variant_Array()
> Dim b As Variant
> b(3,2) = 4711
> .....usw.....
> End Sub
>
> führt aber zu einem Laufzeitfehler: Typen unverträglich.

Klar, b ist ja kein Array.

> Andererseits:
>
> Sub Variant_Array()
> Dim b As Variant
> b = Range("A1:B5") 'B3 = 7
> Debug.Print b(3, 2) '--> 7
> b(3, 2) = 4711
> Debug.Print b(3,2) '---> 4711
>
> hier funktioniert die Zuweisung b(3, 2) = 4711.
> Man könnte also annehmen, daß durch
> b = Range("A1:B5")
> Deine Dim Anweisung:
> Dim a(1 To 5, 1 To 2)
> quasi "nachgeholt" wird

Gut erkannt. Das *ist* so und nennt sich implizite
Konversion. ;-)

> Aber:
>
> Sub Variant_Array()
> Dim b As Variant
> Dim x As Integer
> b = Range("A1:B5")
> Range("F1:G5") = b '<--- = b() ergibt Fehler
> End Sub
>
> funktioniert, ergibt aber den Fehler "Index außerhalb des
> gültigen Bereichs", wenn die vorletzte Zeile
> Range("F1:G5") = b()
> lautet.

Logisch. b ist nach der Range-Zuweisung zwar Behälter
eines Arrays, aber nicht selbst als Array deklariert.
Deswegen kannst Du nicht plötzlich b() benutzen, wenn
Du b deklariert hast.

Eine weitere Verständnisfalle lauert noch:
Excel.Ranges sind *immer* zweidimensional, auch wenn die
zweite Dimension nur die Ausdehnung 1 hat.

Unterscheide:

Dim x(1 To 3, 0) 'oder x(1 To 3, 1 To 1)
Dim y (1 To 3)

y() ist ein eindimensionales Array (Vektor) mit 3
Komponenten, x() ist eine zweidimensionales Array
(Matrix) mit 3 x 1 Komponenten.

Das ist zwar inhaltlich dasselbe, aber formal verschieden
und gibt beim gegenseitigen Zuweisen einen Fehler.

Wenn Du mit einspaltigen Ranges "A1:A5" arbeitest, könntest
Du auf die Idee kommen, den Array-Typ y (Vektor) zu
benutzen. Auch bei nur einer Spalte ist das Array aber
vom Typ x (Matrix).

Hoffe, der Array-Dschungel hat sich etwas gelichtet. ;-)

Gruß aus Mainz
Michael

Eberhard Funke

unread,
Jul 20, 2004, 6:22:08 AM7/20/04
to
Hallo Melanie,

"Melanie Breden" <Melanie....@SPAMmvps.org> schrieb:

Dass an diesem ansonsten trüb regnerischen Tag so ein lichter
Sonneschein meine Bude aufhellt... !

Danke, dass Du Dir die Mühe gemacht hast, meinen gedanklichen
Schlingerkurs erfolgreich nachzuvollziehen.

Ich werde mir Deinen Post hinter den Spiegel stecken.

Eberhard Funke

unread,
Jul 20, 2004, 6:22:08 AM7/20/04
to
Hallo Michael,

"Michael Zimmermann" <Zimme...@SZWeb.de> schrieb:

auch Dir herzlichen Dank. Ich könnte hier nur wiederholen, was ich
schon an Melanie geantwortet habe.
Auch Dein Post kommt hinter den Spiegel.

0 new messages