Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1484to1488
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

ReDim Preserve eines transponierten 2D Arrays

ReDim Preserve eines transponierten 2D Arrays
12.04.2016 00:22:07
tengal
Moin!
Die Ausgangssituation auf die Schnelle: ein dynamisches Array(n,m) soll in einer Schleife seine Länge, bzw. die Anzahl Zeilen ändern, die Werte müssen aber bebehalten werden.
Ein Fall für ReDim Preserve, da man hier nicht die Zeilen- sondern nur die Spaltenzahl ändern kann (nur zweite Dimension) habe ich das Array vorher transponiert. Doch obwohl ich die 1. Dimension beim ReDim nicht verändere, gibt es den "Index außerhalb des gültigen Bereichs" Fehler.
Ein Bsp:
Dim array() as Variant
ReDim array(20, 4) 'immer zu groß, die wahre Größe weiß man aber erst später
array = Application.WorksheetFunction.Transpose (array)
ReDim Preserve array (LBound(array) To UBound(array), n)
Die letzte Zeile verursacht besagten Fehler und ich verstehe einfach nicht warum, denn die 1. Dimension wird ja nicht verändert. Ich habe auch noch ein bischen im Nebel gestochert und mal ein +1 oder -1 rangehängt, keine Chance. Auch wenn man feste Werte statt LBound und UBound nimmt (in obigem Beispiel: (4, n) ändert sicht nichts.
Wäre sehr froh wenn jmd. von euch sieht worans liegt!

13
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
Das fängt schon mal damit an, dass du ...
12.04.2016 00:45:16
Luc:-?
…ein VBA-Schlüsselwort als VariablenBezeichner verwendest, Tengal;
nicht klug (gibt doch genug andere Möglichkeiten, auch deutsche)! Durch eine derartige Unbedachtheit hat eine Volksschul-Dozentin mal ein Access-Pgm gekillt!
Dann geht's mit n weiter → wie ist das deklariert und welchen Wert hat das?
Übrigens, dein Array ist ursprünglich von 0…20 und 0…4 redeklariert worden. Durch Transpose verschieben sich die Indizes auf 1…5 und 1…21, was du für die neuen Zeilen mit LBound(array) To UBound(array) abfängst, während die alleinige Angabe von n wieder 0 To n bedeuten würde, wenn n denn einen (Long-)Wert hätte…
Gruß, Luc :-?
Besser informiert mit …

Anzeige
AW: Das fängt schon mal damit an, dass du ...
12.04.2016 01:03:43
tengal
Danke für deine Antwort Luc:-?
Der Schnipsel ist nicht der "echte" Code, sondern willkürlich zur Illustration. Tatsächlich heißt die Variable weder "array" noch ist n die wahre Spaltenzahl. Da die Berechnung der neu-dimensionierten Spaltenzahl relativ umfangreich ist und für meine Frage nichts zur Sache tut, hab ichs vereinfacht. Dass von 0 auf eine 1er Basis gewechselt wird ist klar, aber ob ich nun 4 (bei Basis 0) oder 1 To 5 schreibe macht ja keinen Unterschied... Deshalb verstehe ich eben auch nicht warum ein Fehler ausgespuckt wird.
Viele Grüße

Na gut, dann vermute ich mal, dass das ...
12.04.2016 01:49:04
Luc:-?
…an dem 0 To n liegen könnte, Tengal;
viell würde es ja mit 1 To n klappen. Aber bevor wir hier weiter rätselraten und testen, schlage ich dir lieber eine andere Methode vor, bei der das bestimmt fktioniert:
Was hältst du davon, für jede Zeile einen einzelnen horizontalen Vektor(4) anzulegen bzw einen ZellBereich zeilenweise derart in einen HptVektor(20) aufzunehmen. Dann erhältst du einen 1dimensionalen senkrechten (Haupt-)Vektor über die Zeilen, dessen Elemente 1dimensionale waagerechte Vektoren über die Spalten der jeweiligen Zeile sind. Sind das immer genausoviele Spalten, die Matrix also rechteckig, ist so etwas prinzipiell auf ZellBereiche abbildbar, muss in einer SubProzedur oder Fkt einer solchen nur noch 2× transponiert wdn. In einer in einer ZellFml eingesetzten Fkt (UDF) kann das sogar entfallen, weil Xl das selber macht.
Der Vorteil des Ganzen ist, dass jeder dieser Vektoren einzeln ReDimmt wdn kann, also auch der HptVektor über die Zeilen. Ist das Füllen seiner Elemente beendet, kann er auf den Stand einer Lauf- bzw ZählVariablen ReDimmt wdn (ggf -1). Ein weiterer Vorteil ist, dass so jede Zeile auch weiterhin einzeln angesprochen wdn kann, zB mit myArray(i), der Einzelwert eines ZeilenVektors dann mit myArray(i)(j). Außerdem kann man auch noch eine Kopie erzeugen, bei der der HptVektor den Spalten folgt, denen dann die ZeilenWerte der jeweiligen Spalte zugeordnet wdn. Dadurch könnte man dann auch eine einzelne Spalte ansprechen.
Durch ein (abschließendes) Transponieren entsteht wieder ein normales 2dimensionales Datenfeld (VBA-Array) mit allen seinen Beschränkungen.
Dazu haben Andere und auch ich schon einiges in verschiedenen XlForen geschrieben, auch hier erst kürzlich wieder (Betreff: Array-Typen).
Luc :-?

Anzeige
AW: Na gut, dann vermute ich mal, dass das ...
12.04.2016 10:57:38
tengal
@ Luc:-? : Ein Jagged Array könnte eine Möglichkeit sein, werde ich nachher mal testen. Gelöst bekomme ich das Problem auch so. Da die es sich im relativ kurze Arrays handelt (30-100 Zeilen) kann ich das Ausgangsarray auch einmal durchlaufen, zählen wie viele Zeilen ich brauche, das andere Array neudimensionieren (ohne Preserve) und dann nochmal durchlaufen und befüllen. Finde ich halt nur etwas weniger elegant, zumal mich auch grundsätzlich (Stichwort Weiterbildung) interessiert, warum es wie im Ausgangspost beschrieben nicht funktioniert.
Aber, um es nochmal konkreter zu machen (auch @Daniel, danke für die Antwort):
Ich habe ArrayEins(39,4)
Dim ArrayZwei() As Variant
RedDim ArrayZwei(39, 4) 'da es im schlimmsten Fall sein kann dass ArrayZwei = ArrayEins
'ich brauche nur 11 Zeilen bei weiterhin 5 Spalten
ArrayZwei = Application.WorksheetFunction.Transpose(ArrayZwei)
'jetzt habe ich: ArrayZwei(5, 40) 'OptionBase = 1 statt 0
ReDim Preserve ArrayZwei(5, 11)
Die letze Zeile gibt den Fehler.
Daniel, ich habe ehrlichgesagt nicht ganz verstanden was du meinst mit "wenn der Ubound-Wert n kleiner ist als der LBound-Wert" meinst. Ich vermute mal du meinst es umgekehrt (denn wenn UBound kleiner LBound wäre es ja negativ). Aber LBound muss n kleiner sein als UBound, sonst würde man die 1. Dimension ja verändern, was logischerweise den Fehler auslöst.
In obigem Fall wäre ja UBound - LBound = 4 = n
Viele Grüße

Anzeige
AW: Na gut, dann vermute ich mal, dass das ...
12.04.2016 11:41:55
Daniel
Hi
du kannst mit Redim-Preserve immer nur die letzte Dimension verändern.
die Anzahl der Elemente in der ersten (und weiteren) Dimension muss unverändert bleiben.
gegen diesen Grundsatz verstösst du.
wenn du mit Option-Base 1 arbeitest ist es so:
Redim ArrayZwei(39, 4) ergibt die Arraygrenzen 1 to 39, 1 to 4
das Transponieren ergibt die Arraygrenzen 1 to 4, 1 to 39
dein Redim Preseve ArrayZwei(5, 11) ergibt die Arraygrenzen 1 to 5, 1 to 11
und damit eine unzulässige Veränderung der ersten Dimension.
wenn du ohne Option-Base 1 arbeitest ist es so:
Redim ArrayZwei(39, 4) ergibt die Arraygrenzen 0 to 39, 0 to 4
das Transponieren ergibt die Arraygrenzen 1 to 5, 1 to 40
dein Redim Preseve ArrayZwei(5, 11) ergibt die Arraygrenzen 0 to 5, 0 to 11
und damit eine unzulässige Veränderung der ersten Dimension, diesmal jedoch an der Untergrenze (was aber genauso unzulässig ist)
wenn du sicher gehen willst, dann das Redim Preserve immer so:
ReDim Preserve ArrayZwei(LBound(ArrayZwei, 1) To UBound(ArrayZwei, 1), LBound(ArrayZwei, 2) To WorksheetFunction.Max(LBound(ArrayZwei, 2), n))
Gruß Daniel

Anzeige
AW: ReDim Preserve eines transponierten 2D Arrays
12.04.2016 10:01:16
Daniel
Hi
welchen Wert hat n wenn der Fehler auftritt?
die ReDim-Funktion erzeugt diesen Fehler, wenn der Ubound-Wert n kleiner ist als der LBound-Wert (wenn Lbound nicht angegeben, dann LBound =0 bzw =1 bei Option Base 1)
Gruß Daniel

AW: ReDim Preserve eines transponierten 2D Arrays
12.04.2016 11:01:09
tengal
Sorry, habe versehentlich nicht auf den aktuellsten Beitrag geantwortet.
Sorry auch wg. Doppelpost, man kann ja nachträglich nicht mehr editieren...

AW: ReDim Preserve eines transponierten 2D Arrays
12.04.2016 12:12:48
tengal
Vorweg: Danke, deine sichere Methode funktioniert. "ReDim Preserve ArrayZwei(LBound(ArrayZwei, 1) To UBound(ArrayZwei, 1), LBound(ArrayZwei, 2) To WorksheetFunction.Max(LBound(ArrayZwei, 2), n))
"
Jetzt aber nochmal zum Verständnis: Bei mir liefert dein sicherer Ausdruck zurück:
ReDim Preserve ArrayZwei(1 To 5, 1 To 11)
Ergo sollte man mit Preserve ArrayZwei(4,11) ja aufs Gleiche kommen (arbeite mit Base 0). Aber egal welchen wert ich einsetze - aus Spaß habe ich mal alles von 2-8 durchprobiert, immer gibts den Fehler.
Es funktioniert tatsächlich nur, wenn man 1 To 5 schreibt (egal ob als Zahl oder mit Variablen wie L/UBound). Wenn ich nur "4" schreiben gehts nicht - obwohl es bei Base 0 ja das gleiche wie 1 To 5 wäre.
Wenns dafür eine Erklärung gibt bin ich vollends zufrieden :)
Viele Grüße

Anzeige
AW: ReDim Preserve eines transponierten 2D Arrays
12.04.2016 13:26:02
Daniel
Hi
1. zum dimensionieren eines Arrays brauchst du immer einen oberen und einen unteren Grenzwert (Ubound und LBound):
Redim X(untere_Grenzwert TO oberer_Grenzwert)
Da VBA eine komfortable Probrammiersprache sein will, erlaubt es dir den unteren Grenzwert wegzulassen und setzt dann automatisch als unteren Grenzwert die 0 ein bzw die 1, wenn du Option Base 1 verwendest.
2. die Funktion Worksheetfunction.Transpose restrukturiert die Grenzwerte und setzt als unteren Grenzwert immer die 1 und berechnet dann den oberen Grenzwert entsprechend der Anzahl der Elemente.
Bedenke, dass Worksheetfunction.Transpose eigentlich eine Funktion ist, die auf einem Tabellenblatt mit Excelzellen eingesetzt wird und da ist es halt so üblich, dass die Linke Obere Zelle immer den Index (1, 1) hat.
Wenn du unter Beibehaltung der originalen Grenzwerte transponieren willst, musst du das selber programmieren:

Option Explicit
Sub test()
Dim X, Y, Z
ReDim X(39, 4)
Y = WorksheetFunction.Transpose(X)
Z = myTranspose(X)
Debug.Print "X:", LBound(X, 1); "|"; UBound(X, 1), LBound(X, 2); "|"; UBound(X, 2)
Debug.Print "Y:", LBound(Y, 1); "|"; UBound(Y, 1), LBound(Y, 2); "|"; UBound(Y, 2)
Debug.Print "Z:", LBound(Z, 1); "|"; UBound(Z, 1), LBound(Z, 2); "|"; UBound(Z, 2)
End Sub
Function myTranspose(ARR As Variant) As Variant
Dim X As Long, Y As Long
Dim Erg As Variant
ReDim Erg(LBound(ARR, 2) To UBound(ARR, 2), LBound(ARR, 1) To UBound(ARR, 1))
For X = LBound(ARR, 1) To UBound(ARR, 1)
For Y = LBound(ARR, 2) To UBound(ARR, 2)
Erg(Y, X) = ARR(X, Y)
Next
Next
myTranspose = Erg
End Function
das ist sowieso besser als Worksheetfunction.Transpose, weil Worksheetfunction.Transpose nur eine limitierte Anzahl von Elementen verarbeiten kann und deutlich langsamer ist als die selbstgeschriebene Funktion (wie gesagt, Worsheetfunction.Transpose verarbeitet normalerweise Excelzellen und eine VBA-Arrays)
Gruß Daniel

