VB /Excel VBA: Array vergrößern

Hallo Reinhard,

möglicherweise ist ja der Lösungsansatz nicht optimal…
wenn Du mal sagst, wie groß die Werte werden können und
die Indexe, findet vielleicht jemand eine elegantere Lösung.

LG ALex

Hallo an alle.

Wenn es um die nicht bekannte Länge eines Strings geht, in Variablen kann man doch die Stringlänge festlegen mit

 Dim Variable As String \* 40

Geht denn daß nicht auch in Arrays? Irgendwie müssen die Daten ja dort rein.

Viele Grüße
Carsten

Hallo Carsten,

Wenn es um die nicht bekannte Länge eines Strings geht, in
Variablen kann man doch die Stringlänge festlegen
mit

Dim Variable As String * 40

ja ich weiß. Ich habe es mal so versucht:

Private Declare Sub CopyMemory Lib "kernel32" Alias \_
 "RtlMoveMemory" (pDst As Any, pSrc As Any, \_
 ByVal ByteLen As Long)

Private Sub Command1\_Click()
 Dim Arr(20) As String \* 1
 Dim i As Integer
 For i = 0 To 20
 Arr(i) = Chr(i + 65)
 Next
 CopyMemory Arr(5), Arr(10), 8&
 For i = 0 To 20
 List1.AddItem Arr(i)
 Next
End Sub

das stürzt auch nicht ab, aber es wird nur ein Zeichen kopiert.

Geht denn daß nicht auch in Arrays? Irgendwie müssen die Daten
ja dort rein.

Ja, aber ich finde nicht heraus, wie genau die verwaltet werden und finde bei AVB, PlanetSourceCode oder sonst mit Google auch keine Hinweise. Das würde mich schon mal interessieren, aber ich bin wohl zu dumm zum Suchen.

Ein Zeiger lässt sich ja kopieren und ich hätte erwartet, daß die Zeiger hintereinander stehen. Unklar ist allerdings, wie viele Bytes so ein Zeiger hat. Ich habe auch schon mal ein paar Bytes mehr kopiert, keie Veränderung, noch nicht mal ein Absturz.

Hast Du eine Idee, wie man dem auf die Spur kommen könnte?

Gruß Rainer

Hallo Rainer.

Nicht wirklich eine Idee, dafür habe ich von Zeigern und API und all dem ganzen Kram leider zu wenig Ahnung.

Aber ich habe natürlich meine naiven Vorstellungen dazu und die sehen in etwa so aus:

Ich versuch ja schon lange selbst eine Software zu schreiben. In dieser Anwendung speichere ich als Variant deklarierte Arrays „auf Schlag“ mit „Open“ und „Put“ und „Close“ in Binär-Dateien mit der Erweiterung „.dat“.

Wenn ich mit jetzt überlege, daß ich ein Array, ganz gleich, wie groß es auch immer sein mag, sowieso Eintrag für Eintrag in einer Schleife nach irgendeinem Wert durchsuchen muß, dann halte ich persönlich es für sinnvoll, schon während des Durchsuchens innerhalb dieser Schleife einfach eine Kopie „mitzuschreiben“ und an der Fundstelle des Wertes dann neue Einträge (oder Zeilen, oder Datensätze) einzufügen.

Dann könnte man doch bestimmt auch in eine mit „For Random“ geöffnete Datei diese neuen Datensätze bereits während des Durchsuchens reinschreiben.

Ich finde diese Vorstellung eigentlich nicht mal naiv, denn das Array muß doch sowieso irgerndwo gespeichert werden.

Viele Grüße
Carsten

P.S. Ich gehe jetzt erstmal zum Frühstücken, hab’ nämlich Urlaub und bin durchaus entspannt.

Hallo Carstan,

Nicht wirklich eine Idee, dafür habe ich von Zeigern und API
und all dem ganzen Kram leider zu wenig Ahnung.

geht mir ähnlich. :smile: Wenn es nicht um Arrays aus Strings geht, dann ist mir das inzwischen klar, aber bei Strings eben gar nicht.

Aber ich habe natürlich meine naiven Vorstellungen dazu und
die sehen in etwa so aus:

Ich versuch ja schon lange selbst eine Software zu schreiben.
In dieser Anwendung speichere ich als Variant deklarierte
Arrays „auf Schlag“ mit „Open“ und „Put“ und „Close“ in
Binär-Dateien mit der Erweiterung „.dat“.

Hmmm, klar kann man das Array schnell auf die Platte schreiben, da bleibt aber immer noch der Festplattenzugriff und der ist sehr viel langsamer als ein Speicherzugriff.

