esegue automaticamente una macro di Excel su un cambio di cella


91

Come posso eseguire automaticamente una macro di Excel ogni volta che cambia un valore in una determinata cella?

In questo momento, il mio codice di lavoro è:

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

dov'è "H5"la particolare cella monitorata ed Macroè il nome della macro.

C'è un modo migliore?


L'UDF RunMacroWhenValueChanges in FormulaDesk soddisfa i tuoi requisiti? formuladesk.com
Gareth Hayter

Risposte:


107

Il tuo codice sembra abbastanza buono.

Fai attenzione, tuttavia, perché la tua chiamata a Range("H5")è un comando di scelta rapida a Application.Range("H5"), che è equivalente a Application.ActiveSheet.Range("H5"). Questo potrebbe andare bene, se le uniche modifiche sono le modifiche dell'utente - che è la più tipica - ma è possibile che i valori delle celle del foglio di lavoro cambino quando non è il foglio attivo tramite modifiche programmatiche, ad esempio VBA.

Con questo in mente, utilizzerei 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

Oppure puoi usare Me.Range("H5"), se il gestore dell'evento si trova nella codepage del foglio di lavoro in questione (di solito lo è):

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

Spero che questo ti aiuti...


4
cosa succede se la cella H5viene modificata da un altro foglio, diciamo che sheet2 la funzione sopra non funziona. plz aiutare in questo.
dhpratik

2
Per chiunque provenga da una ricerca su Google, assicurati di incollare questo codice nel foglio in vba, non in un modulo come ho fatto io. guardare stackoverflow.com/questions/15337008/...
hammythepig

Application.ActiveSheet.Range ("H5"). ==> target.parent.range ("H5") è ancora più sicuro
Pierre,

1
@WillEdiger Ogni volta che non specifichi esplicitamente un riferimento al foglio, Excel presume il ActiveSheete ogni volta che non specifichi esplicitamente che è Excel con cui stai lavorando, Excel presume Application.
Scott Marcus

1
Si noti che, in un modulo di codice del foglio di lavoro (che è dove Worksheet_Changedeve essere localizzato un evento), un Rangenon qualificato non è predefinito ActiveSheetma si riferisce invece al foglio contenente il codice. Il codice in questa risposta è quindi effettivamente lo stesso del codice nella domanda. (Nota: nel 2009, quando è stata scritta questa risposta, potrebbe essere stata diversa, ma sono abbastanza certo che non lo fosse.)
YowE3K

7

Gestisci l' Worksheet_Changeevento o l' Workbook_SheetChangeevento.

I gestori di eventi accettano un argomento "Target As Range", quindi puoi controllare se l'intervallo che sta cambiando include la cella che ti interessa.


Grazie, funziona. Posso controllare la gamma con, diciamo, Target.Address = Range("H5").Address. C'è un modo più semplice?
namin

Un'alternativa: Not (Intersect(Target, Range("H5")) Is Nothing) . È così che lo faresti?
namin

2
Il primo commento ( Target.Address = Range("H5").Address) non funzionerebbe se la tua cella fosse solo una parte dell'intervallo modificato. Il secondo commento soffre ancora dei problemi descritti da Mike Rosenblum.
Ant

5

Ho passato molto tempo a fare ricerche e ad imparare come funziona, dopo aver davvero incasinato i trigger dell'evento. Dato che c'erano così tante informazioni sparse, ho deciso di condividere ciò che ho scoperto funzionare tutto in un unico posto, passo dopo passo come segue:

1) Apri VBA Editor, sotto VBA Project (YourWorkBookName.xlsm) apri Microsoft Excel Object e seleziona il foglio a cui si riferirà l'evento di modifica.

2) La visualizzazione del codice predefinita è "Generale". Dall'elenco a discesa in alto al centro, seleziona "Foglio di lavoro".

3) Private Sub Worksheet_SelectionChange è già lì come dovrebbe essere, lascialo stare. Copia / Incolla il codice di Mike Rosenblum dall'alto e cambia il riferimento .Range alla cella per la quale stai cercando un cambiamento (B3, nel mio caso). Tuttavia, non posizionare ancora la tua Macro (ho rimosso la parola "Macro" dopo "Allora"):

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

oppure dall'elenco a discesa in alto a sinistra, seleziona "Modifica" e nello spazio tra Private Sub e End Sub, incolla If Not Intersect(Target, Me.Range("H5")) Is Nothing Then

4) Nella riga dopo "Allora" disattiva gli eventi in modo che quando chiami la tua macro, non inneschi eventi e cerchi di eseguire nuovamente questo Worksheet_Change in un ciclo infinito che blocca Excel e / o altrimenti incasina tutto:

Application.EnableEvents = False

5) Chiama la tua macro

Call YourMacroName

6) Riattiva gli eventi in modo che la modifica successiva (e qualsiasi / tutti gli altri eventi) si attivi:

Application.EnableEvents = True

7) Termina il blocco If e il Sub:

    End If
End Sub

L'intero codice:

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

Ciò elimina l'attivazione / disattivazione degli eventi dai moduli, il che crea problemi e consente semplicemente di attivare la modifica, disattivare gli eventi, eseguire la macro e riattivare gli eventi.


3

Preferisco in questo modo, non usando una cella ma un intervallo

    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

È lo stesso di una cella. Puoi impostare un intervallo come una cella, un intervallo di celle continue o persino celle sparse (tutte separate da virgola).
Shai Alon

0

Ho una cella collegata al database delle scorte online e aggiornata frequentemente. Voglio attivare una macro ogni volta che il valore della cella viene aggiornato.

Credo che questo sia simile alla modifica del valore della cella da parte di un programma o qualsiasi aggiornamento di dati esterni, ma gli esempi sopra in qualche modo non funzionano per me. Penso che il problema sia perché gli eventi interni di Excel non vengono attivati, ma questa è la mia ipotesi.

Ho fatto quanto segue,

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

1
Non riesco a farlo funzionare per qualche motivo. Quando dico al codice di funzionare in VBA, viene visualizzato un menu a comparsa e mi chiede se voglio eseguire la macro invece di eseguire la macro automaticamente?
David Van der Vieren
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.