Anzeige
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

zu großes Array - echte Nuss für Profis!

Forumthread: zu großes Array - echte Nuss für Profis!

zu großes Array - echte Nuss für Profis!
02.08.2004 11:00:33
Rene
Hallo,
ich habe eine Liste mit ca. 10.000 DS. Der Schlüssel ist eine 14-stellige Zahl (eigentlich eine Kombination aus 3 Werten). Um auf die einzelnen DS schnell zugreifen zu können, wollte ich den Schlüssel in ein Array einlesen, um so mit nur einem Zugriff die ZeilenNR ermitteln zu können. In der Spalte 1 steht dieser zusammengesetzte Schlüssel.
Allerdings kann ich nicht so ein großes Array definieren und das ist mein Problem. Wie kann ich dieses Problem anders lösen. Anbei das 'nicht-funktionierende' Beispiel.
Vielen, vielen Dank für die Hilfe - ist leider auch ein bisschen dringend.
Beispiel:
Public MA_Index(100000000000000) As Integer

Sub Test()
for Zeile = 2 to 10000
MA(cells(Zeile,1)) = zeile
next Zeile
End Sub

Anzeige

20
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: zu großes Array - echte Nuss für Profis!
02.08.2004 11:14:26
Harald
Hallo Rene,
probier's mal mit der Excel-eigenen Suchfunktion, die ist eigentlich recht schnell:

Sub Test()
Cells.Find(What:=Schlüssel, After:=ActiveCell, LookIn:=xlFormulas, LookAt:= _
xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:=False _
, SearchFormat:=False).Activate
End Sub

Alternativ wäre zu fragen, ob Du den Schlüssel durch eine geeignete Funktion 1-zu-1 auf einen 5 stelligen Schlüssel eindampfen kannst. Immerhin hast Du nur ca. 10^5 Datensätze, nicht 10^14.
Gruß Harald
Anzeige
AW: zu großes Array - echte Nuss für Profis!
02.08.2004 11:19:27
Nepumuk
Hallo Harald,
alternativ würden 200.000 Gb Arbeitsspeicher auf helfen. :-)))
Gruß
Nepumuk
AW: zu großes Array - echte Nuss für Profis!
02.08.2004 11:23:00
Harald
Hallo Nepomuk,
ich bin mir nicht sicher, dass Excel oder Windows damit klar kommt, mal abgesehn von der CPU. Hast Du es mal probiert?
Doppel :-)
Gruß Harald
P.S.: Im Ernst, das mit dem Abbilden des Schlüssels war ehrlich gemeint. Wenn man sich richtig austoben will, könnte man eine ausgewachsene Listenverwaltung mit Hash-Funktion und Kollisionsbearbeitung programmieren - oder vielleicht so was in der Rechrche bereits finden.
Anzeige
weitere Frage
02.08.2004 11:22:01
Rene
Hallo Harald,
ich wollte die Zahlen nicht in eine Tabelle eintragen, sondern habe sie am Anfang nur im Speicher. Die Zahlen kann ich leider nicht zusammenpressen - ich finde es auch idiotisch, aber die Zahlen kommen von anderen Systemen, die nur diese "großen" Nummern kennen.
Vielleicht gibt es so was wie cells.find für Array's, also komplett für VBA?
Vielen Dank für jeden Tipp.
Anzeige
AW: weitere Frage
02.08.2004 11:26:28
Nepumuk
Hallo Rene,
guckst du hier: https://www.herber.de/forum/messages/463055.html
Die Routine zum erstellen der Primzahlen:


Public Sub test()
    Dim As Long, y As Long
    Call Primzahlen(50000, x, y)