Wenn ich mit jetzt überlege, daß ich ein Array, ganz gleich,
wie groß es auch immer sein mag, sowieso Eintrag für Eintrag
in einer Schleife nach irgendeinem Wert durchsuchen muß, dann
halte ich persönlich es für sinnvoll, schon während des
Durchsuchens innerhalb dieser Schleife einfach eine Kopie
„mitzuschreiben“ und an der Fundstelle des Wertes dann neue
Einträge (oder Zeilen, oder Datensätze) einzufügen.

Warum Reinhard Bereiche des Arrays kopieren möchte habe ich noch nicht verstanden, das ist halt Excel, da komme ich nicht mit. Ich kann mich nur auf den Umgang mit den Arrays beschränken.

Dann könnte man doch bestimmt auch in eine mit „For Random“
geöffnete Datei diese neuen Datensätze bereits während des
Durchsuchens reinschreiben.

Du willst die Datei ‚For Random‘ öffnen und dann gezielt auf einen Datensatz zugreifen? Das macht Ärger, die Datensatznummer ist Integer. :frowning: Da stößt man viel zu schnell an Grenzen, das stammt noch aus Zeiten, wo eine 500MB-Festplatte riesig war und sich die Entwickler Datenmengen mit mehreren Tausend Datensätzen nicht vorstellen konnten.

Ich finde diese Vorstellung eigentlich nicht mal naiv, denn
das Array muß doch sowieso irgerndwo gespeichert werden.

Das Array bleibt erst mal im Speicher, Reinhard möchte es ja an ein Listen-Steuerelement übergeben. Ob das dann so fesichert wird, oder ob das nur eine Anzeige ist, weiß ich nicht.

P.S. Ich gehe jetzt erstmal zum Frühstücken, hab’ nämlich
Urlaub und bin durchaus entspannt.

Na dann erhol Dich gut und genieße den Urlaub!

Gruß Rainer

Hallo Rainer.

Warum Reinhard Bereiche des Arrays kopieren möchte habe ich
noch nicht verstanden

Ich nämlich auch nicht.
Und: Befinden sich diese Listboxen auf einem UserForm oder auf dem Tabellenblatt? Keiner weiß es.
Eine Vermutung meinerseits ist auch, daß Reinhard möglicherweise so etwas in der Art wie einen „Katalog“ (ganz allgemein gesagt) in der Aufmachung eines Eigenschaften-Fensters aufbauen möchte, in die ein Benutzer irgendwelche Informationen einfügen kann. Daher auch meine erste Idee mit der „AddItem“-Methode.

Du willst die Datei ‚For Random‘ öffnen und dann gezielt auf
einen Datensatz zugreifen? Das macht Ärger, die
Datensatznummer ist Integer. :frowning: Da stößt man viel zu schnell
an Grenzen, das stammt noch aus Zeiten, wo eine
500MB-Festplatte riesig war und sich die Entwickler
Datenmengen mit mehreren Tausend Datensätzen nicht vorstellen
konnten.

Oh.

Na dann erhol Dich gut und genieße den Urlaub!

Danke, das werd’ ich versuchen

Viele Grüße
Carsten

Hallo Rainer,

Warum Reinhard Bereiche des Arrays kopieren möchte habe ich
noch nicht verstanden, das ist halt Excel, da komme ich nicht
mit.

nein, das hat mit Excel nix zu tun. Ich habe ein gefülltes Array a(5) das so im Speicher abgelegt ist (die Zahlen sind die Werte in dem Array):

1
2
3
4
5
6

Nun möchte ich es „vergrößern“ um einen Eintrag, damit es nachher so aussieht im Speicher:

1
2
3
Neuer Eintrag
4
5
6

Dazu kann ich mir ein neues leeres array b(6) anlegen, dann gehe ich das Array a einzeln durch und schaufle die ersten 3 Einträge in die drei ersten Einträge von b, dann schreibe ich den 4ten Eintrag in b hinein,dann schaufle ich die letzten 3 Einträge von a in die 3 letzten Einträge von b.

Das geht, kriegen wir alle hin.

Nun möchte ich aber auf einen Rutsch die ersten 3 Einträge in die 3 ersten Einträge von b kopieren und auch die 3 letzten Einträge von a in die 3 letzten Einträge von b kopieren. Darum geht es mir.

Trotz der Hilfe von Alex und Euch kriege ich das aber nichtmal mit einem eindimensionalen Array hin.

