这个问题来自我的一位正在开发excel Web加载项的客户,他们希望检测事件是由最终用户触发还是由代码触发。
他们已经注册了Worksheet.onChanged事件处理程序。
他们想忽略由代码本身触发的onChanged事件更改。并专注于处理事件处理程序仅应在用户更改值时完成。
场景: 加载项侦听sheetChange事件。加载项用户可以在交叉表中输入值,该加载项将推入服务器。 但是,加载项API还可以对交叉表进行一些修改,例如,加载项可以使用户单击并向下钻取以获取更多数据,其API逻辑将从服务中获取数据并写入交叉表。但是,还会触发sheetChanged事件。
尝试过客户的解决方案:
首先尝试: 我们尝试在更改值之前注销事件处理程序。 更改值后,我们再次注册。 由于取消注册是异步的,因此无法正常工作,我们无法等待取消注册。
第二次尝试: context.runtime.enableEvents =假 这是不可能的,因为还有其他事件我们仍然感兴趣。
当前尝试: 我们在更改值之前存储更改范围的地址。 在onChanged处理程序中,我们比较地址。 如果相同,我们就不做逻辑。 之后,我们再次删除该地址的存储空间。
我也试图使用全局标志并在事件处理程序中检查它,它不起作用。这是我的要旨:https://gist.github.com/lumine2008/2b51d94d20cdca9ac9a0e97029dfd95c
答案 0 :(得分:1)
Office.js尚不提供此类功能。
一些解决方法,包括a)context.runtime.enableEvents API,b)全局标志或c)在更改范围之前注销事件并在以后重新注册事件,这些方法不能跨平台工作。 在某些情况下,它们会过度抑制事件,这意味着由用户操作触发的某些事件也会被抑制。
最可靠的方法是您的“当前尝试”
答案 1 :(得分:0)
您可以创建一个变量,如果用户正在编辑该变量。
例如:
Private Sub Worksheet_Activate()
Static programChanging As Boolean
programChanging = False
End Sub
Private Sub Worksheet_Change(ByVal Target As Range)
If programChanging = False Then MsgBox("The User Is Changing")'*Do your code here*
End Sub
Private Sub Worksheet_SelectionChange(ByVal As Range)
programChanging = True
Range("A1").Value = "The Program Is Changing"
programChanging = False
End Sub
您可以使用programChanging
变量来检查用户是否正在更改,而不是检查程序是否正在更改,但是原理保持不变。
~~编辑~~
您还可以将其中一个单元格用作变量,例如:
Private Sub Worksheet_Change(ByVal Target As Range)
If Range("A1").Value = "False" Then MsgBox("The User Is Changing")'*Do your code here*
End Sub
Private Sub Worksheet_SelectionChange(ByVal As Range)
Range("A1").Value = "True"
Range("B5").Value = "The Program Is Changing"
Range("A1").Value = "False"
End Sub