End Sub
Private Sub Primzahlen(ByVal lng_startwert As LongByRef lng_kleiner As LongByRef lng_groesser As Long)
    Dim lng_counter As Long, lng_startwert_k As Long, lng_startwert_g As Long
    If lng_startwert Mod 10 <> 0 Then
        lng_startwert_k = lng_startwert - (lng_startwert Mod 10)
        lng_startwert_g = lng_startwert + 10 - (lng_startwert Mod 10)
    Else
        lng_startwert_k = lng_startwert
        lng_startwert_g = lng_startwert
    End If
    For lng_counter = lng_startwert_k To Step -10
        If IsPrim(lng_counter - 1) Then lng_kleiner = lng_counter - 1: Exit For
        If IsPrim(lng_counter - 3) Then lng_kleiner = lng_counter - 3:  Exit For
        If IsPrim(lng_counter - 7) Then lng_kleiner = lng_counter - 7:  Exit For
        If IsPrim(lng_counter - 9) Then lng_kleiner = lng_counter - 9:  Exit For
    Next
    For lng_counter = lng_startwert_g To lng_startwert_g * 2 Step 10
        If IsPrim(lng_counter + 1) Then lng_groesser = lng_counter + 1: Exit For
        If IsPrim(lng_counter + 3) Then lng_groesser = lng_counter + 3: Exit For
        If IsPrim(lng_counter + 7) Then lng_groesser = lng_counter + 7: Exit For
        If IsPrim(lng_counter + 9) Then lng_groesser = lng_counter + 9: Exit For
    Next
End Sub
Private Function IsPrim(ByVal lng_pruefziffer As LongAs Boolean
    Dim lng_counter As Long
    If lng_pruefziffer Mod 3 = 0 Then Exit Function
    If lng_pruefziffer Mod 7 = 0 Then Exit Function
    For lng_counter = 10 To CLng(lng_pruefziffer ^ 0.5) Step 10
        If lng_pruefziffer Mod (lng_counter + 1) = 0 Then Exit Function
        If lng_pruefziffer Mod (lng_counter + 3) = 0 Then Exit Function
        If lng_pruefziffer Mod (lng_counter + 7) = 0 Then Exit Function
        If lng_pruefziffer Mod (lng_counter + 9) = 0 Then Exit Function
    Next
    IsPrim = True
End Function


Gruß
Nepumuk
Anzeige
Es wird unklarer
02.08.2004 11:27:19
Harald
Hallo Rene,
die Nachfrage verstehe ich nicht mehr.
Also: Du hast Die Datensätze doch in der Tabelle.Jetzt suchst Du nur noch nach einer Möglichkeit, schnell auf einen Datensatz zuzugreifen, der durch den Schlüssel identifiziert wird.
Was genau meinst Du damit, dass die Zahlen "Anfang nur im Speicher" sind?
Eine FInd-Funktion für Arrays gibt es m.W. in Excel nicht, mal abgesehen von dem Problem mit dem Speicherplatz, siehe die anderen Anmerkungen.
Gruß Harald
Anzeige
sorry - hier nochmal die ganze Problematik
02.08.2004 11:50:33
Rene


Hallo Harald,
danke für deinen Beitrag. Ich will nochmal ganz weit ausholen.
Ich bekomme Rohdaten, die in der ersten Spalte den Schlüssel enthalten. Bisher war dieser Schlüssel eine 6-stellige Zahl, die ich in ein Array einlesen konnte. Die Werte, die in den folgenden Spalten des DS stehen, habe ich in ein selbstgebautes Datenmodell eingelesen.
Nun bläht der Schlüssel (Spalte 1) durch eine IT-Umstellung 'unsinnigerweise' auf 14 Stellen auf. Ich kann aber nicht ohne diesen Firmenschlüssel arbeiten - leider.
Anbei mal das gekürzte Codebeispiel, das bisher funktioniert.
' Definitionen
Public MA_Index(1000000)                        As Integer
Type Mitarbeiter_Daten
    Name                                        As String
    Nummer                                      As Long
    ID                                          As Verweis
    status                                      As Long
    Kategorie                                   As String
    SOS                                         As Boolean
    Erf                                         As Double
    Umsatz                                      As Double
    ...
End Type
Public Mitarbeiter(maxAnzMA)                    As Mitarbeiter_Daten
' Einleseroutine
For Zeile = 2 To maxZE
    If Cells(Zeile, 1) = "" Then exit for
    Zeilen_Inhalt = Rows(Zeile)
    MA_Index(Zeilen_Inhalt(1, 1)) = Zeile - 1
        With Mitarbeiter(Zeile - 1)
            .Nummer = Zeilen_Inhalt(1, 1)
            .Name = Zeilen_Inhalt(1, 6)
            .status = Zeilen_Inhalt(1, 20)
            .Kategorie = Zeilen_Inhalt(1, 82)
            .SOS = Zeilen_Inhalt(1, 85)
            .Erf = Zeilen_Inhalt(1, 87)
            .Umsatz = Zeilen_Inhalt(1, 26)
        End With
    End If
Next
Wird es mit dem Beispiel klarer? Wenn ich bei MA_Index(1000000) einen so hohen Wert eintrage, dann bekomme ich verständlicherweise eine Fehlermeldung. Denn soviel Variablen kann Excel nicht verarbeiten.


Anzeige
AW: sorry - hier nochmal die ganze Problematik
02.08.2004 12:32:19
Harald
Hallo Rene,
ich verstehe das so, dass die Quelldaten auch schon in Form einer Excel-Tabelle vorliegen.
Eigentlich hört sich das für mich nach einem klassischen Datenbankproblem an. Aber ich gehe wohl richtig in der Annahme, dass eine Excel Lösung wegen der weiteren Verarbeitung gewünscht ist.
Du möchtest also den MA_Index (14 stellig) als Index in ein Array benutzen, um über den MA_Index schnell auf die übrigen Daten des Mitarbeiters zugreifen zu können.
So wie Du Dir das vorstellst ist die Lösung unglücklich. Du hälts ein 10^14 Elemente großes Array vor, von dem nur 10^5 Elemente genutzt sind. Selbst wenn das technisch machbar ist, ist das eine große Verschwendung.
Leider habe ich nicht die Zeit, Dir eine komplette Lösung auszuarbeiten, aber ich will mal skizzieren, wie ich vorgehen würde:
Lösung 1)
Es gäbe vielleicht eine Funktion, die den 14stelligen MA-Index eindeutig auf eine kleinere Zahl abbildet? Z.B. könnte es ja sein, dass Teile des Index nur bestimmte Werte annehmen können. Risiko dabei ist, dass man ja nie sicher sein kann, wann die IT-Abteilung die nächste Umstellung vornimmt.
Lösung 2)
Verzichte auf das Array MA_Index().
Statt dessen sortiere das Array Mitarbeiter(maxAnzMA) nach dem MA_Index (geeignete Sortierfunktionen findest Du z.B. in der Recherche. Wenn die Daten weit gehend sortiert ankommen, genügt ein einfaches Bubblesort. Bei stark unsortierten Daten wäre evtl. zu Quicksort zu raten.
Für die Suche in dem sortierten Array kannst Du dann eine einfache binäre Suche verwenden, die dann recht schnell wird. Das geht so:
Einfach das mittlere Element des sortierten Arrays angucken und den Index mit dem Suchwert vergleichen.
Bei Übereinstimmung - gefunden.
Wenn Suchwert größer, Suche in der "rechten" Hälfte des Arrays wiederholen (wieder Halbieren etc.)
Wenn Suchwert kleiner, Suche in der "linken" Hälfte des Array wiederholen.
Du benötigst maximal log2(N) Vergleiche, also maximal 14 Vergleiche - gegenüber im Mittel schon 5000 Vergleichen bei einer linearen Suche...
Wenn das nicht schnell geht?
Viel Erfolg beim Programmieren.
Gruß Harald
Anzeige
Siehe unten Antwort von Gerd
02.08.2004 12:37:44
Gerd
AW: sorry - hier nochmal die ganze Problematik
02.08.2004 12:59:15
Rene
Hallo Harald,
du hast 100% recht. Eigentlich ist es ein DB-Problem, aber ...
Ich werde deinen Lösungsvorschlag 2 näher verfolgen, denn die Idee unter 1 ist mir zu unsicher. Also werde ich versuchen, mal eine binäre Suche zu programmieren - mal was ganz neues für mich.
OK, vielen Dank für alle Tipps.
Anzeige
AW: zu großes Array - echte Nuss für Profis!
Nike
Hi,
das ist nicht unbedingt Profiwissen, eher Basics,
Integer geht halt nur bis ein paar und 60000
versuchs mal mit Double
Public MA_Index(100000000000000) As Double
oder du behandelst es als Text (as string)
Bye
Nike
AW: zu großes Array - echte Nuss für Profis!
02.08.2004 11:21:25
Nepumuk
Hallo Nike,
dann wären wir schon bei ~ 800.000 Gb
Gruß
Nepumuk
Anzeige
AW: zu großes Array - echte Nuss für Profis!
02.08.2004 11:24:17
Harald
Hallo Leute,
eine Fließkommazahl als Index für ein Array ist ja auch nicht gerade der Hit - mal abgesehn vom Speicher...
Gruß Harald
wäre mal ein schritt in richtung Fuzzylogic ;-) oT
IngoG
.
AW: zu großes Array - echte Nuss für Profis!
02.08.2004 11:52:44
Rene
Es nützt nichts, die Variable auf Double zu setzen, weil der Wert nicht das entscheidende Kriterium ist, warum Excel "knallt", sondern weil es mit dem Array zu viele Variablen erzeugt werden. Ich denke, das ist das Problem.
Anzeige
AW: zu großes Array - echte Nuss für Profis!
GerdZ
Hallo Rene,
Du mußt Dein Array nach der Nummer sortieren oder ein "Index-Array" anlegen, was nach Nummer sortiert ist und nur die Nummer und die Position in Deinem Array enthält.
Dann kannst mit folgendem Code (den Du noch an Deine Datenstruktur anpassen mußt) recht schnell die Position ermitteln und auf Deine Daten zugreifen:
Public Function Finde(Table, Element, Optional Anzahl As Integer) As Integer
Dim i As Integer, x As Integer, y As Integer
y = 0
If Anzahl = 0 Then
x = UBound(Table)
Else
x = Anzahl
End If
i = x / 2
If Element = Table(x) Then
Finde = x
Exit Function
End If
If Element = Table(0) Then
Finde = 0
Exit Function
End If
If UBound(Table) = 1 Then
Finde = -1
Exit Function
End If
While Element <> Table(i)
i = x - (x - y) / 2
If Element <= Table(i) Then x = i
If Element >= Table(i) Then y = i
If (x - y) = 1 Then
Finde = -1
Exit Function
End If
Wend
Finde = i
End Function
Gruß
Gerd
Anzeige
AW: zu großes Array - echte Nuss für Profis!
02.08.2004 12:53:54
Rene
Ist das ein Code, für eine binäre Suche?
Sieht so aus o.T.
02.08.2004 12:56:49
Harald
AW: zu großes Array - echte Nuss für Profis!
GerdZ
Hallo Rene,
ja, der Code enthält eine binären Suchalgorithmus.
Zusätzlich werden zuerst das letzte und das erste Element überprüft.
Gruß
Gerd
Anzeige
AW: zu großes Array - echte Nuss für Profis!
Hans
Wozu hat VBA den Typ Collection geschaffen...
Tut das für den angedachten Zweck?
Gruß HW
;

Forumthreads zu verwandten Themen

Anzeige
Anzeige
Anzeige
Anzeige
Entdecke relevante Threads

Schau dir verwandte Threads basierend auf dem aktuellen Thema an

Alle relevanten Threads mit Inhaltsvorschau entdecken

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Entdecke mehr
Finde genau, was du suchst

Die erweiterte Suchfunktion hilft dir, gezielt die besten Antworten zu finden

Suche nach den besten Antworten
Unsere beliebtesten Threads

Entdecke unsere meistgeklickten Beiträge in der Google Suche

Top 100 Threads jetzt ansehen
Anzeige