Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1024to1028
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

Collection oder Array nachträglich ohne Duplikate?

Collection oder Array nachträglich ohne Duplikate?
24.11.2008 18:27:00
Andreas
Hallo Herber Fans,
lange war ich nicht mehr hier, da mir die Arbeit mit dem Forum und das anschließende "allein rumbasteln" viel Wissen über Excel und VBA beschert hat. Aber heute stehe ich auf dem Schlauch...
Ich lasse den Bereich der DataFields einer Pivottabelle zeilenweise untersuchen. Wenn die Gesamte Selection in Zeile i = 0 ist, dann merke ich mir das betreffende PivotItem, um es später dann mit allen anderen, die noch dieses Kriterium erfüllen, auf visible = false zu setzen. Es soll eine Nullwert unterdrückung werden, die die Übersichtlichkeit erhöht.
Bisher habe ich alle Werte die die Kriterien erfüllen, in einer Collection gesammelt. Nach dem Akt des collectens habe ich dann über eine For Each Schleife alle Werte der Collection auf visible = false setzen lassen. Problem: Der Code lief lang. Auch schon mit deaktiviertem ScreenUpdating. Grund dafür: Es lagen Werte doppelt vor in der Collection. Sachlogisch ist das durchaus korrekt. Für die Performance aber nicht gut. Ich dachte bisher auch immer, eine Collection sorgt von sich aus dafür, daß keine Duplikate in ihr enthalten sind. Das hatte ich hier im Forum gelesen, scheint aber nicht korrekt zu sein?!
Wie kann ich beim Erstellen einer Collection (oder eines Arrays) Duplikate verhindern. Ich lese String Werte ein. Ich habe schon probiert mit 'WorksheetFunction.countif/ Match/ find/ etc.' zu arbeiten. Aber all diese Funktionen benötigen Ranges, um korrekt zu arbeiten.
Der Code soll direkt in die Collection (oder Array) gucken und prüfen: Bist du, lieber Textstring schon drin, wenn ja, dann kommst Du nicht noch einmal rein.
Ich könnte ja die Collection seinerseits wieder durch eine Schleife durchlaufen lassen, aber gibt es da keine elegantere Methode?
Vielen Dank und Grüße, Andreas Hanisch

8
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Collection oder Array nachträglich ohne Duplikate?
24.11.2008 18:52:00
ransi
Hallo Andreas
Wenn es um "Unikate oder Doppelte" in irgendeiner Form geht, ist das Dictionary-Object immer einen Versuch wert.
Schau dir das mal an:
Das sind deine Daten:
Tabelle1

 A
155L
255L
355L
455L
555L
69VL
71WQ
8IWA
9RW7
10T7B
11EIA
126S9
13VW9
14VW9
15VW9
16VW9
17VW9
18TQT
198H2
20P91
21P91
22P91
23P91
24RQH
25UYH
26PID
27UP3
28V38
290SI
309MX


Excel Tabellen im Web darstellen >> Excel Jeanie HTML 4
Jetzt starte mal diesen Code:
' **********************************************************************
' Modul: Tabelle1 Typ: Element der Mappe(Sheet, Workbook, ...)
' **********************************************************************

Option Explicit


Public Sub test()
Dim Arr As Variant
Dim MyDic As Object
Dim L As Long
Arr = Range("A1:A30")
Set MyDic = CreateObject("Scripting.Dictionary")
For L = 1 To UBound(Arr)
    MyDic(Arr(L, 1)) = 0 'Unikate sammeln
Next
Range("B1").Resize(MyDic.Count) = WorksheetFunction.Transpose(MyDic.Keys)
End Sub

In Sachen Geschwindigkeit gibts nichts schnelleres.
ransi
Anzeige
AW: Collection oder Array nachträglich ohne Duplikate?
24.11.2008 18:57:00
Reinhard
Hi Andreas,
zeige mal den Code, die Datei wo du in eine Collection was einliest.
Grundsätzlich, Collection ist deshalb langsam weil sie mit Strings arbeitet.
Dazu kommt, sie wird "innerlich" verwaltet, grad auch deshalb damit keine doppelten Werte auftauchen, aber auch aus anderen Gründen.
Bei korrekter Benutzun einer Collection hast du in ihr keine Duplikate eines Eintrags.
Gruß
Reinhard
AW: Collection oder Array nachträglich ohne Duplikate?
24.11.2008 19:02:00
Tino
Hallo,
hier mal ein Beispiel wie Du eine Area ohne doppelte Werte befüllen kannst,
beachte im Beispiel die zweite Schleife.
Sub Area_Fuellen_Ohne_doppelt() Dim meArea() Dim a As Integer For a = 1 To 10 Redim Preserve meArea(a) meArea(a) = "Hallo" & a Next a 'Area mit weiteren werten füllen ohne doppelte********************* For a = 1 To 20 If Not IsNumeric(Application.Match("Hallo" & a, meArea, 0)) Then Redim Preserve meArea(Ubound(meArea) + 1) meArea(Ubound(meArea)) = "Hallo" & a End If Next a '******************************************************************* For a = 1 To Ubound(meArea) Debug.Print meArea(a) Next a End Sub


Gruß Tino

Anzeige
AW: Collection oder Array nachträglich ohne Duplikate?
25.11.2008 12:11:43
Andreas
Hallo ransi, Reinhard und Tino,
schön von Euch zu hören. Das Herber Forum mit seinen Mannen ist einfach unschlagbar! Entschuldigt bitte auch meine späte Rückantwort. Das Erstellen einer vernünftigen Simulationsdatei für diesen Code hat länger gedauert als gedacht.
https://www.herber.de/bbs/user/57111.xls
Ich habe zwei Code Varianten drin. Einmal mit einem einfachen Add zur Collection. Der Wert der dort ausgelesenen Items, die – da sie nur Nullwerte enthalten – in der Pivot auf visible = false gesetzt werden sollen, beträgt 56.
Im zweiten Code läuft noch eine Schleife mit, die den „add“ Vorgang zur Collection regelt und die bisherigen Collection Werte durchläuft und so Duplikate verhindert. Die Anzahl der Items dort beträgt dann 41. Ich habe auch noch eine leere Tabelle (Tabelle2) eingefügt, auf der alle Items aufgelistet werden, inklusive Zählenwenn. Es ist klar ersichtlich, daß der Einfache Collection Code Duplikate mitliest. Das ist für mich insofern ein Widerspruch, als das ich nun schon zwei Mal gehört habe, eine Collection bei korrekter Benutzung keine Duplikate liefern sollte. Alles was ich dazu im Forum fand, bezog sich auf das Generieren einer Collection aus einem Range auf einem Tabellenblatt.
Hier werden die Werte ja anders generiert, oder?
Der Code als solches ist hoffentlich verständlich. Ich habe noch ein paar Kommentare reingeschrieben. In großen Pivottabellen sorgt die von ihm durchgeführte Nullwertunterdrückung für mehr Übersichtlichkeit. Hoffe, diese Idee kann Euch an der ein oder anderen Stelle auch mal nützen.
Ich frage mich abschließend nun, ob die von Euch geposteten Ideen, auch in dieser Konstellation verwandt werden können. An Tinos Beispiel tüftele ich schon, bekomme es aber nicht richtig adaptiert.
Und zweitens, warum die normale Collection Duplikate ausgibt?
Vielen Dank und Grüße, Andreas
PS: Damit der Code in Sachen Geschwindigkeit valide Vergleiche der verschiedenen Varianten erlaubt, müßte vermutlich der Datenbereich der Pivot erweitert werden. Das konnte ich aber nicht, wegen der 300 KB Beschränkung des Uploads. Bei meinen Versuchen hat sich gezeigt, daß die meiste Zeit im Code für das „austicken“ der Pivotitems drauf geht. Daher ist es sinnvoll, die Collection ohne Duplikate zu haben. Bei meinen Versuchen hatte ich z.T. 871 items (inkl. Duplikate) vs. 416 items (ohne Duplikate). Das hat die Geschwindigkeit schon beeinflußt.
Anzeige
AW: Collection oder Array nachträglich ohne Duplikate?
25.11.2008 13:23:00
Rudi
Hallo,
nur mal zu den Collections:
Eine Collection kann keine Duplikete bei den Schlüsseln haben, bei den Werten (Items) hingegen schon.
myCol.Add 1, "a"
myCol.Add 1, "b"
geht
myCol.add 1, "a"
myCol.Add 2, "a"
hingegen nicht.
Gruß
Rudi
AW: Collection oder Array nachträglich ohne Duplikate?
25.11.2008 15:57:00
Andreas
Hallo Rudi,
ich habe Deinem Post entsprechend angefangen mit key- Angaben in der Collection zu experimentieren, aber ich habe es nicht hinbekommen. In diversen Variationen. Der Debugger gab aus: "Dieser Schlüssel ist bereits einmem Element dieser Auflistung zugeordnet". Ich vermute ich habe das Prinzip der Keys noch nicht verstanden... Wenn dieser Key schon einmal zugeordnet ist, dann soll die Collection ihn doch kein zweites Mal annehmen, um Duplikate zu vermeiden.
Ich weiß nicht, wie ich Deine Anregung auf mein Beispiel übertragen kann? Ob es überhaupt geht. Wo kann ich eine Liste der möglichen Keys einsehen?
Kannst Du mir vielleicht ein paar mehr Hinweise geben, die mich dann zur Lösung führen? Ich weiß mit VBA Hilfe und Co. nicht weiter.
Vielen Dank Dir!
Grüße, Andreas
Anzeige
AW: Collection oder Array nachträglich ohne Duplikate?
25.11.2008 17:45:00
ransi
Hallo Andreas
Irgendwie habe ich das Problem (glaube ich) noch nicht verstanden.
Mit meinen Worten:
Suche in PivotSourceData!C4:C2024 nach allen Zellen 0,
liste alle Wertepaare aus A4:B2024 ohne Duplikate und summiere die zugehörigen Werte aus C4:C2024.
Wenn dem so ist, füge mal ein neues Blatt (Tabelle1) in deine Tabelle ein und starte diesen Code:
' **********************************************************************
' Modul: Modul1 Typ: Allgemeines Modul
' **********************************************************************

Option Explicit


Public Sub machs()
Dim arr As Variant
Dim L As Long
Dim Dic1
Dim K
Dim I
Dim Ziel As Variant
Dim Tmp As String
arr = Sheets("PivotSourceData").Range("A4:C10000")
Set Dic1 = CreateObject("Scripting.Dictionary")
'Unikate sammeln
For L = 1 To UBound(arr)
    If arr(L, 3) <> 0 Then
        Tmp = arr(L, 1) & "+++++" & arr(L, 2)
        Dic1(Tmp) = Dic1(Tmp) + arr(L, 3)
    End If
Next
K = Dic1.keys
I = Dic1.items
'Umschaufeln
Redim Ziel(1 To Dic1.Count, 1 To 3)
For L = 1 To Dic1.Count
    Ziel(L, 1) = Split(K(L - 1), "+++++")(0)
    Ziel(L, 2) = Split(K(L - 1), "+++++")(1)
    Ziel(L, 3) = I(L - 1)
Next
'Ausgeben
Sheets("Tabelle1").Range("a1").Resize(UBound(Ziel, 1), UBound(Ziel, 2)) = Ziel
End Sub

Sind das prinzipiell die gesuchten Daten ?
Wenn ja, eine kleine Sortierroutine und die mehrfachvorkommenden in Tabelle1!A:A löschen bekommen wir dann auch noch hin..
ransi
Anzeige
AW: Collection oder Array nachträglich ohne Duplikate?
25.11.2008 18:00:13
Andreas
Hallo Ransi,
nein, das ist es leider nicht. Es soll nichts auf irgendwelchen Ranges gearbeitet werden, sondern sich alles in den Elementen der Pivot bewegen. Mein Code geht durch alle Rows des DataBodyRange und guckt, wo Zeilen sind, die 0 sind, was ein Indiz dafür ist, daß das dazugehörige Item überhaupt keine Werte enthält, nach der abschließenden Verifizierung dieses Verdachtes, merkt sich der Code das Item und 'tickt' es aus (nimmt den Haken weg). Es wird nicht mit Ranges gearbeitet, bzw. nur mit PivotRanges.
Knackpunkt war die Frage wie ich eine Collection (oder auch ein Array) ohne Duplikate erstellen kann, welches sich die betreffenden Items merkt. Dabei kann man anscheinend über Keys arbeiten, was ich aber noch nicht hinbekommen habe, über eine Schleife vor der Collection.Add Passage (das läuft schon) oder mit der Idee von Tino, die ich aber auch noch nicht realisieren konnte.
Die von Dir schon im ersten Post erwähnte Dictionary habe ich in Deiner Versuchskonfiguration einmal über einen Range laufen lassen und ich war vom Speed begeistert. Ich bin froh über diesen Post und die Antwort allein schon wegen dieser neuen Methode, die ich bisher nicht kannte.
Bei diesem konkreten Problem jedoch muß sich alles innerhalb der Pivot abspielen.
Danke für Deinen komplexen Codevorschlag.
Viele Grüße, Andreas
Anzeige

14 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige