автоматично виконувати макрос Excel при зміні комірки


91

Як я можу автоматично виконувати макрос Excel щоразу, коли змінюється значення в певній комірці?

Зараз мій робочий код:

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

де "H5"- конкретна комірка, що відстежується, Macro- це назва макросу.

Чи є кращий спосіб?


Чи відповідає UDF RunMacroWhenValueChanges у FormulaDesk вашим вимогам? formulaladesk.com
Gareth Hayter

Відповіді:


107

Ваш код виглядає досить добре.

Однак будьте обережні, оскільки ваш дзвінок до Range("H5")- це ярлик до Application.Range("H5"), що еквівалентно Application.ActiveSheet.Range("H5"). Це могло б бути добре, якщо єдиними змінами є зміни користувача - що є найбільш типовим - але значення комірок робочого аркуша можуть змінюватися, коли це не активний аркуш за допомогою програмних змін, наприклад VBA.

З огляду на це, я б використав 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

Або ви можете використовувати Me.Range("H5"), якщо обробник подій знаходиться на кодовій сторінці відповідного робочого аркуша (зазвичай це так):

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

Сподіваюся, це допомагає ...


4
що якщо клітинку H5змінити з іншого аркуша, скажімо, sheet2 тоді вищевказана функція не працює. PLZ допомогти в цьому.
dhpratik

2
Для тих, хто приходить сюди з пошуку Google, переконайтеся, що ви вставляєте цей код на аркуш у vba, а не в модуль, як це робив я. дивитися на stackoverflow.com/questions/15337008 / ...
hammythepig

Application.ActiveSheet.Range ("H5"). ==> target.parent.range ("H5") ще безпечніший
П'єр

1
@WillEdiger Щоразу, коли ви явно не вказуєте посилання на аркуш, Excel припускає, ActiveSheetа коли ви явно не вказуєте, що це Excel, з яким ви працюєте, Excel припускає Application.
Скотт Маркус

1
Слід зазначити, що в модулі робочого листа коду (який де Worksheet_Changeподія має бути розташоване), некваліфікований Rangeзовсім НЕ по замовчуванням , ActiveSheetале замість цього відноситься до листу , що містить код. Тому код у цій відповіді фактично такий самий, як і код у питанні. (Примітка: Ще в 2009 році, коли була написана ця відповідь, вона могла бути іншою, але я впевнений, що це не так.)
YowE3K

7

Обробляти Worksheet_Changeподію або Workbook_SheetChangeподію.

Обробники подій беруть аргумент "Націлити як діапазон", щоб ви могли перевірити, чи включає діапазон, що змінюється, клітинку, яка вас цікавить.


Дякую, це працює. Я перевіряю діапазон, скажімо, з Target.Address = Range("H5").Address. Чи є простіший спосіб?
намін

Альтернатива: Not (Intersect(Target, Range("H5")) Is Nothing) . Це як би ти це зробив?
namin

2
Перший коментар ( Target.Address = Range("H5").Address) не спрацював би, якщо ваша комірка була лише частиною зміненого діапазону. Другий коментар все ще страждає від проблем, описаних Майком Розенблюмом.
Мураха

5

Я витратив багато часу, досліджуючи це і дізнавшись, як все це працює, після того, як справді зіпсував тригери події. Оскільки було так багато розкиданої інформації, я вирішив поділитися тим, що, як мені здається, працює в одному місці, крок за кроком наступним чином:

1) Відкрийте редактор VBA, за проектом VBA (YourWorkBookName.xlsm) відкрийте об’єкт Microsoft Excel і виберіть Аркуш, до якого стосуватиметься подія зміни.

2) Типовим переглядом коду є "Загальне". У спадному списку у верхній середині виберіть "Робочий аркуш".

3) Private Sub Worksheet_SelectionChange вже є як слід, залиште це в спокої. Скопіюйте / вставте код Майка Розенблюма зверху та змініть посилання .Range на клітинку, для якої ви спостерігаєте за зміною (B3, у моєму випадку). Однак поки не розміщуйте свій макрос (слово "макрос" я видалив після "потім"):

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

або з випадаючого списку вгорі ліворуч виберіть "Змінити" і вставте в пробіл між приватним суб-та кінцевим суб-списком If Not Intersect(Target, Me.Range("H5")) Is Nothing Then

4) У рядку після "Потім" вимкніть події, щоб, коли ви викликаєте ваш макрос, він не запускав події і спробував запустити цей Worksheet_Change знову в нескінченному циклі, який аварійно завершує роботу Excel та / або іншим чином псує все:

Application.EnableEvents = False

5) Зателефонуйте своєму макросу

Call YourMacroName

6) Увімкніть події знову, щоб наступна зміна (та будь-яка / всі інші події) ініціювала:

Application.EnableEvents = True

7) Завершіть блок If та Sub:

    End If
End Sub

Весь код:

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

Це вимагає включення / вимкнення подій з Модулів, що створює проблеми і просто дозволяє тригеру змін, вимикає події, запускає ваш макрос і знову включає події.


3

Я віддаю перевагу цьому шляху, не використовуючи комірку, а діапазон

    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

Це те саме, що одна клітина. Ви можете встановити діапазон як одну комірку, діапазон континуальних комірок або навіть розсіяні комірки (всі розділені комами).
Шай Алон

0

У мене є комірка, яка пов’язана з онлайн-базою даних та часто оновлюється. Я хочу активувати макрос щоразу, коли значення комірки оновлюється.

Я вважаю, що це схоже на зміну значення комірки програмою чи будь-яким зовнішнім оновленням даних, але наведені вище приклади якимось чином не працюють для мене. Я думаю, що проблема в тому, що внутрішні події Excel не запускаються, але це моє припущення.

Я зробив наступне,

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
Я не можу змусити це працювати з якихось причин. Коли я кажу, що код запускається у VBA, він висуває спливаюче меню і запитує, чи хочу я запустити макрос, а не запускати макрос автоматично?
Девід Ван дер Вієрен,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.