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

Tabellen zusammenführen

Tabellen zusammenführen
24.03.2019 12:00:10
Toni
Hallo liebe Forumsteilnehmer und Experten,
für meine heutige Problemstellung suche ich eine VBA-Lösung. Es werden 2 Tabellen ("Tabelle1" und "Tabelle2") in einer ("Tabelle1") zusammengeführt und alle Abweichungen mit "Treffer" in Spalte G gekennzeichnet.
Meine Errungenschaften sehen erst einmal so aus:
  • 
    Sub test()
    Dim arr1(), arr2(), lRow1 As Long, lRow2 As Long
    Dim WS1 As Worksheet, WS2 As Worksheet
    Set WS1 = ThisWorkbook.Worksheets("Tabelle1")
    Set WS2 = ThisWorkbook.Worksheets("Tabelle2")
    lRow1 = WS1.Cells(Rows.Count, 1).End(xlUp).Row
    lRow2 = WS2.Cells(Rows.Count, 1).End(xlUp).Row
    ReDim arr1(lRow1 - 1, 9) As Variant
    ReDim arr2(lRow2 - 1, 1) As Variant
    arr1 = WS1.Range("A1:I" & lRow1)
    arr2 = WS2.Range("A1:f" & lRow2)
    For i = 2 To UBound(arr1)
    For j = 2 To UBound(arr2)
    If arr1(i, 1) = arr2(j, 1) Then
    GoTo weiter
    End If
    Next j
    arr1(i, 7) = "Treffer"
    weiter:
    Next i
    For j = 2 To UBound(arr2)
    For i = 2 To UBound(arr1)
    If arr2(j, 1) = arr1(i, 1) Then
    GoTo weiter2
    End If
    Next i
    a = a + 1
    ReDim arr1(lRow - 1 + a, 9)
    For b = 1 To 6
    arr1(lRow - 1 + a, b) = arr2(j, b)
    Next b
    arr1(lRow - 1 + a, 7) = "Treffer2"
    weiter2:
    Next j
    WS1.Range("A1:I" & lRow1 + a).Value = arr1()
    End Sub
    

  • Im Tabellenblatt "Ziel" kann man sehen, wie "Tabelle1" aussehen soll, wenn denn das Makro machte, was ich mir von ihm wünschte. Könnt Ihr mir bitte sagen, woran es da noch hapert? Vielen lieben Dank schon jetzt für Eure Unterstützung!
    https://www.herber.de/bbs/user/128620.xlsx
    lGrüße
    Toni

    21
    Beiträge zum Forumthread
    Beiträge zu diesem Forumthread

    Betreff
    Datum
    Anwender
    Anzeige
    AW: Tabellen zusammenführen
    24.03.2019 14:45:26
    Günther
    Moin Toni,
    Zitat: "Könnt Ihr mir bitte sagen, woran es da noch hapert?"
    Nööö, und das liegt an 2 Dingen:
    1. bin ich der Meinung, dass ein GoTo ausschließlich für das ErrorHandling genutzt werden soll. Bei anderen Sprungmarken lese ich erst gar nicht weiter. Ist eine Macke von mir, ich weiß ...
    2. Ich löse so etwas (inzwischen) ohne eine einzige Zeile VBA. Stichwort: Power Query (2010/13) aka Daten | Abrufen und transformieren (2016/365).
    Zugegeben, auch das kostet Einarbeitung ist aber in vielen Fällen einfacher und auch schneller als VBA. Und hat noch diverse andere Vorteile ...
    Also lass deinen Forschergeist ein wenig schweifen, vergleiche abe auf jeden Fall meine Lösung mit deinem Wunsch. Und zugegeben, ich brauchte auch mehr als 1 Anlauf, obwohl ich einigermaßen gut mit Power Query umgehen kann. -> https://www.herber.de/bbs/user/128621.xlsx
    Ach ja, und ehe dich hier ein Jemand anblafft, dass in einer *.xlsx kein Code enthalten sein kann: ICH hätte eine *.xlsm oder *.xlsb NICHT herunter geladen, was auch für verschiedenen andere (vorsichtige) Helfer zutrifft.
    Gruß
    Günther
    Anzeige
    AW: Tabellen zusammenführen
    24.03.2019 15:50:28
    Toni
    Hallo Günther,
    danke (, dass du mir mit Deinem letzten Satz: wie man's macht, macht man's falsch ... Recht gibst und) für Deinen Lösungsvorschlag!!
    Das Makro wird allerdings in ein File integriert werden mit bereits zig bestehenden Routinen, die verschiedentlichst an die dortig vorhandene (und über die von mir nur ausschnittsweise veröffentlichte) Datenstruktur angreifen. Weswegen eine Umstellung auf PQ hier nicht in Frage kommt. Außerdem wäre das Problem, PQ im Unternehmen zu implementieren eine zu große Herausforderung, der sich die Sintflut (also die nach mir) dann stellen kann :).
    Trotzdem danke ich Dir für deinen Ansatz und hoffe, dass eventuell doch noch eine VBA-Lösung machbar ist.
    lG Toni!
    Anzeige
    offen gesetzt owT
    24.03.2019 15:51:17
    Toni
    Haken vergessen ...
    AW: offen gesetzt owT
    24.03.2019 16:44:20
    Werner
    Hallo Toni,
    teste mal:
    Option Explicit
    Public Sub Zusammen()
    Dim loLetzte As Long, loLetzteZiel As Long
    Application.ScreenUpdating = False
    With Worksheets("Tabelle1")
    loLetzte = .Cells(.Rows.Count, 1).End(xlUp).Row
    .Range(.Cells(1, 1), .Cells(loLetzte, 9)).Copy
    With Worksheets("Ziel")
    loLetzteZiel = .Cells(.Rows.Count, 1).End(xlUp).Offset(1).Row
    If .Cells(1, 1) = "" Then loLetzteZiel = 1
    .Cells(loLetzteZiel, 1).PasteSpecial Paste:=xlPasteAll
    Application.CutCopyMode = False
    End With
    End With
    With Worksheets("Tabelle2")
    loLetzte = .Cells(.Rows.Count, 1).End(xlUp).Row
    .Range(.Cells(2, 1), .Cells(loLetzte, 6)).Copy
    With Worksheets("Ziel")
    loLetzteZiel = .Cells(.Rows.Count, 1).End(xlUp).Offset(1).Row
    .Cells(loLetzteZiel, 1).PasteSpecial Paste:=xlPasteAll
    Application.CutCopyMode = False
    loLetzteZiel = .Cells(.Rows.Count, 1).End(xlUp).Row
    .Range("$A$1:$I$" & loLetzteZiel).RemoveDuplicates Columns:=1, Header:=xlYes
    loLetzteZiel = .Cells(.Rows.Count, 1).End(xlUp).Row
    .Range(.Cells(2, 7), .Cells(loLetzteZiel, 7)).FormulaLocal = _
    "=WENN(ZÄHLENWENNS(Tabelle1!A:A;Ziel!A2;Tabelle2!A:A;Ziel!A2)=1;"""";" _
    & "WENN(ISTZAHL(A2*1);""Treffer2"";""Treffer""))"
    .Range(.Cells(2, 7), .Cells(loLetzteZiel, 7)).Value = _
    .Range(.Cells(2, 7), .Cells(loLetzteZiel, 7)).Value
    End With
    End With
    End Sub
    
    Gruß Werner
    Anzeige
    AW: offen gesetzt owT
    24.03.2019 17:11:49
    Toni
    Hallo Werner, bitte entschuldige, ich habe Dir in dem anderen Ast geantwortet. lG Toni
    AW: Tabellen zusammenführen
    24.03.2019 16:16:32
    Daniel
    Hi
    sieht kompliziert aus.
    wenn es richtig ist, dass in Spalte A eine eindeutige identifikationsnummer steht, würde ich so vorgehen:
    1. beide Tabellen untereinander kopieren
    2. mit DATEN - DATENTOOLS - DUPLIKATE ENTFERNEN die doppelten Zeilen rausschmeißen
    3. mit ZählenWenns oder vergleich überprüfen, welche Werte in welcher Tabelle vorkommen.
    geht natürlich auch als Code:
    Sub test()
    Sheets("Tabelle1").UsedRange.Copy Sheets("Ziel").Cells(1, 1)
    Sheets("Tabelle2").UsedRange.Offset(1, 0).Copy Sheets("Ziel").Cells(1, 1).End(xlDown).Offset(1,  _
    0)
    With Sheets("Ziel").UsedRange
    .RemoveDuplicates 1, xlYes
    With .Columns(7)
    .FormulaR1C1 = "=CHOOSE(ISNUMBER(MATCH(RC[-6],Tabelle1!C[-6],0))*1+ISNUMBER(MATCH(RC[-6] _
    ,Tabelle2!C[-6],0))*2+1,"""",""Treffer1"",""Treffer2"","""")"
    .Formula = .Value
    End With
    End With
    End Sub
    
    aber wie gesagt, geprüft wird hier nur die Spalte A und und nicht, ob es Unterschiede in den anderen Spalten gibt.
    Gruß Daniel
    ps: bitte den Umbruch in der Codezeile entfernen. Dieser wird hier automatisch bei langen Codezeilen von der Forensoftware eingefügt, allerdings kann VBA damit nicht arbeiten, daher muss diese Codezeile in eine geschrieben werden.
    Anzeige
    sorry, hätte....
    24.03.2019 16:46:29
    Werner
    Hallo Daniel,
    ...wohl besser vorher nochmal aktualisiert.
    Gruß Werner
    @Daniel und Werner, ...
    24.03.2019 17:11:05
    Toni
    Hallo Daniel, Hallo Werner,
    Eure beide Lösungen funktionieren super!
    Allerdings, ich habe hier mit der Tabelle "Ziel" nur demonstrieren wollen, wie Tabelle1 nach dem Makro gerne aussehen sollte. Da Ihr beide das so gelesen habt, ist das nicht deutlich genug heraus gekommen. Nun könnte man ja von "Ziel" (oder einer anderen Hilfstabelle - wie auch immer) alles wieder zurückkopieren aber:
    Die Originaldatei hat bis zu 200 Spalten und 22000 Zeilen, weswegen ich den Array-Ansatz gewählt hatte. Das Hin- und Herschieben von Tabelle1 nach Ziel und dann wieder zurück nach Tabelle1 schien mir bei der Datenmenge etwas riskant.
    Was meint Ihr? Wird das Ganze damit zu langsam? Ich kann leider erst am Montag testen, wie die Performance dann tatsächlich ist.
    Also falls es einen Ansatz mit Array gibt, würde ich mich freuen (allein schon aus Interesse jetzt). Aber gangbar sind Eure beiden Lösungen in jedem Fall und dafür sage ich in jedem Fall schonmal großes DANKE!!!
    lG Toni
    Anzeige
    Kann bitte nochmal jmd. schauen, ob
    24.03.2019 20:50:58
    Toni
    es nicht vielleicht doch als Array-Lösung geht? Ich verstehe nicht, warum der Code so nicht funktioniert bzw. was fehlt noch?. Ich möchte später mit arr1() dann weiter arbeiten können.
    Danke und schöne Grüße
    Toni
    AW: Kann bitte nochmal jmd. schauen, ob
    25.03.2019 05:35:53
    Hajo_Zi
    Hallo Toni,
    das geht nicht, da eine XLSX Datei kein Makro enthalten kann.
    Ich sehe keinen Grund eine Datei 2x zu speichern. Ich führe keine Liste unter welchem Dateinamen ich die Datei gespeichert habe.
    In Deiner Datei ist Dein Makro auch nicht vorhanden.

    Beiträge von Werner, Luc, robert, J.O.Maximo und folgende lese ich nicht.
    Die Beiträge werden auch ignoriert, es erfolgt keine Antwort.
    Anzeige
    AW: XLSM auf Wunsch ...
    25.03.2019 16:33:10
    Hajo_Zi
    Hallo Toni
    Zeile 4 bis 23 ist mir klar.
    Warum ist Zeile 2 und 3 Treffer ohne Nummer
    Gruß Hajo
    AW: XLSM auf Wunsch ...
    25.03.2019 18:19:58
    Hajo_Zi
    Hallo Toni,
    man mus nicht Antworten. Das hat den Vorteil, man darf den Code selber an seine Bedingungen anpassenb.
    Option Explicit
    Sub test2()
    Dim lRow1 As Long, lRow2 As Long
    Dim WS1 As Worksheet, WS2 As Worksheet
    Dim RAFound1 As Range
    Dim I As Long
    Set WS1 = ThisWorkbook.Worksheets("Tabelle1")
    Set WS2 = ThisWorkbook.Worksheets("Tabelle2")
    lRow1 = IIf(IsEmpty(WS1.Cells(Rows.Count, 1)), WS1.Cells(Rows.Count, 1).End(xlUp).Row, WS1. _
    Rows.Count)
    lRow2 = IIf(IsEmpty(WS2.Cells(Rows.Count, 1)), WS2.Cells(Rows.Count, 1).End(xlUp).Row, WS2. _
    Rows.Count)
    ReDim arr1(lRow1 - 1, 9) As Variant
    ReDim arr2(lRow2 - 1, 1) As Variant
    For I = 2 To lRow1
    Set RAFound1 = WS2.Columns(1).Find(WS1.Cells(I, 1), WS1.Range("A" & Rows.Count),  _
    xlFormulas, _
    xlWhole, , xlNext)
    If RAFound1 Is Nothing Then
    WS1.Cells(I, 7) = "Treffer 1"
    End If
    Next I
    For I = 2 To lRow2
    Set RAFound1 = WS1.Columns(1).Find(WS2.Cells(I, 1), WS1.Range("A" & Rows.Count),  _
    xlFormulas, _
    xlWhole, , xlNext)
    If RAFound1 Is Nothing Then
    WS2.Rows(I).Copy WS1.Rows(lRow1 + 1)
    WS1.Cells(lRow1 + 1, 7) = "Treffer 2"
    lRow1 = lRow1 + 1
    End If
    Next I
    End Sub
    
    Gruß Hajo
    Anzeige
    AW: XLSM auf Wunsch ...
    25.03.2019 18:25:37
    Toni
    Hallo Hajo,
    bin gerade erst wieder an den Rechner gegangen, bin beide Lösungen gerade am durchgehen. Vielen Dank schonmal für Deinen Ansatz hier!!
    AW: XLSM auf Wunsch ...
    25.03.2019 19:33:37
    Toni
    Also Hajo, ich bin platt! Ich habe nichts gefunden, aber der Reihe nach:
    1. diese Konstruktion:
        lRow1 = IIf(IsEmpty(WS1.Cells(Rows.Count, 1)), WS1.Cells(Rows.Count, 1).End(xlUp).Row, WS1.  _
    _
    Rows.Count)
    

    du denkst sogar an die letzte Zelle ;), kannt ich so auch noch nicht, merke ich mir!
    2. dies hier:
            Set RAFound1 = WS2.Columns(1).Find(WS1.Cells(I, 1), WS1.Range("A" & Rows.Count), _
    xlFormulas, _
    xlWhole, , xlNext)
    
    habe ich wegen des zweiten WS1 vermutet, dass da ein WS2 kommen müsste. Da aber letzte Zelle immer leer sein wird, lass ich das. Auch xlFormulas hat er akzeptiert, hatte auch hier zunächst anders xlValues vermutet. Top, läuft durch
    3. dies:
    
    WS2.Rows(I).Copy WS1.Rows(lRow1 + 1)
    

    werde ich explizit auf die ersten 6 Spalten reduzieren ... ist aber absolut unerheblich.
    So: und nun frage ich mich: der Hajo baut doch eigentlich immer was ein, was habe ich übersehen ^^
    Also: ich unterstell jetzt einfach, dass das ne Unterstellung ist und bedanke mich vielmals, dass Du Dich der Sache noch angenommen hast!
    lG Toni!
    Anzeige
    AW: XLSM auf Wunsch ...
    25.03.2019 18:20:22
    Toni
    Hallo Hajo,
    Danke für Deine Antwort!
    ... weil der Schlüssel in Spalte A sowohl Text als auch Nummer sein kann. Und weil dieser Schlüssel in Zeile 2/3 von Tabelle1 in Tabelle2 nicht vorhanden ist.
    lG Toni
    AW: XLSM auf Wunsch ...
    25.03.2019 18:06:10
    Daniel
    HI
    deinen Code verstehe ich nicht.
    probier mal das hier.
    sollte auch mit deiner Datenmenge funktionieren:
    
    Sub test()
    Dim dic As Object
    Dim sh
    Dim arr
    Dim z As Long, x As Long
    Dim K
    Set dic = CreateObject("Scripting.dictionary")
    For Each sh In Array("Tabelle1", "Tabelle2")
    arr = Sheets(sh).UsedRange.Columns(1).Value
    x = x + 1
    For z = 2 To UBound(arr, 1)
    dic(arr(z, 1)) = dic(arr(z, 1)) + x
    Next
    Next
    For Each K In dic.Keys
    Select Case dic(K)
    Case 1: dic(K) = "Tabelle1"
    Case 2: dic(K) = "Tabelle2"
    Case 3: dic(K) = ""
    Case Else: dic(K) = "?"
    End Select
    Next
    Sheets("Tabelle2").UsedRange.Offset(1, 0).Copy
    With Sheets("Tabelle1")
    .Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).PasteSpecial xlPasteAll
    .UsedRange.RemoveDuplicates 1, xlYes
    With .Cells(1, 1).CurrentRegion
    arr = .Columns(1).Value
    arr(1, 1).Cells(1, 7).Value
    For z = 2 To UBound(arr, 1)
    arr(z, 1) = dic(arr(z, 1))
    Next
    .Columns(7).Value = arr
    End With
    End With
    End Sub
    
    gruß Daniel
    Anzeige
    AW: XLSM auf Wunsch ...
    25.03.2019 19:55:53
    Toni
    Hallo Daniel,
    wenn ich ehrlich bin, das hat mich wieder einiges an H-Schmalz gekostet! Immer denke ich, jetzt habe ich etwas, und dann kommt so eine Lösung um die Ecke - absolut baff bin ich!
    das fand ich schon toll: dic(arr(z, 1)) = dic(arr(z, 1)) + x
    hier habe ich was herausgenommen, aber: "aus der Tabelle, ins array, aus dem dictionary, ins array und zurück": einmal Achterbahn fahren bitte :), herrlich:
    With .Cells(1, 1).CurrentRegion
    arr = .Columns(1).Value
    '        arr(1, 1).Cells(1, 7).Value
    For z = 2 To UBound(arr, 1)
    arr(z, 1) = dic(arr(z, 1))
    Next
    .Columns(7).Value = arr
    End With
    
    warum bekommt arr hier kein redim und es funktioniert?
    Habe nun die Qual der Wahl und bin ausgesprochen erleichtert, dass ich da viel gelernt habe und in jedem Fall eine Lösung habe.
    VIELEN DAAAANK!!!
    lG Toni! Einen schönen Abend (auch an Hajo)!
    AW: XLSM auf Wunsch ...
    25.03.2019 23:39:58
    Daniel
    Hi
    naja, wenn du einer Variantvariable die Werte aus einem Zellbereich zuweist, macht VBA den Redim automatisch, die notwendige Größe lässt sich ja aus dem Zellbereich ableiten.
    Das geht auch, wenn die Variable bereits anderweitig verwendet wurde.
    anonsten
    arr(1, 1) = .Cells(1, 7).Value
    

    dann passt auch die Überschrift.
    Gruß Daniel
    Danke für die Info, lG Daniel... owT
    26.03.2019 00:25:46
    Toni
    Performance Nachtrag ...
    25.03.2019 21:19:21
    Toni
    Hallo Daniel,
    nach Tests mit mehreren Tsd Daten stellt sich die Dic-Variante als klar Schnellste heraus. Wusstest Du sicher schon, ist dann für die Weiten des Internets.
    Danke und viele Grüße!!

    Beliebteste Forumthreads (12 Monate)

    Anzeige

    Beliebteste Forumthreads (12 Monate)

    Anzeige
    Anzeige
    Anzeige