Führen Sie bei einem Zellwechsel automatisch ein Excel-Makro aus

91

Wie kann ich jedes Mal, wenn sich ein Wert in einer bestimmten Zelle ändert, automatisch ein Excel-Makro ausführen?

Im Moment lautet mein Arbeitscode:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Range("H5")) Is Nothing Then Macro
End Sub

Wo "H5"ist die bestimmte Zelle überwacht und Macroist der Name des Makros.

Gibt es einen besseren Weg?

namin
quelle
Entspricht die UDF RunMacroWhenValueChanges in FormulaDesk Ihren Anforderungen? formuladesk.com
Gareth Hayter

Antworten:

106

Ihr Code sieht ziemlich gut aus.

Seien Sie jedoch vorsichtig, denn Ihr Aufruf von Range("H5")ist ein Verknüpfungsbefehl zu Application.Range("H5"), der äquivalent zu ist Application.ActiveSheet.Range("H5"). Dies kann in Ordnung sein, wenn die einzigen Änderungen Benutzeränderungen sind - was am typischsten ist -, aber es ist möglich, dass sich die Zellenwerte des Arbeitsblatts ändern, wenn es sich nicht um das aktive Blatt handelt, über programmatische Änderungen, z. B. VBA.

In diesem Sinne würde ich verwenden Target.Worksheet.Range("H5"):

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Target.Worksheet.Range("H5")) Is Nothing Then Macro
End Sub

Oder Sie können verwenden Me.Range("H5"), wenn sich der Ereignishandler auf der Codepage für das betreffende Arbeitsblatt befindet (normalerweise):

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("H5")) Is Nothing Then Macro
End Sub

Hoffe das hilft...

Mike Rosenblum
quelle
4
Was passiert, wenn die Zelle H5von einem anderen Blatt geändert wird? Sagen wir, sheet2dann funktioniert die obige Funktion nicht. Bitte helfen Sie dabei.
Dhpratik
2
Wenn Sie von einer Google-Suche hierher kommen, stellen Sie sicher, dass Sie diesen Code in das Blatt in vba einfügen, nicht in ein Modul wie ich. Schauen Sie sich stackoverflow.com/questions/15337008/…
Hammythepig
Application.ActiveSheet.Range ("H5"). ==> target.parent.range ("H5") ist noch sicherer
Pierre
1
@WillEdiger Immer wenn Sie eine Blattreferenz nicht explizit angeben, geht Excel davon aus, ActiveSheetund wenn Sie nicht explizit angeben, dass es sich um Excel handelt, mit dem Sie arbeiten, geht Excel davon aus Application.
Scott Marcus
1
Man beachte , dass in einem Arbeitsblatt - Code - Modul (das ist , wenn ein Worksheet_ChangeEreignis muss befinden), ein unqualifiziertes Rangeist nicht standardmäßig , ActiveSheetsondern bezieht sich auf das Blatt den Code enthält. Der Code in dieser Antwort ist daher effektiv der gleiche wie der Code in der Frage. (Hinweis: Im Jahr 2009, als diese Antwort geschrieben wurde, war sie vielleicht anders, aber ich bin mir ziemlich sicher, dass dies nicht der
Fall
7

Behandeln Sie das Worksheet_ChangeEreignis oder das Workbook_SheetChangeEreignis.

Die Ereignishandler verwenden das Argument "Ziel als Bereich", sodass Sie überprüfen können, ob der sich ändernde Bereich die Zelle enthält, an der Sie interessiert sind.

Joe
quelle
Danke, es funktioniert. Ich überprüfe den Bereich mit Target.Address = Range("H5").Address. Gibt es einen einfacheren Weg?
Namin
Eine Alternative : Not (Intersect(Target, Range("H5")) Is Nothing) . Würden Sie das so machen?
Namin
2
Der erste Kommentar ( Target.Address = Range("H5").Address) würde nicht funktionieren, wenn Ihre Zelle nur Teil des geänderten Bereichs wäre. Der zweite Kommentar leidet immer noch unter den von Mike Rosenblum beschriebenen Problemen.
Ameise
5

Ich habe viel Zeit damit verbracht, dies zu erforschen und zu lernen, wie alles funktioniert, nachdem ich die Ereignisauslöser wirklich durcheinander gebracht habe. Da es so viele verstreute Informationen gab, beschloss ich, das, was ich gefunden habe, Schritt für Schritt an einem Ort wie folgt zu teilen:

1) Öffnen Sie den VBA-Editor, öffnen Sie unter VBA-Projekt (YourWorkBookName.xlsm) das Microsoft Excel-Objekt und wählen Sie das Blatt aus, auf das sich das Änderungsereignis beziehen soll.

2) Die Standardcodeansicht ist "Allgemein". Wählen Sie in der Dropdown-Liste oben in der Mitte "Arbeitsblatt" aus.

3) Private Sub Worksheet_SelectionChange ist bereits vorhanden, wie es sein sollte, lassen Sie es in Ruhe. Kopieren Sie den Code von Mike Rosenblum von oben und fügen Sie ihn ein. Ändern Sie den .Range-Verweis auf die Zelle, für die Sie nach einer Änderung suchen (in meinem Fall B3). Platzieren Sie Ihr Makro jedoch noch nicht (ich habe das Wort "Makro" nach "Dann" entfernt):

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("H5")) Is Nothing Then
End Sub

oder wählen Sie in der Dropdown-Liste oben links "Ändern" aus und fügen Sie sie in das Feld zwischen "Private Sub" und "End Sub" ein If Not Intersect(Target, Me.Range("H5")) Is Nothing Then

4) Deaktivieren Sie in der Zeile nach "Dann" Ereignisse, damit beim Aufrufen Ihres Makros keine Ereignisse ausgelöst werden, und versuchen Sie, diese Arbeitsblattänderung in einem nie endenden Zyklus erneut auszuführen, der Excel zum Absturz bringt und / oder auf andere Weise alles durcheinander bringt:

Application.EnableEvents = False

5) Rufen Sie Ihr Makro auf

Call YourMacroName

6) Schalten Sie Ereignisse wieder ein, damit die nächste Änderung (und alle anderen Ereignisse) ausgelöst wird:

Application.EnableEvents = True

7) Beenden Sie den If-Block und das Sub:

    End If
End Sub

Der gesamte Code:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Not Intersect(Target, Me.Range("B3")) Is Nothing Then
        Application.EnableEvents = False
        Call UpdateAndViewOnly
        Application.EnableEvents = True
    End If
End Sub

Dadurch werden Ereignisse in den Modulen ein- und ausgeschaltet, was zu Problemen führt und die Änderung einfach auslösen lässt, Ereignisse ausschaltet, Ihr Makro ausführt und Ereignisse wieder einschaltet.

Eric Vaughn-Shobey
quelle
3

Ich bevorzuge diesen Weg, nicht eine Zelle, sondern einen Bereich

    Dim cell_to_test As Range, cells_changed As Range

    Set cells_changed = Target(1, 1)
    Set cell_to_test = Range( RANGE_OF_CELLS_TO_DETECT )

    If Not Intersect(cells_changed, cell_to_test) Is Nothing Then 
       Macro
    End If
Javier Torón
quelle
Es ist das gleiche wie eine Zelle. Sie können einen Bereich entweder als eine Zelle, als Bereich von Continuos-Zellen oder sogar als verstreute Zellen (alle durch Komma getrennt) festlegen.
Shai Alon
0

Ich habe eine Zelle, die mit der Online-Bestandsdatenbank verknüpft und regelmäßig aktualisiert wird. Ich möchte ein Makro auslösen, wenn der Zellenwert aktualisiert wird.

Ich glaube, dies ähnelt einer Änderung des Zellenwerts durch ein Programm oder eine externe Datenaktualisierung, aber die obigen Beispiele funktionieren bei mir irgendwie nicht. Ich denke, das Problem ist, dass keine internen Excel-Ereignisse ausgelöst werden, aber das ist meine Vermutung.

Ich habe folgendes getan:

Private Sub Worksheet_Change(ByVal Target As Range) 
  If Not Intersect(Target, Target.Worksheets("Symbols").Range("$C$3")) Is Nothing Then
   'Run Macro
End Sub
Juan Garcia
quelle
1
Ich kann das aus irgendeinem Grund nicht zum Laufen bringen. Wenn ich dem Code sage, dass er in VBA ausgeführt werden soll, wird ein Popup-Menü aufgerufen und ich werde gefragt, ob ich das Makro ausführen möchte, anstatt das Makro automatisch auszuführen.
David Van der Vieren