2013-08-29 6 views
3

Это должно быть просто. Когда значение ячейки изменяется, я хочу вызвать некоторый код VBA. Ячейка (D3) представляет собой расчет из двух других ячеек =B3*C3. Я попытался 2 подхода:Макрос триггера VBA при изменении значения ячейки

Private Sub Worksheet_Change(ByVal Target As Range) 
    If Target.Column = 4 And Target.Row = 3 Then 
    MsgBox "There was a change in cell D3" 
    End If 
End Sub 

Поскольку клетка является расчет это не срабатывает, когда изменяется значение, потому что вычисление остается тем же самым. Я также пробовал:

Private Sub Worksheet_Calculate() 
    MsgBox "There was a calculation" 
End Sub 

Но у меня есть несколько расчетов на листе, и он срабатывает несколько раз. Есть ли способ определить, какие вычисления были изменены в событии расчета? Или есть ли другой способ отслеживать изменения D3?

ответ

5

Не могли бы вы попробовать что-то вроде этого? Измените формулу на =D3AlertOnChange(B3*C3).

Private D3OldVal As Variant 

Public Function D3AlertOnChange(val) 
    If val <> D3OldVal Then MsgBox "Value changed!" 
    D3OldVal = val 
    D3AlertOnChange = val 
End Function 
+0

Я разместил вариант и публичную функцию на листе vba, где находится ячейка. Я изменил формулу на '= D3AlertOnChange (B3 * C3)', и он говорит '#NAME? 'Я поместил код в неправильное расположение? –

+2

Попробуйте поместить его в стандартный модуль. Щелкните правой кнопкой мыши по любому из листов и выберите «Вставить -> Модуль». – Chel

+0

Хотя я могу настроить это решение для удовлетворения моих потребностей, я хотел бы упомянуть, что это событие запускается до того, как ячейка обновлена ​​на листе, а не после. Поместите «MsgBox (val)» справа в начале функции, которую вы видите, что функция получает новое значение параметра, но вы можете видеть, что это значение не было обновлено в ячейке на листе, но остерегайтесь. –

3

Или попробуйте

Private Sub Worksheet_Change(ByVal Target As Range) 
Dim numdependences As Integer 
On Error Resume Next 
HasDependents = Target.Dependents.Count 
If Err = 0 Then 
    If InStr(Target.Dependents.Address, "$D$3") <> 0 Then 
     MsgBox "change" 
    End If 
End If 
On Error GoTo 0 
End Sub 

Вам нужен контроль ошибок в случае, если изменить ячейку, которая имеет не иждивенцы.

+0

Я думал, что это сработает, но это не так. Я наблюдаю, как меняется моя ячейка D3, и никакое событие не срабатывает. –

+0

Он должен работать только при изменении B3 или C3 в вашем примере. Если вы измените D3 напрямую, это не будет работать. – Diego

1

попробовать это:

Sub Worksheet_Change(ByVal Target As Range) 

    If Not Intersect(Target, Target.Worksheet.Range("B1")) Is Nothing Then 

     Call macro 

    End If 

End Sub 

выглядит для изменения значения ячейки B1, а затем выполняет «макро»

0

Если вы ищете только если Worksheet_Change то он будет считать изменение для чего-нибудь введенный, даже если он совпадает с предыдущим значением. Чтобы преодолеть это, я использую переменную Public, чтобы фиксировать начальное значение и сравнивать его.

Это мой код для этого. Он также позволяет вам опустить части рабочего листа или использовать его для оценки каждой ячейки на листе.

Поместите этот код в Рабочий лист.

Public TargetVal As String 'This is the value of a cell when it is selected 


Private Sub Worksheet_SelectionChange(ByVal Target As Range) 
If Target.Cells.CountLarge > 1 Then 'If more then one cell is selected do not save TargetVal. CountLarge is used to protect from overflow if all cells are selected. 
    GoTo EXITNOW 
Else 
    TargetVal = Target 'This sets the value of the TargetVal variable when a cell is selected 
End If 
EXITNOW: 
End Sub 

Sub Worksheet_Change(ByVal Target As Range) 
'When a cell is modified this will evaluate if the value in the cell value has changed. 
'For example if a cell is entered and enter is pressed the value is still evaluated 
'We don't want to count it as a change if the value hasn't actually changed 

Dim ColumnNumber As Integer 
Dim RowNumber As Integer 
Dim ColumnLetter As String 

'--------------------- 
'GET CURRENT CELL INFO 
'--------------------- 
    ColumnNumber = Target.Column 
    RowNumber = Target.Row 
    ColumnLetter = Split(Target.Address, "$")(1) 

'--------------------- 
'DEFINE NO ACTION PARAMETERS 
' IF CELL CHANGED IS IN NO ACTION RANGE, EXIT CODE NOW FOR PERFORMANCE IMPROVEMENT OR TO NOT TAKE ACTION 
'--------------------- 
    If ColumnNumber <> 4 Then 'This would exempt anything not in Column 4 
     GoTo EXITNOW 
    ElseIf RowNumber <> 3 Then 'This would exempt anything not in Row 3 
     GoTo EXITNOW 
    'Add Attional ElseIf statements as needed 
    'ElseIf ColumnNumber > 25 Then 
     'GoTo EXITNOW 
    End If 

'--------------------- 
'EVALUATE IF CELL VALUE HAS CHANGED 
'--------------------- 
Debug.Print "---------------------------------------------------------" 
Debug.Print "Cell: " & ColumnLetter & RowNumber & " Starting Value: " & TargetVal & " | New Value: " & Target 

    If Target = TargetVal Then 
     Debug.Print " No Change" 
     'CALL MACRO, FUNCTION, or ADD CODE HERE TO DO SOMETHING IF NOT CHANGED 
    Else 
     Debug.Print " Cell Value has Changed" 
     'CALL MACRO, FUNCTION, or ADD CODE HERE TO DO SOMETHING IF CHANGED 
    End If 
Debug.Print "---------------------------------------------------------" 

EXITNOW: 
End Sub 
Смежные вопросы