Excel VBA - ActiveX列表框行为 - 正在清除的选择

时间:2016-03-01 17:45:02

标签: excel excel-vba listbox activex named-ranges vba

我试图找出一对ActiveX多选列表框的问题。

  1. 这些列表框位于不同的工作表上,但我将它们设置为在两者之间的鼠标向上同步值。
  2. 这些调用函数来同步这两个,然后更新单元格以保留选择。
  3. 因为写入工作表会导致Excel计算,所以我必须恢复这些选择。
  4. 出于某种原因,一切似乎都能正常工作,除非我从"摘要"的第二个框中运行它。片材。

    简而言之,使用调试器的断点运行第二个框的MouseUp事件代码。只是在没有断点的情况下触发事件将使一切正常,但是在一两秒之后,选择将被清除。

    我可以确认,从那时起重新运行代码以恢复选择将正常工作。此时的所有其他行为都按预期工作。只有当MouseUp事件被触发(没有断点)时,它才会导致某些事件清除选择。 (我现在相信这是重新启用事件后的工作表计算...虽然我认为这也会在调试中发生...)

    更新1:在设置EnableEvents为true后,我找到了与存储选择的工作表相关的解决方法。因此我插入了Sheet(...).Calculate,如下所示,现在按预期工作。这种行为似乎很奇怪,所以我想看看是否有其他人遇到过这样的事情。为什么即使在禁用事件时进行了更改,工作表也会重新计算?由于某些原因,暂时禁用计算似乎也没有做到,尽管我没有花太多时间来测试这个想法(它似乎创造了比修复更多的问题)。

    更新和解决方案:

    这个问题与我原先的想法不同。我发现它与同步无关,实际上与列表框在不同的工作表上有关。两者都指的是动态范围(我忘了提及),这实际上与动态范围重新计算的方式有关(从而重置列表框)。最初,当我有一个盒子时,我通过不传递命名范围的盒子来解决这个问题,但是每次因为导入数据而更新范围的地址(或者使用就地控制进行调整)。

    此框与动态范围位于同一页面上,而另一个则不是,这意味着我无法传递地址(ActiveX控件不会在" Linked Cell&#34中使用工作表引用;),所以我决定提到指定的范围。这再次引入了我所见过的问题,在这个问题出现之前,我的许多解决方法都处理了其他症状。

    我能够通过制造另一个“停滞不前”来解决这个问题。命名范围,当我的其他宏更新时,我会更新引用以指向原始命名范围,从而阻止它重新计算(并重置我的列表框)。希望这对某人有帮助。

    box1:LegSections2Check

    Private Sub LegSections2Check_MouseUp(ByVal Button As Integer, _ 
                         ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    
        Application.EnableEvents = False
        Application.ScreenUpdating = False
        Call SyncChoices(Sheets("Loads"))
        Retain_Selections SetUp:=True
        Retain_Selections SetUp:=False
        Application.ScreenUpdating = True
        Application.EnableEvents = True
    
    End Sub
    

    box2:LegSections2Check2

    Private Sub LegSections2Check2_MouseUp(ByVal Button As Integer, _ 
                         ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    
        Application.EnableEvents = False
        Application.ScreenUpdating = False
        Call SyncChoices(Sheets("Summary"))
        Retain_Selections SetUp:=True
    
        'Sheets("Loads").Calculate     '*** This seems to resolve the issue, although _
                                       ' I can't seem to resolve it by setting_ 
                                       ' Application.Calculation to manual in the functions _
                                       ' (this actually broke more things, haha)   
    
        Retain_Selections SetUp:=False
        Application.ScreenUpdating = True
        Application.EnableEvents = True
    
    End Sub
    

    SyncChoices(检测编辑框所在的工作表并更新另一个框):

    Sub SyncChoices(ByVal mySheet As Worksheet)
    Dim i As Integer
        If mySheet.Name = "Loads" Then
            With ActiveWorkbook.Sheets("Loads").LegSections2Check
                For i = 0 To .ListCount - 1
                    If .Selected(i) Then
                        ActiveWorkbook.Sheets("Summary").LegSections2Check2.Selected(i) = True
                    ElseIf Not .Selected(i) Then
                        ActiveWorkbook.Sheets("Summary").LegSections2Check2.Selected(i) = False
                    End If
                Next
            End With
        ElseIf mySheet.Name = "Summary" Then
            With ActiveWorkbook.Sheets("Summary").LegSections2Check2
                For i = 0 To .ListCount - 1
                    If .Selected(i) Then
                        ActiveWorkbook.Sheets("Loads").LegSections2Check.Selected(i) = True
                    ElseIf Not .Selected(i) Then
                        ActiveWorkbook.Sheets("Loads").LegSections2Check.Selected(i) = False
                    End If
                Next
            End With
        End If
    End Sub
    

    Retain_Selections功能:

    Sub Retain_Selections(ByVal SetUp As Boolean)
    'Dim myListBox As ListBox
    Dim i As Integer
    Dim MyVals As String
    Dim Selections() As String
    Dim offset As Integer
    Dim myCount As Integer
    
        With ActiveWorkbook.Sheets("Loads").LegSections2Check
            RefColumn = ActiveWorkbook.Sheets("Loads").Range("RefCol").Column
            If SetUp Then
                ActiveWorkbook.Sheets("Loads").Cells(2, RefColumn).Value = GetSelections()
            Else
                Selections = Split(ActiveWorkbook.Sheets("Loads").Cells(2, RefColumn).Value, ", ")
                ClearSelectedSections
                myCount = .ListCount
                ActiveWorkbook.Sheets("Summary").LegSections2Check2.ListFillRange = "LegsSections"
                If UBound(Selections) > 0 Then If Selections(UBound(Selections)) * 1 > myCount - 1 Then offset = 1: ExtraRow = True
                For i = 0 To UBound(Selections) - offset
                    .Selected(Selections(i)) = True
                    ActiveWorkbook.Sheets("Summary").LegSections2Check2.Selected(Selections(i)) = True
                Next i
            End If
        End With
    

    GetSelections()函数:

    Function GetSelections()
    Dim i As Integer
    Dim MyVals As String
    With ActiveWorkbook.Sheets("Loads").LegSections2Check
        For i = 0 To .ListCount - 1
            If .Selected(i) = True Then
                If MyVals = "" Then
                    MyVals = i
                Else
                    MyVals = MyVals & ", " & i
                End If
            End If
        Next i
    End With
    GetSelections = MyVals
    End Function
    

    表格的代码' WorkSheet_Activate

    "载荷和#34;

    Private Sub Worksheet_Activate()
        Retain_Selections Setup:=False
    End Sub
    

    "总结"

    Sub Worksheet_Activate()
        Retain_Selections Setup:=False
    End Sub
    

1 个答案:

答案 0 :(得分:0)

禁用事件时,不会关闭自动计算。 Excel引用单独的工作簿 - 全局属性来确定工作簿是否需要重新计算。所以你必须自己禁用/启用autocalc。

所以,有两件事:

除了暂时禁用事件外,我的“标准”实用程序功能还可选择将AutoCalc设置为手动Application.Calculation = xlManual,以确保在允许计算之前完成所有宏。

此外,如果您的列表框位于不同的工作表上,则在用户激活该工作表之前,没有理由重新填充非活动工作表上的列表框。在这种情况下,当用户选择该表时,我会在每张表上使用Worksheet_Activate()事件来填充列表框。

第二件事的推论:如果您的代码依赖于列表框中的项目列表作为部分代码中使用的“过滤器”,请考虑创建一个命名范围作为填充每个列表框的数据。此方法意味着您只更新工作表上的单元格区域,并且列表框在激活时会自动选择它。