Die Codes von Alex habe ich stundenlang getestet in VB5.0 , ich glaube ich habe alle Varianten durchgespielt wo man strptr(), Byval, byref sowohl in den Aufrufen als auch in der API-Deklaration benutzen kann.

Ich glaube eine Lösung kann ich mir abschminken:frowning:
Denn erschwerdend kommt dazu, daß Originalarray um das es geht, wird beim Einlesen einer Textdatei erstellt, und ergibt dann ein Array von ca. a(45000,2) und alle Einträge sind Strings von unterschiedlicher Länge.

Soweit ich weiß wird das dann so im Speicher abgelegt, daß erst die 45000 Einträge mit dem Zweitindex 0 abgelegt werden, dann die nächsten 45000 Einträge mit dem zweitindex 1, dann die letzten 45000 Einträge mit dem Zweitindex 2.

Um da jetzt was in dieses Array „einzufügen“ müßte ich ja an drei Stellen etwas einfügen und die SpeicherAdressen dieser drei Stellen kenne ich ja nicht da die Einträge unterschiedliche Bytelängen haben.

Würde ich diese Speicheradressen kennen könnte ich ja mit rtlmovememory die nachfolgenden Einträge verschieben um da was einzutragen.

Theoretisch bin ich mir sehr sicher die Lösung zu kennen wie man das lösen kann.
Angenommen ich habe das Array a(45000,2) und ich möchte dort wo in a(x,1) das Wort „Huhu“ steht, etwas einfügen.
Dann muß ich nur ab der Startspeicheradresse vom Array a nach dem Wort „Huhu“ suchen.
Wenn ich jetzt die Speicheradresse des Wortes „Huhu“ kenne, nützt mir das erstmal nix.
Aber, soweit ich weiß hat jeder Eintrag in einer Arrayliste die im Speicher steht hinten eine 0 o.ä.
Wenn ich nun ermitteln könnte wieviele „Nullen“ es zzwischen der Startadresse des Array und dem Eintrag „Huhu“ gibt, so kann ich daraus berechnen, daß das Wort „Huhu“ in a(32378,1) stehen muß.
Auch durch Zählung der „Nullen“ kriege ich dann raus wo im Speicher a(32378,0) und a(32378,2) abgelegt wurde.
Dann könnte ich durch dreimaliges „Move“ das Problem lösen.

Soweit die Theorie :smile:

Ich hoffe ich konnte mich einigermaßen verständlich machen :smile:

Das Array bleibt erst mal im Speicher, Reinhard möchte es ja
an ein Listen-Steuerelement übergeben. Ob das dann so
fesichert wird, oder ob das nur eine Anzeige ist, weiß ich
nicht.

Letzlich soll die reine Ausgabe dann doch in Excel erfolgen. Aber ich wollte es ja umbauen sodaß man das Ergebnis in einer VB-Listbox sieht.
Leider weigert sich meine Listbox in VB5.0 beharrlich mehrere Spalten anzuzeigen. Hinweise auf ListView brachten mir nix, weil ich die bei VB5.0 nicht finde :frowning:

Danke an alle die sich einen Kopf machen um mir da zu helfen mit dem Problem der Arrayumverschiebung.
Gruß
Reinhard

Hallo Reinhard,

nein, das hat mit Excel nix zu tun. Ich habe ein gefülltes
Array a(5) das so im Speicher abgelegt ist (die Zahlen sind
die Werte in dem Array):

OK.

1
2
3
4
5
6

Nun möchte ich es „vergrößern“ um einen Eintrag, damit es
nachher so aussieht im Speicher:

1
2
3
Neuer Eintrag
4
5
6

Auch OK. Mit Zahlen kein Problem.

Private Declare Sub CopyMemory Lib "kernel32" \_
 Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, \_
 ByVal ByteLen As Long)

Dim Arr() As Byte

Private Sub Command1\_Click()
 Dim Pos As Long, i As Integer
 Pos = 3 '




> Dazu kann ich mir ein neues leeres array b(6) anlegen, dann  
> gehe ich das Array a einzeln durch und schaufle die ersten 3  
> Einträge in die drei ersten Einträge von b, dann schreibe ich  
> den 4ten Eintrag in b hinein,dann schaufle ich die letzten 3  
> Einträge von a in die 3 letzten Einträge von b.  
>   
> Das geht, kriegen wir alle hin.


Ja, auch ohne neues Array. :smile:



> Nun möchte ich aber auf einen Rutsch die ersten 3 Einträge in  
> die 3 ersten Einträge von b kopieren und auch die 3 letzten  
> Einträge von a in die 3 letzten Einträge von b kopieren. Darum  
> geht es mir.


Wenn Du unbedingt zwei Arrays willst, das geht genau so.



    
    
    Private Declare Sub CopyMemory Lib "kernel32" \_
     Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, \_
     ByVal ByteLen As Long)
    
    Dim a() As Byte
    Dim b() As Byte
    
    Private Sub Command1\_Click()
     Dim Pos As Long, i As Integer
     Pos = 3 '
    
    
    
    > Trotz der Hilfe von Alex und Euch kriege ich das aber nichtmal  
    > mit einem eindimensionalen Array hin.
    
    
    Das muss aber jetzt auch bei Dir laufen, ist getestet.
    
    
    
    > Die Codes von Alex habe ich stundenlang getestet in  
    > **<u>VB5.0</u>** , ich glaube ich  
    > habe alle Varianten durchgespielt wo man strptr(), Byval,  
    > byref
    
    
    Brauchst Du bei Arrays nicht. Einfach weg lassen und nur das Feld des Arrays schreiben. Das wird Dein Problem gewesen sein.
    
    
    
    > sowohl in den Aufrufen als auch in der API-Deklaration  
    > benutzen kann.  
    >   
    > Ich glaube eine Lösung kann ich mir abschminken:frowning:  
    > Denn erschwerdend kommt dazu, daß Originalarray um das es  
    > geht, wird beim Einlesen einer Textdatei erstellt, und ergibt  
    > dann ein Array von ca. a(45000,2) und alle Einträge sind  
    > Strings von unterschiedlicher Länge.
    
    
    
    Das ist der Punkt. Sobald das Array als String deklariert ist, funktioniert das so nicht mehr. Ob und wie das dann geht, habe ich keine Ahnung. Dafür habe ich noch keine Lösung gesehen.
    
    
    
    > Soweit ich weiß wird das dann so im Speicher abgelegt, daß  
    > erst die 45000 Einträge mit dem Zweitindex 0 abgelegt werden,  
    > dann die nächsten 45000 Einträge mit dem zweitindex 1, dann  
    > die letzten 45000 Einträge mit dem Zweitindex 2.
    
    
    Das zweidimensionale Array ist eher nicht das Problem. Das Problem sind die Strings!
    
    
    
    > Um da jetzt was in dieses Array "einzufügen" müßte ich ja an  
    > drei Stellen etwas einfügen und die SpeicherAdressen dieser  
    > drei Stellen kenne ich ja nicht da die Einträge  
    > unterschiedliche Bytelängen haben.
    
    
    Zumal Du da nichts verändern kannst. So einfach ist es nicht.
    
    
    
    > Würde ich diese Speicheradressen kennen könnte ich ja mit  
    > rtlmovememory die nachfolgenden Einträge verschieben um da was  
    > einzutragen.
    
    
    Nein. Nur die Zeiger stehen in einem Zusammenhängenden Speicherbereich. Die einzelnen Strings werden an zufällig freie Speicheradressen geschrieben, stehen nicht direkt hintereinender. 
    
    
    
    > Theoretisch bin ich mir sehr sicher die Lösung zu kennen wie  
    > man das lösen kann.
    
    
    Du warst Dir sicher, weil Du fälschlicher Weise angenommen hast, daß das Array in der richtigen Reihenfolge in einem zusammenhängenden Speicherbereich steht. Das war ein Irrtum.
    
    
    
    > Angenommen ich habe das Array a(45000,2) und ich möchte dort  
    > wo in a(x,1) das Wort "Huhu" steht, etwas einfügen.  
    > Dann muß ich nur ab der Startspeicheradresse vom Array a nach  
    > dem Wort "Huhu" suchen.  
    > Wenn ich jetzt die Speicheradresse des Wortes "Huhu" kenne,  
    > nützt mir das erstmal nix.  
    > Aber, soweit ich weiß hat jeder Eintrag in einer Arrayliste  
    > die im Speicher steht hinten eine 0 o.ä.
    
    
    Nein. Diese 'Arrayliste' gibt es so nicht. Es gibt ein eigenes Array, in dem die Zeiger auf die Strings stehen. Das habe ich erfolglos versucht zu manipulieren. :frowning:
    
    
    
    > Wenn ich nun ermitteln könnte wieviele "Nullen" es zzwischen  
    > der Startadresse des Array und dem Eintrag "Huhu" gibt, so  
    > kann ich daraus berechnen, daß das Wort "Huhu" in a(32378,1)  
    > stehen muß.  
    > Auch durch Zählung der "Nullen" kriege ich dann raus wo im  
    > Speicher a(32378,0) und a(32378,2) abgelegt wurde.  
    > Dann könnte ich durch dreimaliges "Move" das Problem lösen.  
    >   
    > Soweit die Theorie :smile:
    
    
    Leider falsch. 
    
    
    
    > Ich hoffe ich konnte mich einigermaßen verständlich machen :smile:
    
    
    Ja, das schon, aber Du hast eine falsche Vorstellung. So wie du dachtest, wird das Array nicht verwaltet.
    
    
    
    > > Das Array bleibt erst mal im Speicher, Reinhard möchte es ja  
    > > an ein Listen-Steuerelement übergeben. Ob das dann so  
    > > fesichert wird, oder ob das nur eine Anzeige ist, weiß ich  
    > > nicht.
    > 
    >   
    > Letzlich soll die reine Ausgabe dann doch in Excel erfolgen.  
    > Aber ich wollte es ja umbauen sodaß man das Ergebnis in einer  
    > VB-Listbox sieht.  
    > Leider weigert sich meine Listbox in VB5.0 beharrlich mehrere  
    > Spalten anzuzeigen.
    
    
    Das geht schon, aber sehr schlecht zu handhaben und sieht auch nicht gut aus. Stell mal bei List2 Die Eigenschaft 'Columns' auf 3 und dann:
    
    
    
        
        
        Private Sub Command2\_Click()
         Dim c As Integer, r As Integer
         For i = 1 To 4
         List2.AddItem " "
         Next
         For r = 0 To 4
         List2.List(r) = CStr(r) + Chr(9) + "a" + Chr(9) + "b"
         Next
        End Sub
        
    
    
    
    
    Übel, finde ich. :frowning:
    
    
    
    > Hinweise auf ListView brachten mir nix,  
    > weil ich die bei VB5.0 nicht finde :frowning:
    
    
    Und das MsFlexgrid? Sag bloß, das hast Du auch nicht. Auch nicht unter Projekte/Komponenten? 
    
    Gruß Rainer

