当单元格值更改时自动运行Excel vba代码

我正在寻找一种方式来自动启动一个特定的小组,当单元格的值为零。

例如,如果我在单元格A1中input“0”,则应该运行以下Sub

Range("H32").FormulaR1C1 = "=SUM(R[-4]C:R[-2]C)" 

如果我input1(或任何其他值大于0)到单元格A1另一个子应运行,例如

 Range("B15").FormulaR1C1 = "=SUM(R[-1]C:R[-1]C)" 

调用Sub应该是在我在excel中input值之后进行的,而不用按任何button。 有没有办法做到这一点?

让我们从这个代码开始,我将在下面解释。

打开VB编辑器Alt + F11 。 右键单击希望发生此行为的工作表,然后select“ View Code

将以下代码复制并粘贴到工作表代码中。

 Private Sub Worksheet_Change(ByVal Target As Range) 'CountLarge is an Excel 2007+ property, if using Excel 2003 'change to just Count If Target.Cells.CountLarge > 1 Or IsEmpty(Target) Then Exit Sub If Target.Address = "$A$1" Then If Target.Value = 0 Then Me.Range("H32").FormulaR1C1 = "=SUM(R[-4]C:R[-2]C)" ElseIf Target.Value = 1 Then Me.Range("B15").FormulaR1C1 = "=SUM(R[-1]C:R[-1]C)" End If End If End Sub 

每次用户对工作表进行更改时,都会触发Worksheet_Change事件。 例如,如果更改单元格值,则会触发此事件。

这个子程序中的第一行检查,以确保多个单元格没有改变,实际上有一个实际的单元格更改,如果不是真的,那么它不会继续。

然后我们检查一下,确保值A1在单元格A1中发生了变化,如果有的话,我们input这个IF语句。

从那里,我们检查input到单元格A1的值。 如果该值为0,则将适当的公式添加到H32 。 如果值为1,则将适当的公式添加到B15 。 如果在单元格A1中input的值不是0或1,则不会发生任何情况。

重要的是要注意,你必须离开单元格来触发这个事件,所以虽然这是一个好的开始,但是我现在还不知道如何在没有按下input或离开单元格的情况下触发这个事件。

更新

经过一些研究和玩耍,我已经想出了如何在不按下input或任何其他button的情况下进行更改,即使您正在编辑“0”或“1”单元格值。 我从以前的SO问题中使用了一个键盘处理程序。

BEGIN KEYBOARD HANDLINGEND KEYBOARD HANDLING事件之间的代码是从上面开始的。

将以下代码复制并粘贴到要捕获这些关键笔划的工作表代码中:

 Option Explicit 'BEGIN KEYBOARD HANDLING Private Type POINTAPI x As Long y As Long End Type Private Type MSG hwnd As Long Message As Long wParam As Long lParam As Long time As Long pt As POINTAPI End Type Private Declare Function WaitMessage Lib "user32" () As Long Private Declare Function PeekMessage Lib "user32" _ Alias "PeekMessageA" _ (ByRef lpMsg As MSG, ByVal hwnd As Long, _ ByVal wMsgFilterMin As Long, _ ByVal wMsgFilterMax As Long, _ ByVal wRemoveMsg As Long) As Long Private Declare Function TranslateMessage Lib "user32" _ (ByRef lpMsg As MSG) As Long Private Declare Function PostMessage Lib "user32" _ Alias "PostMessageA" _ (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lParam As Any) As Long Private Declare Function FindWindow Lib "user32" _ Alias "FindWindowA" _ (ByVal lpClassName As String, _ ByVal lpWindowName As String) As Long Private Const WM_KEYDOWN As Long = &H100 Private Const PM_REMOVE As Long = &H1 Private Const WM_CHAR As Long = &H102 Private bExitLoop As Boolean Sub StartKeyWatch() Dim msgMessage As MSG Dim bCancel As Boolean Dim iKeyCode As Integer Dim lXLhwnd As Long 'handle the ESC key. On Error GoTo errHandler: Application.EnableCancelKey = xlErrorHandler 'initialize this boolean flag. bExitLoop = False 'get the app hwnd. lXLhwnd = FindWindow("XLMAIN", Application.Caption) Do WaitMessage 'check for a key press and remove it from the msg queue. If PeekMessage _ (msgMessage, lXLhwnd, WM_KEYDOWN, WM_KEYDOWN, PM_REMOVE) Then 'strore the virtual key code for later use. iKeyCode = msgMessage.wParam 'translate the virtual key code into a char msg. TranslateMessage msgMessage PeekMessage msgMessage, lXLhwnd, WM_CHAR, _ WM_CHAR, PM_REMOVE 'for some obscure reason, the following 'keys are not trapped inside the event handler 'so we handle them here. If iKeyCode = vbKeyBack Then SendKeys "{BS}" If iKeyCode = vbKeyReturn Then SendKeys "{ENTER}" 'assume the cancel argument is False. bCancel = False 'the VBA RaiseEvent statement does not seem to return ByRef arguments 'so we call a KeyPress routine rather than a propper event handler. Sheet_KeyPress _ ByVal msgMessage.wParam, ByVal iKeyCode, ByVal Selection, bCancel 'if the key pressed is allowed post it to the application. If bCancel = False Then PostMessage _ lXLhwnd, msgMessage.Message, msgMessage.wParam, 0 End If End If errHandler: 'allow the processing of other msgs. DoEvents Loop Until bExitLoop End Sub Sub StopKeyWatch() 'set this boolean flag to exit the above loop. bExitLoop = True End Sub Private Sub Worksheet_Activate() Me.StartKeyWatch End Sub Private Sub Worksheet_Deactivate() Me.StopKeyWatch End Sub 'End Keyboard Handling Private Sub Sheet_KeyPress(ByVal KeyAscii As Integer, ByVal KeyCode As Integer, ByVal Target As Range, Cancel As Boolean) 'CountLarge is an Excel 2007+ property, if using Excel 2003 'change to just Count If Target.Cells.CountLarge > 1 Or IsEmpty(Target) Then Exit Sub If Target.Address = "$A$1" Then If KeyAscii = 48 Then Me.Range("H32").FormulaR1C1 = "=SUM(R[-4]C:R[-2]C)" ElseIf KeyAscii = 49 Then Me.Range("B15").FormulaR1C1 = "=SUM(R[-1]C:R[-1]C)" End If End If End Sub 

此外,右键单击ThisWorkbook对象 – >查看代码,并添加此代码:

 Private Sub Workbook_Open() Sheets("Sheet1").StartKeyWatch End Sub 

确保将Sheet1更改为工作表的名称。

VBA将“听”按键,如果活动单元格为A1,并且input0或1,则在用户执行其他任何操作之前,将执行相应的操作。

我会补充说他的性能成本很低,因为在Workbook_Open上执行的代码需要几秒钟才能运行。

感谢用户Siddharth Rout指出了Excel 2007中Count的潜在问题,并指导我使用CountLarge