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

Tabellenblaetter vergleichen mit VBA

Tabellenblaetter vergleichen mit VBA
05.07.2018 21:34:50
Matto
Liebe Experten,
Ich baue seit einigen Tagen an einem Excel Dokument.
Nun habe ich ein Problem, bei dem ich einfach nicht weiterkomme. Die im Netz gefundenen Lösungen kann ich leider nicht ganz nachvollziehen und somit auch nicht adaptieren.
Vorinfo:
ich erstelle aus einem Blatt mit Rohdaten per VBA eine Arbeitsliste. Falls nach dem Erstellen der Arbeitsliste noch neue Rohdaten hinzu kommen, möchte ich diese gerne in die Arbeitsliste einpflegen, ohne die bisherigen Einträge zu verändern.
Idee:
Nun war mein Gedanke, dass ich einfach eine neue TemporäreArbeitsliste auf Basis der Rohdaten erstelle und anschließend beide Arbeitslisten vergleiche.
Gibt es neue Einträge sollen die Inhalte der jeweiligen Zeilen aus der TempArbeitsliste in die Arbeitsliste kopiert werden.
Sorry für die verwirrende Erklärung.
https://www.herber.de/bbs/user/122501.xlsx
Hier findet Ihr eine Beispieldatei, die das Prinzip erahnen lässt.
Ich brauch jetzt erstmal ein Bier.
Gruß
Mat

13
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Tabellenblaetter vergleichen mit VBA
06.07.2018 00:40:35
Barbaraa
Hallo Mat,
während Du ein Bier genießt, habe ich mich bemüht, Dir zu helfen. Probier mal dies:

Sub Matto0705()
Dim wsA         As Worksheet
Dim wsN         As Worksheet
Dim lAZeile     As Long
Dim lAZeileMax  As Long
Dim lNZeile     As Long
Dim lNZeileMax  As Long
Dim lNSpalteMax As Long
Dim lSpalte     As Long
Set wsA = Worksheets("ListeAlt")
Set wsN = Worksheets("ListeNeu")
lAZeileMax = wsA.Range("A1").CurrentRegion.Rows.Count
lNZeileMax = wsN.Range("A1").CurrentRegion.Rows.Count
lNSpalteMax = wsN.Range("A1").CurrentRegion.Columns.Count
For lNZeile = 2 To lNZeileMax
For lAZeile = 2 To lAZeileMax
For lSpalte = 1 To lNSpalteMax
If wsN.Cells(lNZeile, lSpalte)  wsA.Cells(lAZeile, lSpalte) Then Exit For
Next lSpalte
If lSpalte > lNSpalteMax Then Exit For
Next lAZeile
If lAZeile > lAZeileMax Then
wsN.Cells(lNZeile, lSpalte).Resize(1, lNSpalteMax).Copy _
wsA.Cells(lAZeileMax + 1, 1)
lAZeileMax = lAZeileMax + 1
End If
Next lNZeile
End Sub
Jede in ListeAlt nicht gefundene ListeNeu-Zeile wird angehängt. In Deinem konkreten Fall ist das die Zeile mit dem Monster-Truck.
ListeAlt-Zeilen, die in ListeNeu NICHT vorkommen, bleiben bestehen.
Warum verwendest Du nicht gleich die Begriffe der Beispieldatei? Du schreibst "Rohdaten", wenn Du "ListeNeu" meinst, und "Arbeitsliste", wenn Du "ListeAlt" meinst.
Wenn Du das nächste Mal hier ein Problem vorstellst, beziehe Dich bei der Erklärung bitte auf die Beispieldatei. Denn von der geht man aus, wenn man Dein Problem liest.
Wenn Du eine Lösung willst, dann mach statt einer "Beispieldatei, die das Prinzip erahnen lässt" eine solche, in der es möglich ist, eine Lösung zu erstellen.
Erfüllt mein Lösungsvorschlag Deine Erwartungen?
LGB
Anzeige
AW: Tabellenblaetter vergleichen mit VBA
06.07.2018 09:09:45
Matto
Hi Barbaraa,
Ganz groß! Vielen Dank für die Mühen.
Der Code funktioniert wunderbar und sieht gut aus.
Ich versuche es nachzuvollziehen:
Du beginnst in Zeile 2, erste Spalte und vergleichst die Werte beider Blätter.
Sind die Werte gleich, gehst Du zu Zeile 2, zweite Spalte usw.
Gibt es Unterschiede oder hast du bereits die letzte beschriebene Spalte erreicht,
gehst Du zur nächsten Zeile in ListeAlt, bis die letzte Zeile erreicht ist.
Dann kopierst du in der aktuellen Zeile der ListeNeu von Spalte 1 bis zur letzten zusammenhängend beschriebenen Spalte und fügst diese an die letzte Stelle der ListeAlt. Ja?
Hatte die vereinfachte Datei erstellt, da ich dachte, es sei daran gut nachzuvollziehen. Wollte nicht noch mehr Verwirrung stiften.
Im Original ist es so, dass ich eine Rohdatenliste hab mit sehr vielen Datensätzen. Anhand von Eintragungen in einer Auswahlspalte übernehme ich die Inhalte der jeweiligen Zeilen aus der Rohdatenliste in ein anderes Tabellenblatt - ListeAlt.
Werden nun in den Rohdaten noch andere Zeilen markiert, erstelle ich über ein anderes Makro die ListeNeu. Diese dient dann nur als Vergleichsobjekt.
Ich werde jetzt ein wenig rumexperimentieren.
Vielen Dank!
Anzeige
AW: Tabellenblaetter vergleichen mit VBA
06.07.2018 11:45:12
Bernd
Servus Matto,
für diese Aufgabenstellung kann ich auch empfehlen dich in
Application.Match

einzulesen. Gerade wenn die Zeilenanzahl mal über 50-100 hinausgeht wird dir
Application.Match

schneller Ergebnisse liefern können.
Grüße, Bernd
AW: Tabellenblaetter vergleichen mit VBA
06.07.2018 12:54:07
Matto
Danke Dir für den Hinweis.
Ich werde mich mal einlesen.
AW: Tabellenblaetter vergleichen mit VBA
06.07.2018 11:56:50
Barbara
Der Ablauf ist so:
Eine Zeile von Neu wird mit jeder Zeile von Alt verglichen, solange bis Gleichheit gefunden wird.
Gleichheit zweier Zeilen liegt vor, wenn beim Vergleich der einzelnen Zellen dieser Zeilen
For lSpalte = 1 To lNSpalteMax

keine Ungleichheit entdeckt wird.
Falls doch, wird der Vergleich der einzelnen Zellen abgebrochen (

If wsN.Cells ... Then Exit For
) und die nächste Alt-Zeile kommt dran (Next lAZeile).
Falls nicht, wird abgebrochen (

If lSpalte > lNSpalteMax Then Exit For
).
Danach wird untersucht, ob gleiche Zeilen gefunden oder alle Alt-Zeilen erfolglos durchsucht wurden.
Falls Zweiteres (

If lAZeile > lAZeileMax Then
), wird die neue Zeile in den Altbestand kopiert.
Dann kommt die nächste Neu-Zeile dran (Next lNZeile)
Viel Erfolg beim rumexperimentieren.
LGB
Anzeige
AW: Tabellenblaetter vergleichen mit VBA
06.07.2018 12:53:21
Matto
Danke für die detaillierte Erklärung.
Eine Sache ist mir jetzt aufgefallen.
Wenn mehrere neue Einträge in ListeNeu dazu kommen, zerhauts mir in ListeAlt die Formatierung.
AW: Tabellenblaetter vergleichen mit VBA
06.07.2018 13:08:19
Barbara
Kannst Du das etwas konkretisieren? Kannst Du den Fehler weiter eingrenzen?
Weisst Du, ob die Formatierung mitkopiert wird, oder nur der Zellinhalt?
Bist Du sicher, dass dieses Formatierungsproblem entsteht, weil mehrere neue Einträge dazukommen?
Hat das vielleicht mit der bestehenden Formatierung der Zellen weiter unten etwas zu tun?
Falls Du diese Fragen nicht beantworten kannst, sag, wo Du hängst.
LGB
Anzeige
AW: Tabellenblaetter vergleichen mit VBA
06.07.2018 14:25:49
Matto
Hallo Barbaraa,
Danke fürs Dranbleiben!
Also ich habs noch nicht ganz durchdrungen, aber beschreibe nochmal detaillierter, was passiert.
Ich beziehe mich auf die Beispieldatei:
In ListeNeu werden am Ende zwei Zeilen ergänzt:
grün|2|201|Fahrrad|15
grün|2|202|Auto|20
Es gibt also insgesamt drei Zeilen, welche sich zu ListeAlt unterscheiden.
Wenn nun das Makro ausgeführt wird, sind in der letzten Zeile von ListeAlt die Einträge verschoben.
der Eintrag lautet:
202|Auto|20| und nicht grün|2|202|Auto|20
Zusatzwunsch:
Ist es möglich, dass die Einträge in ListeAlt anschließend gleich sortiert werden?
Ich stelle es mir so vor, dass die erste Bündelung über die Einträge in Spalte A geschieht. Anschließend wird nach Artikelnummer in Zeile C sortiert. Wenn man nicht nach Texten sortieren kann, kann ich in Zeile A auch gerne Nummern Zahlen verwenden.
Danke und viele Grüße
Mat
Anzeige
AW: Tabellenblaetter vergleichen mit VBA
06.07.2018 18:49:59
Barbaraa
@ Bernd:
Meiner Meinung nach kann hier Application.Match nicht sinnvoll angewendet werden, denn es wird ja Zelle A mit Zelle 1, Zelle B mit Zelle 2, Zelle C mit Zelle 3 usw. verglichen und nicht Zelle A mit den Zellen 1, 2, 3.
Oder habe ich da was nicht verstanden?
@ Matto:
Hatte einen kleinen Fehler in
wsN.Cells(lNZeile, lSpalte).Resize(1, lNSpalteMax).Copy
Den habe ich ausgebessert. Der Code sieht nun so aus:
Sub Matto0706()
Dim wsA         As Worksheet
Dim wsN         As Worksheet
Dim lAZeile     As Long
Dim lAZeileMax  As Long
Dim lNZeile     As Long
Dim lNZeileMax  As Long
Dim lNSpalteMax As Long
Dim lSpalte     As Long
Set wsA = Worksheets("ListeAlt")
Set wsN = Worksheets("ListeNeu")
lAZeileMax = wsA.Range("A1").CurrentRegion.Rows.Count
lNZeileMax = wsN.Range("A1").CurrentRegion.Rows.Count
lNSpalteMax = wsN.Range("A1").CurrentRegion.Columns.Count
For lNZeile = 2 To lNZeileMax
For lAZeile = 2 To lAZeileMax
For lSpalte = 1 To lNSpalteMax
If wsN.Cells(lNZeile, lSpalte)  wsA.Cells(lAZeile, lSpalte) Then Exit For
Next lSpalte
If lSpalte > lNSpalteMax Then Exit For
Next lAZeile
If lAZeile > lAZeileMax Then
wsN.Cells(lNZeile, 1).Resize(1, lNSpalteMax).Copy _
wsA.Cells(lAZeileMax + 1, 1)
lAZeileMax = lAZeileMax + 1
End If
Next lNZeile
With wsA.Range("A1").CurrentRegion
.Sort Header:=xlYes, _
key1:=.Range("A1"), order1:=xlAscending, _
key2:=.Range("C1"), order2:=xlAscending
End With
End Sub
Am Schluss wird nach Spalte A und C sortiert.
Noch ein Tipp, wenn man händisch schnell nach mehreren Kriterien sortieren will:
Stelle Dich in eine Zelle der Sortierspalte C. Nicht mehrere Zellen markieren, sonst wird nur in diesem Bereich sortiert!
Menü Start, ganz rechts "Sortieren und Filtern", "Nach Größe sortieren".
Dann gehe in eine Zelle in Spalte A, dann "Nach Größe sortieren".
Der Trick ist, dass Du in umgekehrter Spaltenreihenfolge, also erst C, dann A, sortierst.
Das geht schneller als "Benutzerdefiniertes Sortieren", wo man mühevoll die Sortierspalten eingibt.
OK?
LGB
Anzeige
AW: Tabellenblaetter vergleichen mit VBA
07.07.2018 12:38:56
Matto
Hallo Barbaraa,
ich hatte es heute nacht kurz ausproboiert und es funktionierte hervorragend. :)
Danke für die Tipps. Das bringt mich weiter.
Ich werde Montag mit meiner Tabelle noch ein bissl rumexperimentieren und mich nochmal melden, falls ich Verständnisfragen habe.
Also vielen vielen Dank für Deinen unermüdlichen Einsatz.
Schönes Wochenende!
Gruß
Mat
AW: Tabellenblaetter vergleichen mit VBA
09.07.2018 10:55:14
Matto
Guten Morgen,
es funktioniert wunderbar. :-)
In meinem Dokument war die erste Zeile leer. Daher wurde der Kopf beim Sortieren immer mit sortiert. Nachdem ich die Leerzeile gelöscht habe, ist aber alles bestens.
Ich habe dennoch ein paar Verständnisfragen.
Wozu dient das "Resize" genau?
Könnte ich statt
wsN.Cells(lNZeile, 1).Resize(1, lNSpalteMax).Copy auch
wsN.Range("A" & lNZeile ":" lNspalteMax & "1").Copy schreiben?