Hallo Jungs,

ich antworte nun mal nicht jeden einzeln.
Ihr macht euch das alles viel zu schwer oder denkt zu kompliziert :s

Schauen wir doch einmal uns das alles genauer an!

Bei der API CopyMemory wird einmal nach der Destination gefragt, dann noch nach der Source Quelle und dann noch einmal nach der Grösse.

Die Destination, sowie die Source sind kein Thema! Der Hund ist bei der Grösse begraben.

Wenn wir nun einmal ueberlegen, wie man das am besten löst fallen einem doch spontan 2 wege ein! Entweder man vergibt im Vorfeld schon eine Fixe Grösse. Diese kann man dann angeben. Also Grösse *2 ist ja klar :wink:( VB speichert intern String im Unicode Format ab, deswegen 2 Byte anstatt nur 1!)
Aber da stellt sich die Frage. Was für ein Daten Volumen kommen an Daten an. VB Strings koennen glaub bis zu max. 2 GB an Daten aufnehmen. Also verwerfen wir die Idee mal wieder ganz fix!

Für alle die es dennoch interessiert.

Public Function CopyString(ByVal Pointer As Long, ByVal Size As Long)As String
 Dim nString As String
 Dim nPos As Long
 nString = String$(Size, 0)
 CopyMemory ByVal StrPtr(nString), ByVal Pointer, Size \* 2
 nPos = InStr(nString, Chr(0))
 If nPos Then
 PtrStr = Mid$(nString, 1, nPos - 1)
 Else
 PtrStr = nString
 End If
End Function

Wenn wir nun einmal weiter überlegen. Hmm, welche Datentypen unter VB koennen Strings speichern. Da haetten wir einmal den String, der aber flexibel ist und wir die Grösse nicht wissen!
Dann haetten wir noch den Datentyp Variant! Und genau dem machen wir uns zu nutzen. Der Datentyp Variant kann alles mögliche beinhalten, also auch Strings. dabei interessiert die Länge nicht! der Datentyp Variant brauch 16 Byte!
Also schreiben wir den ganzen Kram halt auf Variant. Benötigt man später dann die Daten so kann man sie jederzeit wieder in einen String umwandeln :wink:

Speziell für Reinhard, wo ich mal hoffe das ich nun richtig liege.

