在Excel中使用VBA循环复选框非常慢

Posted

技术标签:

【中文标题】在Excel中使用VBA循环复选框非常慢【英文标题】:Looping over checkboxes with VBA in Excel very slow 【发布时间】:2019-04-12 23:45:09 【问题描述】:

我有一个包含大约 4500 个复选框的 Excel 表(我知道,这听起来很愚蠢,但它是给客户的,请不要问...)。 只需在下面编写 VBA Sub 以取消选中所有框。到目前为止它可以工作,但速度非常慢,需要超过 5 分钟才能取消选中所有 boces,并且在 Sub 运行时,整个 Excel Applikation 灰显冻结。我知道,4500 Checkboxes 很安静,但我想知道它是否真的足以让 Excel 陷入这样的麻烦......有没有人有想法?

最好的 迈克尔

Sub DeselectAll()
   Application.EnableCancelKey = False
   Application.Calculation = xlCalculationManual
   Application.ScreenUpdating = False
   Application.EnableEvents = False
   Dim wksA As Worksheet
   Dim intRow As Integer

   Set wksA = Worksheets("Companies")
   For intRow = 1 To 4513
      wksA.CheckBoxes("Checkbox_" & intRow).Value = False
   Next
 End Sub

【问题讨论】:

这有帮助吗: If wksA.CheckBoxes("Check box " & intRow).Value = xlOn Then wksA.CheckBoxes("Check box " & intRow).Value = xlOff .+Don'不要忘记重新开始您的活动。 不,只有复选框 您可能对我的帖子感兴趣:CheckedRange Class。我认为这比用这么多复选框使您的工作簿臃肿更好。 【参考方案1】:

详细阐述@Ahmed AU 解决方案。

选择/取消选择信号/多个虚拟复选框

Private Sub Worksheet_SelectionChange(ByVal Target As Range)

Dim isect As Range
Dim Cl As Range
Dim Prvsel As Range
Set isect = Application.Intersect(Target, Range("C1:C4000"))
If isect Is Nothing Then
Set Prvsel = Nothing  'Release multiple selection
Exit Sub
End If

' Use WINGDING font Chr (254) for checked
' Use WINGDING font Chr (111) for uncheck

If isect.Cells.Count >= 1 Then
Set Prvsel = isect        
    For Each Cl In Prvsel.Cells
            If Cl.Value = Chr(111) Then
                Cl.Value = Chr(254)
                Else
                Cl.Value = Chr(111)
            End If
    Next Cl
End If
'Go to offset cell selection
       Selection.Offset(0, 1).Select
    End Sub

【讨论】:

【参考方案2】:

我赞成的最佳答案是@EvR 解决方案。我不是想回答,而是提供一个解决方法的想法。

我通过一个简单的 3 行循环在空白工作簿中的空白工作表中添加 4000 ComboBox 来检查时间(天哪,我忘了关闭屏幕更新和计算等)。在我的旧笔记本电脑上花了大约 10 分钟。我没有勇气再重蹈覆辙。

当我尝试使用带有循环的代码时,它只需要 3-4 秒,而 @EvR 的解决方案没有循环和选择需要 1-2 秒。这些时间是Debug.Print 或写入某些单元格的实际时间。屏幕更新、计算、事件在工作表激活的情况下启用后,实际的戏剧就会展开。它变得非常不稳定,任何不小心的点击等都会导致 excel 进入“无响应”状态 2-5 分钟。

尽管客户和老板总是对的。在我的一生中,有一次我成功地将工作表上数百个按钮的类似方法说服了一些虚拟的东西。我的想法是在工作表中创建虚拟复选框。适当的单元格大小和边框,将单元格验证为 `=ChrW(&H2714)' 并忽略空白,如下所示的简单代码可以使其成为一种传递类型的解决方法。

Public Prvsel As Range
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim isect, Cl As Range
Set isect = Application.Intersect(Target, Range("C1:C4000"))

    If isect Is Nothing Then
    Set Prvsel = Nothing  'Release multiple selection
    Exit Sub
    End If

    If isect.Cells.Count > 1 Then
    Set Prvsel = isect        'storing multiple selection for next click event
    Else
        If Target.Value = ChrW(&H2714) Then
        Target.Value = ""
        Else
        Target.Value = ChrW(&H2714)
        End If
        If Not Prvsel Is Nothing Then
            For Each Cl In Prvsel.Cells
            Cl.Value = Target.Value
            Next Cl
        End If
    End If
End Sub

【讨论】:

看了这篇文章后我也有类似的想法。你可能对我的帖子感兴趣:CheckedRange Class。我喜欢您的 ChrW(&H2714) 与过滤器配合使用的方式。 @TinMan 我对你的帖子感到不知所措。它很棒,很棒。当然会非常有用 一个建议将您的显示名称更改为“GoldMan”而不是“TinMan”【参考方案3】:

没有选择:

Sub DeselectAll()
  With Worksheets("Companies").CheckBoxes
   .Value = xlOff
  End With
End Sub

【讨论】:

这正是我想要的。非常感谢您的所有回答。【参考方案4】:

只是不要循环。

这是选择可以提供帮助的一个很好的例子:

设置所有复选框:

Sub dural()
    ActiveSheet.CheckBoxes.Select
    Selection.Value = xlOn
End Sub

取消选中所有复选框:

Sub dural2()
    ActiveSheet.CheckBoxes.Select
    Selection.Value = xlOf
End Sub

(在表单类型的复选框上测试)

【讨论】:

无选择:Sub dural() With ActiveSheet.CheckBoxes .Value = xlOff End With End Sub Nice GS 不用Select,直接赋值即可:activesheet.checkboxes.value = xlOff @EvR 谢谢....因为分组对象的主题很有趣,考虑发布您的想法。 @FunThomas 谢谢....因为分组对象的主题很有趣,请考虑发布您的想法。

以上是关于在Excel中使用VBA循环复选框非常慢的主要内容,如果未能解决你的问题,请参考以下文章

Excel VBA用户表单使用复选框将数据输入多行

使用VBA获取Excel中所有复选框的值

使用 VBA 宏从 Excel 工作簿中取消选择所有复选框

如何使用 VBA 从 Excel 用户窗体中读取复选框的值

VBA 灰色复选框

如何从 VBA Access 中勾选 Excel 复选框