Anzeige
MTRANS (wf.Transpose) verarbeitet xl-basierte ...
12.04.2016 15:19:56
Luc:-?
…ZellBereiche und Datenfelder, Daniel,
wobei die Betonung auf xl-basiert liegt, was den unteren GrenzIndex 1 zur Folge hat.
Option Base kann in VBA eingestellt sein wie es will, xl-basierte Prozesse, also auch WorksheetFunctions, wdn dadurch nicht beein­flusst.
Und, Tengal,
ein UBound kann durchaus mal < als ein LBound sein, dann ist das aber entweder ein Fehler oder im Falle von standardmäßig 0-ba­sierten ParamArrays einem leeren Array geschuldet → konkret dann: LBound(myParamArray) = 0 und UBound(myParamArray) = -1
Gruß, Luc :-?

Anzeige
AW: MTRANS (wf.Transpose) verarbeitet xl-basierte ...
12.04.2016 15:50:49
Daniel
Hi Luc
schön, dass du nochmal wiederholst, was ich bereits geschrieben habe.
Gruß Daniel

Du hattest nur ZELLBEREICHE im Zusammenhang ...
13.04.2016 13:27:57
Luc:-?
…mit MTRANS erwähnt, Daniel,
deshalb mein BT!
Neulich hattest du um den umgekehrten Fall eine längere sinnfreie Diskussion angezettelt und zuvor ebenfalls nur eine von 2 von mir dargestellten regulären Varianten des Langen und Breiten erklärt. Und das war dann auch noch die ungünstigere, weil fehleranfälligere… :->
Kannste ma sehn wie det iss…! ;-]
Luc :-?

AW: Du hattest nur ZELLBEREICHE im Zusammenhang ...
15.04.2016 14:38:06
Daniel
ist gut Luc, wenns dich glücklich macht ;-)

51 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige