Dieses Forum nutzt Cookies
Dieses Forum verwendet Cookies, um deine Login-Informationen zu speichern, wenn du registriert bist, und deinen letzten Besuch, wenn du es nicht bist. Cookies sind kleine Textdokumente, die auf deinem Computer gespeichert werden. Die von diesem Forum gesetzten Cookies werden nur auf dieser Website verwendet und stellen kein Sicherheitsrisiko dar. Cookies aus diesem Forum speichern auch die spezifischen Themen, die du gelesen hast und wann du zum letzten Mal gelesen hast. Bitte bestätige, ob du diese Cookies akzeptierst oder ablehnst.

Ein Cookie wird in deinem Browser unabhängig von der Wahl gespeichert, um zu verhindern, dass dir diese Frage erneut gestellt wird. Du kannst deine Cookie-Einstellungen jederzeit über den Link in der Fußzeile ändern.

VBA Makro Zwei Tabellen vergleichen und Änderungen übernehmen
#1
Liebe Community,

ich würde mich über Hilfe und Ideen freuen, für folgendes Problem:

Jede Woche bekomme ich eine neue Excel Tabelle mit gleichen Spaltenaufbau und unterschiedlichen Inhalten.

Die Aufgabe ist es, zwei Sheets zu vergleichen und wenn sich für bestimmte Ereignisse die Daten geändert haben, diese in einem dritten Sheet wiederzugeben und die alten Daten neben die neuen zu setzen. Hierfür habe ich eine Exceldatei vorbereitet (siehe Anhang).

Mein Ziel ist es, dies mittels Makro zu tun und per Knopfdruck das erste Sheet auszufüllen.
Problem bei der Sache ist, dass sich die Zeilen ändern können! Das bedeutet, dass man für jedes bestimmte Ereignis (Name) die jeweiligen Daten heraussuchen muss.

Somit sollte die einzige konstante der Name sein...

Doch was passiert, wenn sich der Name ändert (teile des Namens) oder neue hinzukommen?


LG Flo


Angehängte Dateien
.xlsx   Strukturplan_Änderung_Forumversion - Kopie.xlsx (Größe: 119,5 KB / Downloads: 9)
Antworten Top
#2
Hallo Flo,

anbei deine Datei mit Makro zurück. Ich nehme an das die Lösung so richtig sein wird.  Rückmeldung waere nett.  In Zeile D9 steht "Start Ende", hat mich anfangs von der Logik verwirrt. Ich nehme an es muss "Start veraltet" heissen.

Die Zellen in "Änderungen zur Vorwoche" müssen noch auf Datum formatiert werden. Ich kopiere nur die Werte, ohne Formate. Sollte der Löschbereich in der Const Anweisung "B10;K58" nicht ausreichen bitte von Hand abaendern. 

mfg  Gast  123


Angehängte Dateien
.xlsm   Strukturplan_Änderung_Forumversion - F.xlsm (Größe: 128,58 KB / Downloads: 26)
[-] Folgende(r) 1 Nutzer sagt Danke an Gast 123 für diesen Beitrag:
  • Exceljunge
Antworten Top
#3
Hallo Gast123 :D

Vielen Dank für deine Hilfe! Funktioniert soweit super...

jedoch habe ich eine Frage:
Er gibt ALLE Daten in der Zieltabelle aus, nicht nur diese, bei der sich das Datum geändert hat.. Ist es möglich nur die auszugeben, die sich im Datum beispielsweise "Ende" unterscheiden?


LG
Antworten Top
#4
So habe jetzt nochmal ein wenig rumgespielt und einige Fragen :)


Sub Tabellen_vergliechen()
Dim Tb1 As Object, Tb2 As Object, Tb3 As Object
Dim AC As Object, rFind As Object, asw As String
Dim lz2 As Long, lz3 As Long, lz As Long, z As Long
Set Tb1 = Worksheets("Änderungen zur Vorwoche")
Set Tb2 = Worksheets("Strukturplan Aktuell")
Set Tb3 = Worksheets("Strukturplan Veraltet")
    lz = Cells.Rows.Count 'LastZell suchen
    lz2 = Tb2.Cells(lz, 2).End(xlUp).Row
    lz3 = Tb3.Cells(lz, 2).End(xlUp).Row
    z = 10 '1. Zeile in Änderungen  B10
      
    'alte Tabelle löschen
    'Tb3.Range(ClrBer).ClearContents  Das habe ich nicht ganz verstanden und rausgenommen, müsste doch eigl Tb1.Range.....ClearContents heißen oder? Da sonst die Tabelle gelöscht wird, die ich ja eigentlich vergleichen wollte mit der neuen.
   