'Demo mit 1000 Daten!
'eine Form erstellen.
'Darauf 2 listboxen ( List1 und List2)
'Ein Command Button ( Command1)
'List1 zeigt die Daten im Array A an und List2 die Daten im Array B

Option Explicit


Private Declare Sub Copy Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)


Dim a() As Variant
Dim b() As Variant
Dim Loading As Boolean

Private Sub Command1\_Click()
On Error Resume Next
Dim Count As Variant
Dim vData As String
Count = InputBox("Ab welcher Position einfügen?")
If IsNumeric(Count) Then
 If Count \> UBound(a) Or Count "" Then
 List2.AddItem b(i)
 End If
Next
Screen.MousePointer = 0
End Sub

Private Sub Form\_Activate()
Dim i As Long
Dim j As Byte
Dim k As Integer
If Loading Then
 Screen.MousePointer = 11
 Me.Caption = "Lade Daten"
 Loading = Not Loading
 ReDim a(1000)
 ReDim b(UBound(a) + 1)
 For i = 0 To 1000
 k = Int(Rnd \* 30) + 1
 For j = 1 To k
 a(i) = a(i) + Chr(Int((26 \* Rnd) + 1) + 65)
 Next j
 List1.AddItem a(i)
 Me.Caption = "Lade Daten [" & i & "/1000]"
 If i Mod 1000 = 0 Then DoEvents
 Next i
End If
Me.Caption = "Bereit"
Screen.MousePointer = 0
End Sub

Private Sub Form\_Load()
 Loading = True
End Sub

MfG Alex

1 Like

Hallo Jungs,

Hallo Alex!

ich antworte nun mal nicht jeden einzeln.
Ihr macht euch das alles viel zu schwer oder denkt zu
kompliziert :s

hmmm, die Lösung habe ich noch nie gesehen, SUPER !!! Schon gesichert! :smile:

Ja, das ist exakt das, was Reinhard gesucht hat und was ich nicht gefunden habe.

Gruß Rainer

Hallo Rainer,

hmmm, die Lösung habe ich noch nie gesehen, SUPER !!! Schon
gesichert! :smile:

Marke Eigenbau mit ca. 10 Minuten Arbeit *zwinker*

Ja, das ist exakt das, was Reinhard gesucht hat und was ich
nicht gefunden habe.

Da waerst du auch selbst darauf gekommen, wenn du nicht zu kompliziert gedacht haettest. Waerst du auf die Idee gekommen die Daten in ein Variant Feld abzulegen haettest du das auch binnen paar Minuten hinbekommen :smile: Ansonsten haettet man es halt mit einem String einer Fixen Grössen lösen koennen :smile: Dazu habe ich dir ja auch den Weg gezeigt.
Aber warum verwendet Reinhard bei solch einem Datenvolumen nicht eine Klasse und daraus eine Collection? Da ist er flexibler :wink:

Aber schön das wir es nun geschafft haben, Reinhard zu helfen. Da wird er sich sicher freuen und sein Vorhaben nicht aufgeben :wink:

Er muss nur darauf achten das er sich so den Speicher sinnlos zu müllt und das frueher oder später zu abstuerzen führen kann!

MfG Alex

Ein Zeiger lässt sich ja kopieren und ich hätte erwartet, daß
die Zeiger hintereinander stehen. Unklar ist allerdings, wie
viele Bytes so ein Zeiger hat. Ich habe auch schon mal ein
paar Bytes mehr kopiert, keie Veränderung, noch nicht mal ein
Absturz.

Ein Zeiger ist nichts weiter als eine Variable vom Typ Long. Ein Zeiger wird im Stack abgelegt, beinhaltet die Adresse der Daten im Heap und zeigt auf diese. Also ist die Grösse eines Zeigers immer 4 Byte!

MfG Alex

Hi Alex,

Ein Zeiger ist nichts weiter als eine Variable vom Typ Long.
Ein Zeiger wird im Stack abgelegt, beinhaltet die Adresse der
Daten im Heap und zeigt auf diese. Also ist die Grösse eines
Zeigers immer 4 Byte!

danke. Inzwischen hatte ich ein wenig ‚Grundlagenforschung‘ :smile: betrieben und habe gesehen, daß das vier Bytes sind. Mein erster Versuch, die zu verbiegen ist allerdings gescheitert. Ich habe inzwischen eine vage Vermutung, warum und wie man das eventuell umgehen kann. Ich werde jetzt aber aufhören, mir das Hirn zu zermartern wo da die Probleme liegen und wie man das eventuell doch noch packen könnte, Deine Lösung mit Hilfe von ‚Variant‘ funktioniert ja perfekt. Warum muss ich ja nicht unbedingt verstehen.

Gruß Rainer

Hi Alex,

ich habe das Programm noch ein paar mal gestartet, alles verstehe ich noch nicht, aber es gibt ein Problem. Beim Beenden des Programms stürzt die IDE ab. Ich bastel mal weiter …

Gruß Rainer

Hi Alex,

ich habe es doch noch mal mit Strings versucht, klappt und stürzt auch nicht ab.

Option Explicit

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" \_
 (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Dim Arr() As String
Dim Ze() As Long

Private Sub Command1\_Click()
 Dim i As Integer, m As Long, Po As Long, Txt As String
 Txt = "AAAAAAAAAAAAAAAAAAAAA"
 Po = 4
 ReDim Preserve Arr(UBound(Arr) + 1)
 ReDim Preserve Ze(UBound(Arr))
 Arr(UBound(Arr)) = Txt
 CopyMemory Ze(0), ByVal VarPtr(Arr(0)), (UBound(Arr) + 1) \* 4
 m = Ze(UBound(Ze))
 CopyMemory Ze(Po + 1), Ze(Po), (UBound(Ze) - Po) \* 4
 Ze(Po) = m
 CopyMemory ByVal VarPtr(Arr(0)), Ze(0), (UBound(Arr) + 1) \* 4
 List2.Clear
 For i = 0 To UBound(Arr)
 List2.AddItem Arr(i)
 Next
End Sub

Private Sub Form\_Load()
 Dim r As Integer, p As Integer, n As Integer, i As Integer, zl As String
 ReDim Arr(10)
 ReDim Ze(10)
 For i = 0 To 10
 zl = ""
 n = Int(Rnd(1) \* 10) + 1
 For p = 1 To n
 r = Int(Rnd(1) \* 26) + 65
 zl = zl + Chr(r)
 Next
 Arr(i) = zl
 List1.AddItem zl
 Next
End Sub

Der Umweg über das zweite Array ist nötig. Wenn ich das richtig verstehe weigert sich VB mit zweí verschiedenen Zeigern auf die selbe Stelle im Speicher zu zeigen. Schritt für Schritt an den Zeigern zu arbeiten geht also nicht, aber das ganze Array auf einmal überschreiben geht.

Gruß Rainer

Speziell für Reinhard, wo ich mal hoffe das ich nun richtig
liege.

Hallo Alex,

danke für deine Ausführlichkeit.
Ja, jetzt klappt es so wie ich mir das gewünscht habe:smile:

Ich habe jetzt mehrmals den Code unverändert ausprobiert, leider ist, wenn ich auf das Schließkreuz der Form klicke, danach die IDE wech :frowning:

@Rainer, ich kam noch nicht dazu deine Codes zu testen. Ich habe jetzt so viele Codes erhalten und auch selbst eigene entwickelt und einige im Internet gefunden, ich muß da erst mal wieder den Überblick kriegen,also diesen Artikelbaum ausdrucken usw.

Wie ich schon schrieb wird das Ganze mehr mehrdimensionalen Arrays noch komplizierter.

Und eine Umsetzung nach VBA steht je nach Code noch in den Sternen, da z.B. VBA kein „strptr“ kennt. „varptr“ ist bekannt, wird aber nicht in der Hilfe beschrieben.
Das macht aber nix, dann ist halt das Excelprojekt gestorben, es war sowieso nur der Versuch einer Lösung für eine Anfrage im Excelbrett, die sich gar nicht um Arrays handelt.

Jmd. wollte aufgrund der Vornamen einer bestehenden Kundendatenliste wissen ob man für einen Serienbrief aufgrund des Vornamens die Anrede „Herr“ oder „Frau“ automatisch festlegen könnte.
Dazu braucht man ja Listen mit weiblichen und männlichen Vornamen, ich stieß dabei auf eine entsprechende Liste im Txtformat,
hier der Anfang dieser Liste: http://www.hostarea.de/server-10/Oktober-3285ab8e90.txt
Die insgesamt ca. 45000 Zeilen mit den Vornamen habe ich dann in ein Array a(45000,2) gesplittet. Im Index 1 stehen die Vornmaen, im Index 0 M oder F, und im Index 2 Infos in welchen Ländern das so ist.

Die Liste ist komprimiert/kodiert, das heißt im Index 1 steht nicht z.B.

Ralf
Rainer
Reiner
Rheiner
Richard

untereinander, sondern verkürzt zu

Ralf
Rner
Richard

und im Kopf der Originaldatei ist halt aufgelistet, daß „“ durch „ai“, „ei“ und „hei“ zu ersetzen ist um die komplette Liste zu erhalten. Neben „“ gibt es noch andere „Ersetzungen“

So kam ich halt auf die ganze Arraygeschichte…

Gruß
Reinhard

Hallo Reinhard,

Ich habe jetzt mehrmals den Code unverändert ausprobiert,
leider ist, wenn ich auf das Schließkreuz der Form klicke,
danach die IDE wech :frowning:

ja, bei mir auch. Da muss es Probleme mit dem Speicher geben, die ich aber noch nicht verstehe.

Deshalb habe ich noch weiter gebastelt und eine stablie Lösung gefunden.

/t/vb-excel-vba-array-vergroessern/4820024/22

Nach meiner Meinung muss das auch in Excel-VBA in einer Userform laufen.

Gruß Rainer

Der Umweg über das zweite Array ist nötig. Wenn ich das
richtig verstehe weigert sich VB mit zweí verschiedenen
Zeigern auf die selbe Stelle im Speicher zu zeigen. Schritt
für Schritt an den Zeigern zu arbeiten geht also nicht, aber
das ganze Array auf einmal überschreiben geht.

Hallo Rainer,

bei meinen Recherchen stiess ich auf rtlMOVEmemory und rtlCOPYmemory, beim letzteren ist die Einschränkung daß sich Quell- und Zielbereich nicht überlappen dürfen.

Bei rtlMOVEmemory gibt es diese Einschränkung nicht, insofern verstehe ich auch nicht warum man nicht paar Zeiger auf die gleiche Stelle lassen dürfte.

Irritieren tut mich auch die allgemeine Verwendung von „copymemory“ für rtlMOVEmemory.

Für mich unterscheiden sich Copy und Move schon eklatant. D.h. den Aliasnamen „Movememory“ für rtlMOVEmemory würde ich verstehen, den Aliasnamen „Copymemory“ halt nihct.
Aber alle benutzen „Copymemory“ für rtlMOVEmemory *grübel*

Gruß
Reinhard

Hallo Reinhard,

bei meinen Recherchen stiess ich auf rtlMOVEmemory und
rtlCOPYmemory, beim letzteren ist die Einschränkung daß sich
Quell- und Zielbereich nicht überlappen dürfen.

Bei rtlMOVEmemory gibt es diese Einschränkung nicht, insofern
verstehe ich auch nicht warum man nicht paar Zeiger auf die
gleiche Stelle lassen dürfte.

Wenn die Zeiger von ‚a‘ und ‚b‘ gleich sind und ich ändere ‚a‘ müsste sich ‚b‘ mit ändern. Daß VB das nicht mag, kann ich verstehen. :smile:

Irritieren tut mich auch die allgemeine Verwendung von
„copymemory“ für rtlMOVEmemory.

Für mich unterscheiden sich Copy und Move schon eklatant. D.h.
den Aliasnamen „Movememory“ für rtlMOVEmemory würde ich
verstehen, den Aliasnamen „Copymemory“ halt nihct.
Aber alle benutzen „Copymemory“ für rtlMOVEmemory *grübel*

Das ist einfach, kein Mensch tippt die Deklaration. :smile:
Das steht so in der API-Guide und ich kopiere das dort. Das ist bequem und vermeidet Tippfehler oder Irrtümer. Wenn ‚alle‘ das so verwenden, werden die die Deklaration auch nicht tippen, sondern nur kopieren.

Gruß Rainer

Hallo Rainer,

danke. Inzwischen hatte ich ein wenig ‚Grundlagenforschung‘

-) betrieben und habe gesehen, daß das vier Bytes sind. Mein

erster Versuch, die zu verbiegen ist allerdings gescheitert.
Ich habe inzwischen eine vage Vermutung, warum und wie man das
eventuell umgehen kann. Ich werde jetzt aber aufhören, mir das
Hirn zu zermartern wo da die Probleme liegen und wie man das
eventuell doch noch packen könnte, Deine Lösung mit Hilfe von
‚Variant‘ funktioniert ja perfekt. Warum muss ich ja nicht
unbedingt verstehen.

Nichts zu danken :smile:
Aber was verstehst du denn nicht an dem Source ( Mit dem Variant?)
Und welchen Zeiger willst du denn wie verbiegen? Und wobei hast du denn da Schwierigkeiten? Vielleicht kenne ich ja die Lösung und dann weisst du sie dann auch danach :wink:

MfG Alex