Anzeige
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Anzeige
Inhaltsverzeichnis

Änderungen erst beim Speichern per VBA protokollieren

Forumthread: Änderungen erst beim Speichern per VBA protokollieren

Änderungen erst beim Speichern per VBA protokollieren
27.08.2025 12:27:57
MikeA
Hallo zusammen,
ich habe mit Hilfe des Forums es geschafft Änderungen in der Tabelle "Planung" protokollieren zu lassen. Das funktioniert auch ganz gut. Es gibt nur zwei Probleme für die ich keine Lösung gefunden habe.

  • Mit dem Code wird jede Änderung protokolliert, also auch wenn man in der Planung "rumprobiert" was am besten passen könnte. Gibt es eine Möglichkeit die Änderungen erst dann zu protokollieren, wenn man die Datei speichert?

  • Das zweite Problem ist folgendes. Wenn ich den Inhalt von mehreren Zellen gleichzeitig lösche oder in mehrere Zellen gleichzeitig etwas einfüge, wird nur der neue und alte Wert der ersten markierten Zelle protokolliert. Gibt es die Möglichkeit die Änderungen von allen Zellen protokollieren zu lassen? Die geänderten Zellen (Target.Address) wird korrekt angezeigt.


  • Vielen Dank für eure Hilfe
    Mike


    Hier mein VBA-Code:
    Public AlterWert As Variant
    Private Sub Workbook_SheetChange(ByVal Sh As Object, ByVal Target As Range)
    Dim ErsteFreieZeile As Long
    If Sh.Name > "Planung" Then Exit Sub
    If Target.CountLarge > 100 Or IsError(Target) Then Exit Sub
    If Intersect(Target, Sh.Range("A1:AF76")) Is Nothing Then Exit Sub
    With Sheets("Protokoll")
    ErsteFreieZeile = .Cells(Rows.Count, 1).End(xlUp).Row + 1
    .Cells(ErsteFreieZeile, 1) = Date
    .Cells(ErsteFreieZeile, 2) = Time
    .Cells(ErsteFreieZeile, 3) = AlterWert
    .Cells(ErsteFreieZeile, 4) = Target.Value
    .Cells(ErsteFreieZeile, 5) = Target.Address(0, 0)
    .Cells(ErsteFreieZeile, 6) = Environ("username")
    End With
    End Sub

    Private Sub Workbook_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
    If Target.CountLarge > 100 Or IsError(Target) Then Exit Sub
    If Sh.Name > "Planung" Then Exit Sub
    If Not Intersect(Target, Sh.Range("A1:AF76")) Is Nothing Then
    AlterWert = Target.Value
    End If
    End Sub
    Anzeige
    AW: Änderungen erst beim Speichern per VBA protokollieren
    27.08.2025 13:32:19
    daniel
    Hi
    Wenn du nur die finalen Änderung protokollieren willst, musst du:

    1. Ein zusätzliches Platt anlegen "Planung Sicherung"

    2. Im Workbook-Open kopierst du "Planung" und fügst als Wert in "Planung Sicherung" ein

    3. Im BeforeSave musst du dann in einer Schleife jede Zelle von "Planung" mit dem Wert der gleichen Zelle von "Planung Sicherung" vergleichen und wenn diese nicht gleich sind, die Protokollzeile erstellen.

    Kannst du das programmieren?

    Deine zweite Frage hätte sich damit erübrigt.

    Gruß Daniel
    Anzeige
    AW: Änderungen erst beim Speichern per VBA protokollieren
    28.08.2025 11:01:51
    MikeA
    Hi Daniel,
    danke für deine Hilfe. Leider kenne ich mich mit VBA nicht wirklich aus. Die ersten zwei Punkte habe ich hinbekommen. Bei dem dritten Punkt habe ich leider überhaupt keine Ahnung, wie ich das anstellen soll. Kann mir hier jemand helfen.

    Vielen Dank


    Hier mein Code für das Kopieren der Tabelle:
    Private Sub Workbook_Open()
    Sheets("Planung").Range("A1:AF76").Copy
    Sheets("Sicherung").Range("A1").PasteSpecial Paste:=xlPasteValues
    Application.CutCopyMode = False
    End Sub
    Anzeige
    AW: Änderungen erst beim Speichern per VBA protokollieren
    28.08.2025 13:02:46
    MikeA
    Ich habe jetzt noch weiter rumprobiert und folgende Lösung gefunden. Das funktioniert soweit. Ist es aber normal, dass das Speichern bzw. Schließen der Tabelle recht lange dauert, wenn viele Zellen geändert wurden?


    Private Sub Workbook_Open()
    Sheets("Planung").Range("A1:AF76").Copy
    Sheets("Sicherung").Range("A1:AF76").PasteSpecial Paste:=xlPasteValues
    Application.CutCopyMode = False
    End Sub

    Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    Dim ErsteFreieZeile As Long
    For Each zelle In Worksheets("Sicherung").Range("A1:AF76")
    If Worksheets("Planung").Range(zelle.Address).Value > Worksheets("Sicherung").Range(zelle.Address).Value Then
    With Sheets("Protokoll")
    ErsteFreieZeile = .Cells(Rows.Count, 1).End(xlUp).Row + 1
    .Cells(ErsteFreieZeile, 1) = Date
    .Cells(ErsteFreieZeile, 2) = Time
    .Cells(ErsteFreieZeile, 3) = Worksheets("Sicherung").Range(zelle.Address).Value
    .Cells(ErsteFreieZeile, 4) = Worksheets("Planung").Range(zelle.Address).Value
    .Cells(ErsteFreieZeile, 5) = Worksheets("Planung").Range(zelle.Address).Address(0, 0)
    .Cells(ErsteFreieZeile, 6) = Environ("username")
    End With
    End If
    Next
    End Sub
    Anzeige
    AW: Änderungen erst beim Speichern per VBA protokollieren
    28.08.2025 14:49:02
    daniel
    Hi
    Ja ist normal weil jetzt die ganze Protokollierung, die vorher über deine ganze Arbeitszeit verteilt stattgefunden hat, gebündelt beim Speichen stattfindet.

    So sollte es schneller gehen:
    1. Verwende Variablen, um die Zellen zu anzusprechen, damit du nicht jedesmal über die Adressen gehen musst
    2. Schreibe die Protokollwerte erst in ein Array, damit du sie dann als ganzes ins Protokoll schreiben kannst. Jedes Schreiben in eine Zelle erfordert Zeit, die kann man reduzieren wenn man möglichst viele Zellen gemeinsam befüllt.

    Private Sub Workbook_Open()
    
    Sheets("Planung").Range("A1:AF76").Copy
    Sheets("Sicherung").Range("A1:AF76").PasteSpecial Paste:=xlPasteValues
    Application.CutCopyMode = False
    End Sub


    Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    
    Dim ZelleS as Range
    dim ZelleP as Range
    Dim x(1 to 6)

    For Each ZelleS In Worksheets("Sicherung").Range("A1:AF76")
    Set ZelleP= worksheets("Planung").Range(ZelleS.Address)
    If ZelleS.Value > ZelleP.Value Then
    x(1, 1) = Date
    x(1, 2) = Time
    x(1, 3) = ZelleS.Value
    x(1, 4) = ZelleP.Value
    x(1, 5) = Zelle.Address
    x(1, 6) = Environ("username")
    Sheets("Protokoll").Cells(rows.Count, 1).end(xlUp).offset(1, 0).Resize(1, 6).value = x
    End If
    Next
    End Sub



    Wenn das noch nicht ausreicht, Google mal:
    GetMoreSpeed

    Gruß Daniel
    Anzeige
    AW: Änderungen erst beim Speichern per VBA protokollieren
    28.08.2025 15:29:31
    daniel
    Bitte korrigieren:

    Dim x(1 to 1, 1 to 6)


    Noch schneller geht's, wenn du die Protokollerstellung komplett auf Array-Ebene durchführst
    
    
    Dim ArrS, ArrP
    Dim z as Long, s as long
    Dim X
    Dim I as long

    ArrS = Sheets("Sicherung").Range("A1:AF76").value
    ArrS = Sheets("Planung").Range("A1:AF76").value
    For z = 1 to Ubound(arrS,1)
    For s = 1 to Ubound(arrS, 2)
    I = l - (arrS(z, s) > arrP(z, s))
    Next
    Next

    Redim X(1 to I, 1 to 6)
    I = 0

    For z = 1 to Ubound(arrS,1)
    For s = 1 to Ubound(arrS, 2)
    if arrS(z, s) > arrP(z, s) then
    I = I + 1
    x(i, 1) = Date
    x(i, 2) = Time
    x(i, 3) = arrS(z, s)
    x(i, 4) = arrP(z, s)
    x(i, 5) = cells(z, s).address(0, 0)
    x(i, 6) = Environ("username")
    End if
    Next
    Next
    Sheets("Protokoll").Cells(rows.Count, 1).end(xlUp).offset(1, 0).resize(Ubound(x, 1), Ubound(x, 2)) = x


    Das arbeiten in Arrays ist sehr schnell und du hast am Ende nur einen Schrei Vorgang ins Tabellenblatt.

    Gruß Daniel
    Anzeige
    AW: Änderungen erst beim Speichern per VBA protokollieren
    28.08.2025 15:56:59
    MikeA
    Hi Daniel,
    jetzt warst du zu schnell für mich mit deinem neuen Code. In dem neuen Code kommt der Fehler "Laufzeitfehler 9: Index außerhalb des gültigen Bereichs". Markiert wird dann die Zeile:
    ReDim X(1 To I, 1 To 6)

    In deinem zweiten Code müsste es oben beim Festlegen der Bereiche "ArrP" statt das zweite mal "ArrS" heißen, oder?

    Vielen Dank für deine Mühen
    Mike
    Anzeige
    AW: Änderungen erst beim Speichern per VBA protokollieren
    28.08.2025 16:20:23
    daniel
    Ich hab den Code jetzt einfach nur direkt ins Forum geschrieben.
    Soll ja ne Anregung für dich sein

    Ja muss einmal ArrP und einmal ArrS sein.

    Check mal die Variable I, welchen Wert die hat
    Du musst nach der ersten Schleife noch ne Prüfung einbauen, für den Fall, dass keine Änderung stattgefunden hat (i = 0)
    Wen das der fall ist, kann man an dieser Stelle das Makro beenden und muss den zweiten Teil nicht ausführen.

    Gruß Daniel
    Anzeige
    AW: Änderungen erst beim Speichern per VBA protokollieren
    28.08.2025 16:24:08
    daniel
    Vielleicht ist noch ein Fehler drin, die Variable muss immer i sein (ist ggf mal groß und mal klein geschrieben, aber das ist egal) aber kein L oder l.
    AW: Änderungen erst beim Speichern per VBA protokollieren
    29.08.2025 11:59:27
    MikeA
    Ich hab den Code jetzt mal folgendermaßen eingetragen. Das scheint auch zu funktionieren oder hab ich was übersehen, was ggf. problematisch werden kann?

    Vielen Dank nochmals

    
    
    Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    Dim ArrS, ArrP
    Dim z As Long, s As Long
    Dim X(1 To 2432, 1 To 6)
    Dim i As Long

    ArrS = Sheets("Sicherung").Range("A1:AF76").Value
    ArrP = Sheets("Planung").Range("A1:AF76").Value
    i = 0
    For z = 1 To UBound(ArrS, 1)
    For s = 1 To UBound(ArrS, 2)
    If ArrS(z, s) > ArrP(z, s) Then
    i = i + 1
    X(i, 1) = Now
    X(i, 2) = ArrS(z, s)
    X(i, 3) = ArrP(z, s)
    X(i, 4) = Cells(z, s).Address(0, 0)
    X(i, 5) = Environ("username")
    End If
    Next
    Next
    Sheets("Protokoll").Cells(Rows.Count, 1).End(xlUp).Offset(1, 0).Resize(UBound(X, 1), UBound(X, 2)) = X
    End Sub
    Anzeige
    AW: Änderungen erst beim Speichern per VBA protokollieren
    29.08.2025 13:16:28
    daniel
    Ich sehe grad kein Problem.
    Solange die Anzahl der Zellen, die du prüfst unveränderlich ist, kannst du X auch auf den maximal möglichen Wert dimensionieren, das sollte kein Problem sein.

    Im Sinne einer flexiblen Programmierung, bei der Änderungen an der Excel-Datei möglichst wenig Änderungen am Code erfordern, könnest du die Zeilenzahl für X noch berechnen.

    Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    
    Dim ArrS, ArrP
    Dim z As Long, s As Long
    Dim X
    Dim i As Long

    ArrS = Sheets("Sicherung").Range("A1:AF76").Value
    ArrP = Sheets("Planung").Range("A1:AF76").Value
    Redim X(1 to Ubound(arrP, 1) * Ubound(arrP, 2), 1 to 6)


    Ich finde des gut, dass du dir selber Gedanken zum Code machst

    Gruß Daniel
    Anzeige
    AW: Änderungen erst beim Speichern per VBA protokollieren
    28.08.2025 15:41:19
    MikeA
    Hi Daniel,
    vielen Dank nochmal. Es kommt mit deiner Formel leider die Fehlermeldung "Fehler beim Kompilieren: Falsche Anzahl an Dimensionen" und "x(1, 1) =" wird blau markiert bzw. ausgewählt.
    Ich habe versucht das nachzuvollziehen, aber hier komme ich echt nicht mehr weiter

    Viele Grüße
    Anzeige

    Forumthreads zu verwandten Themen

    Anzeige
    Anzeige
    Anzeige