For Each AC In Tb2.Range("B4:B" & lz2)
    asw = "Nein"   'Auswerten Ja/Nein (Empty)
    Set rFind = Tb3.Range("B4:B" & lz).Find(What:=AC, After:=Range("B4"), LookIn:=xlFormulas, _
        LookAt:=xlWhole, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
    If rFind Is Nothing Then Cells(AC.Row, 3) = "No": GoTo weiter       Den Block verstehe ich leider nicht ganz, bin noch ein Excel Anfänger..muss ich mich noch etwas tiefgründiger mit befassen.
    'wenn Name gefunden Datum vergleichen  (über ElseÝf)
    'bei -gleichem- Datum "tue nichts", ElseÝf ausführen
  '  If rFind.Offset(0, 3) <> AC.Offset(0, 3) Then asw = ""  'Start       Habe ich erstmal rausgenommen, weil ich nun doch nur Ende (Veraltet) und Ende (aktuell) miteinander vergleiche

    If rFind.Offset(0, 4) <> AC.Offset(0, 4) Then asw = ""  'Ende

    'If rFind.Offset(0, 7) <> AC.Offset(0, 7) Then asw = ""  'Bas-Start
    'If rFind.Offset(0, 8) <> AC.Offset(0, 7) Then asw = ""  'Bas-Ende
    'wenn asw Empty Zeile kopieren
    If asw = Empty Then
       Tb1.Cells(z, 2) = AC.Offset(0, -1)     'ZNr
       Tb1.Cells(z, 3) = AC.Offset(0, 0)      'Name
      
     '  Tb1.Cells(z, 4) = rFind.Offset(0, 3)   'Start veraltet
       Tb1.Cells(z, 4) = rFind.Offset(0, 4)   'Ende veraltet
      ' Tb1.Cells(z, 6) = rFind.Offset(0, 7)   'Ba-Start veraltet
      ' Tb1.Cells(z, 7) = rFind.Offset(0, 7)   'Ba-Ende veraltet
        
      ' Tb1.Cells(z, 8) = AC.Offset(0, 3)      'Start
       Tb1.Cells(z, 5) = AC.Offset(0, 4)      'Ende
      ' Tb1.Cells(z, 10) = AC.Offset(0, 7)     'Ba-Start
      ' Tb1.Cells(z, 11) = AC.Offset(0, 7)     'Ba-Ende
       Tb1.Cells(z, 6) = AC.Offset(0, 6)     'Status
         z = z + 1 'next Zeile
    End If
weiter:
Next AC
End Sub


Ich würde das:

    If rFind.Offset(0, 4) <> AC.Offset(0, 4) Then asw = ""  'Ende

gerne verfeinern und nur zeilen vergleichen, die im Status nicht geschlossen sind.. hätte es so versucht:

    If rFind.Offset(0, 4) <> AC.Offset(0, 4) & rFind.Offset(0,6) <> "Geschlossen" Then asw = ""  'Ende

aber dann hat er mir immer ALLE ausgeworfen und ich hatte 1000 Einträge in meiner Zieltabelle.
Antworten Top
#5
Hallo,

zu deinen Fragen vorab einige Antworten, den Rest muss ich mir im Makro ansehen.
Zur 1. Frage:  das Löschen bezieiht sich auf den farblich markierten Bereich in der Tabelle "Änderungen zur Vorwoche". Weil ich nicht wusste ob sich der Bereich in der Länge verändern kann habe ich diesen Bereich oben als Const deklariert. Dort kannst du ihn von Hand ändern. Bei Programmierern ist die Methode Adressen so festzulegen gebräuchlich. Dann braucht man nicht im Makro suchen, sondern ändert es oben 

Ich bin davon ausgegangen das der Vergleich nur in den Tabellen "Aktuell" und "Veraltet" durchgeführt werden soll, und diie alte Liste  "Änderungen zur Vorwoche" somit immer gelöscht werden muss.  Ist das falsch ???

If rFind Is Nothing heisst konkret, es wurden keine Daten gefunden, und Goto weiter heisst, überspringe den Makroteil! Die gesamte Auswertung wird damit übersprungen. Das Gegenstück heisst.  "If Not rFind Is Nothing", wobei man sich als Neuling an den Begriff "Not rFind is Nothing" als "Wahr", ein Wert wurde gefunden, erst gewöhnen muss.  

Ich verweise dich auf den Anfang der For Next Schleife und den 1. Befehlt asw = "Nein",das  heist, keine Auswertung! Diese Variable wird gelöscht, wenn Auswertung erfolgen soll. Wenn du diese Löschungen annullierst kann ich nicht genau sagen was das Makro dann macht.  Ob es noch korrekt ablaeuft?? Muss ich mir in Ruhe ansehen.

Unter Strich ist es aber nicht schlecht mal damit zu spielen.  Mein Tipp:  dazu bitt die Daten aus der Original Datei in mein Beispiel kopieren und dann experimentieren.  Gefährlich bei Makros ist das falsche Befehle Daten löschen können.  Ich arbeite trotz 20 Jahre programmieren beim Entwickeln nie in einer Original Datei. Ich habe mir schon zuviele selbst zerschossen.  Dann arbeitet man beim Entwickeln immer in einer Test Datei. 

Solltest du dir als VBA Neuling konsequent angewöhnen!

mfg  Gast 123
Antworten Top
#6
Hallo Flo,

anbei das geänderte Makro, jetzt müsste es laufen.  Ich entschuldige mich, es war ein dummer Flüchtigkeitsfehler drin, den ich nicht bemerkt habe weil im Beispiel nur 9 Zeilen mit Daten ausgefüllt sind.  Ich wollte logischerweise die alten Daten in Tabelle  "Änderungen zur Vorwoche" löschen, was sicher auch korrekt ist.  Schreibt man im Makro aber für Tabelle 1 den Befehl:  Tb3.Range().ClearContents, dann löscht man in Tabelle 3 und nicht in Tabelle1.  Im Beispiel standen in Tabelle3 ab Zeile 10  -keine- Daten, deshalb ist mir der Fehler nicht aufgefallen. Und Excel fährt sturheil den Code so ab wie er ist!! 

Die Auswertung habe ich vorsichtshalber mit vier Variablen für DAtum geändert.  Jetzt sollte es perfekt laufen.

mfg  Gast 123

Code:
Option Explicit      '21.10.2016   Gast 123  Clever Forum
'3 Start E5, 4 Ende F6, 7-Start I9, 8-Ende J10   (Offset)

Dim Start As Date, Ende As Date     'neu eingefügt statt asw Variable
Dim BStart As Date, BEnde As Date   'Vergleich geaendert  24.10.2016

Const ClrBer = "B10:K58"   'Löschbereich in Tabelle "Änderungen"



Sub Tabellen_vergliechen()
Dim Tb1 As Object, Tb2 As Object, Tb3 As Object
Dim AC As Object, rFind As Object, z As Long
Dim lz2 As Long, lz3 As Long, lz As Long
Set Tb1 = Worksheets("Änderungen zur Vorwoche")
Set Tb2 = Worksheets("Strukturplan Aktuell")
Set Tb3 = Worksheets("Strukturplan Veraltet")
   lz = Cells.Rows.Count 'LastZell suchen
   lz2 = Tb2.Cells(lz, 2).End(xlUp).Row
   lz3 = Tb3.Cells(lz, 2).End(xlUp).Row
   z = 10 '1. Zeile in Änderungen  B10
     
   'alte Änderungen Tabelle löschen
   Tb1.Range(ClrBer).ClearContents    '(korrigiert)

For Each AC In Tb2.Range("B4:B" & lz2)
   Set rFind = Tb3.Range("B4:B" & lz).Find(What:=AC, After:=Range("B4"), LookIn:=xlFormulas, _
       LookAt:=xlWhole, SearchDirection:=xlNext, MatchCase:=False, SearchFormat:=False)
   
   'falls gewünscht Fehlermeldung in Spalte C wenn Name nicht gefunden wird
   'If rFind Is Nothing Then Cells(AC.Row, "C") = "No"  'Name nicht gefunden!
   If rFind Is Nothing Then GoTo weiter

   'alle Datum Variable laden
   Start = AC.Offset(0, 3)
   Ende = AC.Offset(0, 4)
   BStart = rFind.Offset(0, 3)
   BEnde = rFind.Offset(0, 4)
   
   'wenn Name gefunden Datum vergleichen  (über Elseİf)
   'bei -ungleichem- Datum aktive Zeile auflisten
   If BStart <> Start Or BEnde <> Ende Then
      Tb1.Cells(z, 2) = AC.Offset(0, -1)     'ZNr
      Tb1.Cells(z, 3) = AC.Offset(0, 0)      'Name
     
      Tb1.Cells(z, 4) = rFind.Offset(0, 3)   'Start veraltet
      Tb1.Cells(z, 5) = rFind.Offset(0, 4)   'Ende veraltet
      Tb1.Cells(z, 6) = rFind.Offset(0, 7)   'Ba-Start veraltet
      Tb1.Cells(z, 7) = rFind.Offset(0, 7)   'Ba-Ende veraltet
       
      Tb1.Cells(z, 8) = AC.Offset(0, 3)      'Start
      Tb1.Cells(z, 9) = AC.Offset(0, 4)      'Ende
      Tb1.Cells(z, 10) = AC.Offset(0, 7)     'Ba-Start
      Tb1.Cells(z, 11) = AC.Offset(0, 7)     'Ba-Ende
        z = z + 1 'next Zeile
   End If
weiter:
Next AC
End Sub
Antworten Top
#7
Läuft alles perfekt durch, vielen Dank für deine Hilfe!

Ist allerdings alles etwas kniffliger, als ich dachte...

Die Tabellen, die ich Vergleiche, haben jeweils 1000 Einträge - es ist ein Art Ordnerstrukturplan mit mehreren Hierarchieebenen. Problem hier ist, dass Namen doppelt belegt werden und das Makro den ersten gefundenen Namen in der alten Tabelle nimmt und das dazugehörige Datum... zusätzlich ändert sich die ZNr. wenn jemand eine neue Datei im Ordner erstellt.. also ist diese auch nicht konstant.

Was vielleicht helfen könnte, wäre ein Befehl, der Namen ausschließt, die öfter als 2mal vorkommen - geht das ? Weil diese sind teilweise nicht relevant.
Zusätzlich sind nur Daten wichtig, bei denen kein Start Datum existiert. Also wollte ich die If Bedingung etwas umschreiben.. daran arbeite ich grade etwas und fuchse mich dadurch!

Was bedeutet Option Explicit? :D

Code:
Option Explicit      '21.10.2016   Gast 123  Clever Forum
'3 Start E5, 4 Ende F6, 7-Start I9, 8-Ende J10   (Offset)

Dim Start As Date, Ende As Date     'neu eingefügt statt asw Variable
Dim BStart As Date, BEnde As Date   'Vergleich geaendert  24.10.2016

Const ClrBer = "B10:K58"   'Löschbereich in Tabelle "Änderungen"

LG
Antworten Top
#8
Strukturplan Aktuell - dort wird der Name entnommen und im Strukturplan veraltet gesucht

Kann man die Suche nach dem neuen Namen dort beginnen lassen, wo man bei dem letzten Name/Datum - Vergleich aufgehört hat?
Antworten Top
#9
Hallo Flo,

zu deiner Frage Option Explicit, kann man drauf verzichten, sollte man aber nicht. Es legt nur fest ob alle Variablen vorher mit Dim festgelegt sein müssen. Deaktiviere ihn mal durch ein Hochkomme, so:  'Option und schreibe ins Makro eine neue Variable mit dem Namen Test = Range(xx).Value,  gefolgt von MsgBox Test, dahinter Exit Sub.  Jetzt stoppt das Makro und zeigt dir den Wert Test an. Benutze ich zur Fehlersuche!  Dann aktiviere Option wieder, der meckert sofort das diese neue Variable nicht mit Dim deklariert wurde.  Option hilft dir keine Variable Deklaration zu vergessen und zeigt Schreibfehler an.   

Die If Bedingung kannst du so aendern:   If Start = Empty And BEnde <> Ende Then  Welcher Start ist gemeint, Start oder Basis Start? 
Oder müssen beide Start auf Null sein, dann so:   If BStart = Empty And Start = Empty And BEnde <> Ende

Die andere Sache mit den doppelten Namen hatte ich nicht gerechnet, das muss ich mir in Ruhe anschauen und aendern. Kann es auch doppelte Namen unter dem gleichen Datum geben? Soll die ZNr mit übernommen werden, wenn ja aus welcher Tabelle?? Ich nehme an aktive Daten??

mfg  Gast 123
Antworten Top


Gehe zu:


Benutzer, die gerade dieses Thema anschauen: 1 Gast/Gäste