Gibt es eine Faustregel, wann ich besser "Cells" und wann besser "Range" verwenden sollte?

Ich habe beim ansprechen von Zellen meist Range verwendet.
Zusatzwunsch:
Ist es möglich, dass beim Listenvergleich auch berücksichtigt wird, dass wenn aus der neuen Liste Einträge gelöscht wurden, diese auch in der alten gelöscht werden?
Ist aber wirklich als Zusatzwunsch zu verstehen und nicht sooo wichtig.
Nochmals Danke und viele Grüße
Mat
Anzeige
AW: Tabellenblaetter vergleichen mit VBA
09.07.2018 19:20:26
Barbaraa
Hi Mat,
"Wozu dient das "Resize" genau?"
Ich will den Bereich, der die Zeile Nummer lNZeile, von der ersten bis zur letzten Zelle umfasst, erstellen.
Experimentiere selbst:
Setze an der Stelle mit Resize eine Stopp-Marke und starte das Makro. Es hält dann ebenda an.
Öffne im Codefenster das Direktfenster (mit Strg+G) oder im Menü Ansicht.
Wenn Du zB wissen willst, was in diesem Moment lNZeile ist, mach im Direktfenster ?lNZeile und Enter. Wichtig ist das Fragezeichen zu Beginn. Die zahl für lNZeile wird darunter angezeigt.
Oder wenn Du einen Range sehen willst, mach zB wsN.Cells(lNZeile, 1).Resize(1, lNSpalteMax).select und Enter.
Wichtig ist hier, dass zu Beginn KEIN Fragezeichen steht, aber am Schluss .select. Jetzt ist der Range markiert. Oder es kommt eine Fehlermeldung, wenn das zugehörige Sheet NICHT aktiviert ist.
Das Direktfenster ist recht praktisch und für mich ein wertvolles Instrument.
Zur Beantwortung Deiner Frage, ob man wsN.Range("A" & lNZeile ":" lNspalteMax & "1").Copy schreiben kann. Nein, kann man nicht. Oder funktioniert es bei Dir? Untersuche erst mal im Direktfenster wsN.Range("A" & lNZeile ":" lNspalteMax & "1").select
Das geht nicht. Warum?
Jetzt untersuche den Inhalt der Klammer: ?"A" & lNZeile ":" lNspalteMax & "1" (wieder mit einem Fragezeichenzu Beginn und Du siehst, dass da für Range kein geeigneter Ausdruck rauskommt.
Die Spalte liegt als Zahl vor, nicht als Buchstabe. Also muss man was anderes finden:
Die erste Zelle der gewünschten Zeile ist wsN.Cells(lNZeile, 1). Diese erweitere ich nun hinunter nicht (es bleibt also bei einer Zeile), und nach rechts auf lNSpalteMax Zellen. Diese Erweiterung des Ranges erfolgt also mit .Resize(1, lNSpalteMax)
Woher ich das weiß? Weil ich mal im Code-Editor den Cursor mitten in "Resize" gestellt und dann F1 gedrückt habe. Du kannst auch nach "Excel vba resize" gugln. Wenn Du deutsche Suchergebnisse bevorzugst, schreib zB "funktioniert nicht" dazu.
Damit ist der gewünschte Range erstellt, der dann zu kopieren ist.
"Ich habe beim ansprechen von Zellen meist Range verwendet."
Ich glaube, das sind grammatikalische Nuancen, die andere besser beantworten können. Ich habe jedenfalls herausgefunden, dass beides geht.
Und ich habe was noch schnelleres herausgefunden: Statt Set wsA = Worksheets("ListeAlt") kann man Set rAlt = Worksheets("ListeAlt").Cells schreiben. Man muss allerdings zu Beginn rAlt als Range (und nicht als Worksheet) deklarieren.
Die Zelle E2 ist dann einfach rAlt(2,5) statt wsA.cells(2,5)
Zu Deinem nicht so wichtigen Zusatzwunsch:
Wenn ich das richtig verstehe, ist dann das Ergebnis, dass in ListeAlt dasselbe steht wie in ListeNeu.
Wenn das so ist, dann kannst Du Dir das Ganze sparen und gleich die ListeNeu rüber kopieren.
Viel Spass beim Experimentieren.
LGB
Anzeige
AW: Tabellenblaetter vergleichen mit VBA
09.07.2018 20:24:44
Matto
Hi Barbaraa,
das Direktfenster werde ich mir vornehmen.
Die Zusatzwunschsache ist nicht so einfach. In meiner Tabelle sind die Einträge Arbeitsaufträge. Ich habe ich mehrere Spalten, in denen Eintragungen gemacht werden. Daher kann ich die neu erstellte Tabelle nicht einfach kopieren.
Beste Grüße
Mat

301 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige