Liste ohne Dublikate aus einer Matrix

  • Excel

Es gibt 6 Antworten in diesem Thema. Der letzte Beitrag () ist von DaCapitalist.

    Liste ohne Dublikate aus einer Matrix

    Hallo zusammen!

    Ich bin leider VBA-Anfänger und konnte mir bisher nur einzelne Code-Schnipsel zusammen suchen und dann anpassen.
    Bei dieser Frage übersteigen die Anforderungen leider meinen Kenntnisstand.

    Ich versuche, aus einer externen Excel-Tabelle jede zweite Spalte innerhalb eines Bereiches ab inkl. Spalte G in ein Dictionary einzulesen und danach in der eigenen Tabelle ohne Duplikate untereinander auszugeben.

    Bei meinem Code gibt es allerdings einen Array-Fehler. Und auch sonst komme ich nicht weiter.

    Quellcode

    1. Sub Daten_holen()
    2. Dim i, r As Long
    3. Dim oDict As Object
    4. Set Source = GetObject(ActiveWorkbook.Worksheets("Optionen").Range("D16").Value) 'Pfad der Projekt-Liste in Zelle D16
    5. Set oDict = CreateObject("scripting.dictionary")
    6. Const intZ = 2 'Import ab Zeile 2 der Zieltabelle
    7. 'Idee: While-Schleife, um Dictionary erstmal mit allen Projekten zu füttern und Duplikate zu entfernen
    8. With Source.Worksheets("Assignment")
    9. For i = 7 To .Columns.Count Step 2
    10. For r = 5 To .Cells(Rows.Count, 1).End(xlUp).Row 'ab Zeile 5 (Überschrift weglassen)
    11. If Len(Trim(.Cells(r, i))) Then oDict(.Cells(r, i).Text) = "" 'Spalte 2
    12. Next r
    13. Next i
    14. End With
    15. ActiveWorkbook.Worksheets("Projektliste").Cells(intZ, 1).Resize(oDict.Count, 1) = Application.Transpose(oDict.keys)
    16. End Sub


    Es wäre klasse, wenn mir hier jemand helfen könnte.

    Vielen Dank!

    DaCapitalist schrieb:

    Bei meinem Code gibt es allerdings einen Array-Fehler
    Welche Zeile?

    Btw:
    Was ist ActiveWorkbook? Das, in dem der Code läuft?
    Oder ein Fremdes? Wenn ja, wie ist es geöffnet worden?

    ​Set Source = GetObject(ActiveWorkbook.Worksheets("Optionen").Range("D16").Value) 'Pfad der Projekt-Liste in Zelle D16
    ist eine äusserst merkwürdige Konstruktion und kann sicher wesentlich verbessert werden, wenn du die obigen Fragen beantwortet hast.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Danke für die schnelle Antwort!

    ActiveWorkbook ist das, aus dem der Code aufgerufen wurde. Dort drin liegt eine Zelle, die den Pfad zur externen Datei enthält (Damit man diesen später ohne coden ändern kann, wenn die Datei auf einen anderen Computer kopiert wird). Diese Zelle wird in deinem zweiten Zitat referenziert.
    Genau richtig. Es geht nur darum, die Datei irgendwo speichern zu können. Ohne, dass man einen bestimmten Pfad wählen muss, wenn man kein VBA beherrscht.

    Hier nochmal ein Update, welches auch korrekt durchläuft (wenn auch recht langsam).
    Es fehlt im Grunde nur noch die Dynamisierung des Dateipfades:

    Quellcode

    1. Sub Daten_holen()
    2. Dim i, r As Long
    3. Dim oDict_Names As Object 'Projektnamen
    4. Dim oDict_Numbers As Object 'Projektnummern
    5. 'Set Source = GetObject(ActiveWorkbook.Worksheets("Optionen").Range("D16").Value) 'Pfad der Projekt-Liste in Zelle D16
    6. Set oDict_Names = CreateObject("scripting.dictionary")
    7. Set oDict_Numbers = CreateObject("scripting.dictionary")
    8. 'Idee: While-Schleife, um Dictionary erstmal mit allen Projekten zu füttern und Duplikate zu entfernen
    9. 'Projektnamen sammeln
    10. 'With Source.Worksheets("Assignment")
    11. With Workbooks("Projektliste.xlsx").Worksheets("Assignment")
    12. For i = 7 To .Columns.Count Step 2
    13. For r = 5 To .Cells(Rows.Count, 1).End(xlUp).Row 'ab Zeile 5 (Überschrift weglassen)
    14. If (Not IsError(.Cells(r, i))) Then 'Bezugfehler überspringen
    15. If Len(Trim(.Cells(r, i))) Then oDict_Names(.Cells(r, i).Text) = "" 'Spalte
    16. End If
    17. Next r
    18. Next i
    19. End With
    20. 'Projektnummern sammeln
    21. 'With Source.Worksheets("Assignment")
    22. With Workbooks("Projektliste.xlsx").Worksheets("Assignment")
    23. For i = 8 To .Columns.Count Step 2
    24. For r = 5 To .Cells(Rows.Count, 1).End(xlUp).Row 'ab Zeile 5 (Überschrift weglassen)
    25. If (Not IsError(.Cells(r, i))) Then 'Bezugfehler überspringen
    26. If Len(Trim(.Cells(r, i))) Then oDict_Numbers(.Cells(r, i).Text) = "" 'Spalte
    27. End If
    28. Next r
    29. Next i
    30. End With
    31. 'Einfügen in Zeile 2 und Spalte 1 der Zieltabelle [NAMES]
    32. ActiveWorkbook.Worksheets("Projekte").Cells(2, 1).Resize(oDict_Names.Count, 1) = Application.Transpose(oDict_Names.keys)
    33. 'Einfügen in Zeile 2 und Spalte 2 der Zieltabelle [NUMBERS]
    34. ActiveWorkbook.Worksheets("Projekte").Cells(2, 2).Resize(oDict_Numbers.Count, 1) = Application.Transpose(oDict_Numbers.keys)
    35. End Sub

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „DaCapitalist“ ()

    ??
    Du hast ein Workbook "Projektliste.xlsx", aus dem du das Dictionary füllst und hast ein
    ActiveWorkbook, in dem der Code läuft und in das du speicherst.

    Das Projektliste-Workbook ist wohl schon offen?
    Zumindest sehe ich in deinem Code kein explizites Open.

    Mein Ansatz wäre da wahrscheinlich vom Grundansatz in etwa so:

    Visual Basic-Quellcode

    1. Set SourceWB = Workbook.Open("Projektliste.xlsx", ReadOnly :=True) 'besser mit Pfadangabe
    2. Set SourceWS = SourceWB.Worksheets("Assignment")
    3. With SourceWS
    4. ' fill dictionary
    5. End With
    6. Set DestWS = ThisWorkbook.Sheets("Projekte")
    7. ' write to DestWS


    Allerdings verstehe ich den Umweg über zwei Dictionaries nicht so richtig.
    Ein Dictionary beinhaltet normalerweise Wertepaare, von denen du nur eines füllst.
    Deine Gedankengänge überlasten mich.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Danke für die Antwort und sorry, dass meine etwas auf sich warten ließ.
    Ich habe zwischenzeitlich ein selbst ein wenig weitergeforscht und schaffe es mittlerweile, den Code weit fortlaufen zu lassen. Nun wird das Dictionary auch etwas mehr ausgenutzt.
    Bei einer weiteren Funktion in Zeile 103 gibt er mir aber jedes Mal einen Fehler aus, dass die Zuweisung ungültig ist - als würde er keinen Key aus dem Dict übergeben bekommen. Obwohl es ja vorher erfolgreich gefüllt wird. (Ich habe das mit der Konsolenausgabe bereits getestet)

    Kannst du damit etwas anfangen? Die For-each-Schleife wird nur wenig weiter oben ja exakt genauso definiert.

    Quellcode

    1. Sub Daten_holen()
    2. 'Variablen für Import von Projekten
    3. Dim i, r As Long
    4. Dim oDict_Numbers As Object 'Projektnummern
    5. Dim oDict_Berater As Object 'Projekt-/Berater-Verzeichnis
    6. Set oDict_Numbers = CreateObject("scripting.dictionary")
    7. 'Idee: While-Schleife, um Dictionary erstmal mit allen Projekten zu füttern und Duplikate zu entfernen
    8. 'Projektnummern und KW sammeln
    9. Debug.Print "Sammle Projektnummern und Kalenderwochen..."
    10. With Workbooks("Projektliste.xlsx").Worksheets("Assignment")
    11. For i = 8 To .Columns.Count Step 2
    12. For r = 5 To .Cells(Rows.Count, 1).End(xlUp).Row 'ab Zeile 5 (Überschrift weglassen)
    13. If (Not IsError(.Cells(r, i))) Then 'Bezugfehler überspringen
    14. 'Leere Zeilen ignorieren
    15. If Len(Trim(.Cells(r, i))) Then
    16. 'Checken, ob Wert in Dictionary vorhanden
    17. If oDict_Numbers.Exists(.Cells(r, i).Text) Then
    18. 'Checke ob Spaltennummer höher als der dict.Value zu dieser Projektnummer, dann schreibe Wert ins Dict
    19. If oDict_Numbers.Item(.Cells(r, i).Text) < i Then oDict_Numbers.Item(.Cells(r, i).Text) = i
    20. Else
    21. 'Zu Dictionary hinzufügen
    22. oDict_Numbers.Item(.Cells(r, i).Text) = i 'Spalte
    23. End If
    24. End If
    25. End If
    26. Next r
    27. Next i
    28. End With
    29. 'Berater und Rollen sammeln
    30. Berater_sammeln
    31. 'Einfügen in Zeile 2 und Spalte 1 der Zieltabelle [NAMES]
    32. 'ActiveWorkbook.Worksheets("Projekte").Cells(2, 1).Resize(oDict_Names.Count, 1) = Application.Transpose(oDict_Names.Keys)
    33. 'Einfügen in Zeile 2 und Spalte 2 der Zieltabelle [NUMBERS]
    34. 'ActiveWorkbook.Worksheets("Projekte").Cells(2, 2).Resize(oDict_Numbers.Count, 1) = Application.Transpose(oDict_Numbers.Keys)
    35. 'Projektnummern bereinigen und in Import-Sheet + KWs
    36. For Each strKey In oDict_Numbers.Keys()
    37. If Not IsNumeric(strKey) Then oDict_Numbers.Remove (strKey)
    38. Next
    39. ActiveWorkbook.Worksheets("Projekte_neu").Cells(2, 1).Resize(oDict_Numbers.Count, 1) = Application.Transpose(oDict_Numbers.Keys)
    40. ActiveWorkbook.Worksheets("Projekte_neu").Cells(2, 3).Resize(oDict_Numbers.Count, 1) = Application.Transpose(oDict_Numbers.Items)
    41. 'Berater-Liste für jedes Projekt erstellen #######################################################################################
    42. Set oDict_Berater = CloneDictionary(oDict_Numbers)
    43. With Workbooks("Projektliste.xlsx").Worksheets("Assignment")
    44. 'Kopiere Projektliste in ein neues Dictionary (Values werden später mit den Namenslisten ersetzt
    45. Debug.Print "Sammle Berater für Projekte..."
    46. For Each strKey In oDict_Berater.Keys
    47. Debug.Print "Lese Berater für: " & strKey
    48. 'Jedes Projekt bekommt eine Beraterliste (ggf. durch Array ersetzen)
    49. Set berater = CreateObject("scripting.dictionary")
    50. 'Für jeden Berater
    51. For r = 5 To .Cells(Rows.Count, 1).End(xlUp).Row
    52. 'Wenn Projektnummer in der Zeile des Beraters auftaucht, dann Beratername zu Dictionary hinzufügen
    53. For i = 8 To .Columns.Count Step 2 'dieses i läuft scheinbar bis über 4965, obwohl der gleiche Code oben korrekt funktioniert
    54. If i > 150 Then Exit For
    55. If .Cells(r, i).Text = strKey Then
    56. berater.Item(.Cells(r, 1).Text) = ""
    57. Debug.Print "Berater " & .Cells(r, 1).Text & " in Projekt " & strKey
    58. 'Raus aus der Schleife, wir brauchen nicht weiter zu suchen - Berater war dabei
    59. Exit For
    60. End If
    61. Next i
    62. Next r
    63. 'Berater-Liste in Dictionary speichern
    64. oDict_Berater.Key(strKey) = berater
    65. Next
    66. End With
    67. 'TODO: Berater-Liste in Spalten einfügen
    68. With ActiveWorkbook.Worksheets("Projekte_neu")
    69. Dim spalte As Integer
    70. spalte = 5
    71. 'Projektnummern-Spalte durchgehen und Projekt finden, dann Berater-Spalten füllen
    72. Debug.Print "Gebe Beraterlisten aus..."
    73. For Each strProjektnummer In oDict_Berater.Keys
    74. Debug.Print "Key: " & strProjektnummer
    75. For r = 2 To .Cells(Rows.Count, 1).End(xlUp).Row
    76. If r > 150 Then Exit For 'Vorerst nach 150 Zeilen abbrechen (Trotzdem: Warum erkennt er die letzte Zeile nicht selbst?)
    77. If .Cells(r, 1).Text = strProjektnummer Then 'Fehler: Ungültige Anzahl an Argumenten oder ungültige Zuweisung
    78. For Each strBerater In oDict_Berater.Item(strProjektnummer)
    79. .Cells(r, spalte).Text = strBerater
    80. spalte = spalte + 1
    81. Next
    82. 'Beginn Berater-Spalten zurücksetzen
    83. spalte = 5
    84. End If
    85. Next
    86. Next
    87. End With
    88. End Sub


    Kannst du / könnt ihr mir hier weiterhelfen?

    Vielen Dank vorab!