Worksheet_Change事件会触发,但表单控件复选框在视觉上没有更新
我正在尝试在特定工作表上基于触发单元格数值变化,自动勾选/取消勾选表单控件复选框(例如F19)。
逻辑:
- 用户修改触发单元格。
- VBA在一个单独的数据表的A 列中搜索该值。
- 如果找到匹配项,则在该行的特定列(T到 AJ)中进行检查。
- 如果某个单元格包含 "OUI",主工作表上对应的复选框应该被勾选(
xlChecked)。
问题:
- 事件
Worksheet_Change确实会触发(用MsgBox测试过)。 - 代码能正确找到该行以及 "OUI" 的值。
- 代码能按名称正确找到复选框。
- 但是:复选框在屏幕上没有可视更新。尽管代码没有错误地执行,它们仍然保持未选中状态。
我已验证的内容:
- 工作表属性
Visible设置为-1 - xlSheetVisible(见附带截图)。 ScrollArea为空。Application.EnableEvents为True。- 代码中的复选框名称与Name Box中的名称完全一致。
- 我使用的是表单控件(Form Controls),而不是ActiveX。
下面是我使用的代码:
VBA
Private Sub Worksheet_Change(ByVal Target As Range) If Intersect(Target, Me.Range("F19")) Is Nothing Then Exit Sub Application.EnableEvents = False Application.ScreenUpdating = False
Dim wsSource As Worksheet, searchVal As String, foundRow As Variant
Dim cb As CheckBox, cellValue As Variant, isApproved As Boolean, i As Integer
' Generic sheet names used in my file
Set wsSource = ThisWorkbook.Sheets("Sheet_Data")
searchVal = Trim(Me.Range("F19").Value)
If searchVal <> "" Then
foundRow = Application.Match(searchVal, wsSource.Columns(1), 0)
If IsError(foundRow) Then foundRow = 0
End If
' Arrays setup (Names match exactly what is in the Name Box)
Dim caseNames(1 To 17) As String, colMapping(1 To 17) As String
caseNames(1) = "CB_Name_1": colMapping(1) = "T"
' ... (rest of the mapping) ...
For i = 1 To 17
Set cb = Nothing: isApproved = False
If foundRow <> 0 Then
cellValue = wsSource.Range(colMapping(i) & foundRow).Value
If UCase(Trim(cellValue)) = "OUI" Then isApproved = True
End If
Set cb = Me.CheckBoxes(caseNames(i))
If Not cb Is Nothing Then
cb.Value = IIf(isApproved, xlChecked, xlUnchecked)
End If
Next i
Application.EnableEvents = True
Application.ScreenUpdating = True
End Sub
有没有人遇到过这样的情况:cb.Value 在内部会改变,但视觉上的勾选标记却没有出现?这会不会是显示设置的问题,还是表单控件的某个特定属性?
解决方案
你正在使用无效的值来勾选/取消勾选复选框。xlChecked 和 xlUnchecked 在VBA中未定义。问题在于你没有使用 Option Explicit,这点你应该始终遵循。因此,VBA会“创建”这些值并用 0 初始化它们,这会把勾选框取消选中。启用 Option Explicit 时,编译器会对未知变量报错,很容易发现这个错误。
正确的值分别是 XlOn 用于设置勾选框,XlOff 用于取消勾选。
现在如果我是你,我会尝试在不编程的情况下找到解决方案。不过这要看你的具体需求:用户是应该手动勾选/取消勾选复选框,还是它们应该始终反映 OUI-单元格的状态?(如果用户可以更新勾选框,OUI 单元格的值也应自动改变吗?)
你可以把复选框链接到包含公式的单元格,如 =Sheet2!A1="OUI"。不过,你需要保护这些单元格,否则勾选框改变时,Excel可能会把公式覆盖成 TRUE 或 FALSE。
也可以使用条件格式,或使用像 =IF(Sheet2!A1="X";"R";"£") 这样的简单公式(用WinDings2进行格式化),但同样需要保护公式,以防用户覆盖它。