简体   繁体   English

在 Excel 2010 中导致 SheetSelectionChange 事件的 SpecialCells

[英]SpecialCells causing SheetSelectionChange event in Excel 2010

I have a test Macro我有一个测试宏

Sub test()
    Dim rSrcMatrix As Range
    Set rSrcMatrix = Sheets("Code Matrix").Range("Xfer_To_Xfer_Matrix").Range("A1")
    Set rSrcMatrix = rSrcMatrix.Resize(rSrcMatrix.SpecialCells(xlCellTypeLastCell).Row, rSrcMatrix.SpecialCells(xlCellTypeLastCell).Column)     
End Sub

I am using this macro to test my COM addin that I have created in VS2010.我正在使用这个宏来测试我在 VS2010 中创建的COM插件。 I have delegated the SheetSelectionChange event in the addin to some function.我已将插件中的SheetSelectionChange事件委托给一些 function。

Now I notice that whenever I run this macro, Excel fires the SheetSelectionChange event 4 times and my addin calls the associated method for that many times.现在我注意到,每当我运行此宏时,Excel 都会触发SheetSelectionChange事件 4 次,并且我的插件会多次调用关联的方法。

Is there anything that I am missing or is this a bug in excel?有什么我遗漏的,还是 excel 中的错误?

I believe and I could be wrong because I couldn't find an MSDN article to prove it but SpecialCells performs a type of selection and triggers the Worksheet_SelectionChange or the Workbook_SheetSelectionChange event and hence you need to switch off events. 我相信而且我可能是错的,因为我找不到MSDN文章来证明这一点,但是SpecialCells执行一种选择并触发Worksheet_SelectionChangeWorkbook_SheetSelectionChange事件,因此您需要关闭事件。

Here is a simple way to test it. 这是一种简单的测试方法。

Place this code in the Sheet Code Area 将此代码放在工作表代码区域

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    MsgBox "Damn! The SpecialCells caused me to pop up!!!"
End Sub

Sub test()
    Debug.Print ActiveSheet.Cells.SpecialCells(xlCellTypeLastCell).Row
End Sub

Worksheet_SelectionChange and Workbook_SheetSelectionChange do the same job. Worksheet_SelectionChangeWorkbook_SheetSelectionChange做相同的工作。 Worksheet_SelectionChange is used in the sheet code are for a specific sheet. Worksheet_SelectionChange表代码中使用的Worksheet_SelectionChange用于特定的工作表。 And Workbook_SheetSelectionChange is used when you want the event to fire across all the sheets in that workbook. 当您希望事件在该工作簿中的所有工作表上触发时,将使用Workbook_SheetSelectionChange

YOUR QUESTION FROM THE COMMENT : What if we wanted to associate another event with that line of code. 您的评论 :如果我们想将另一个事件与该行代码关联,该怎么办。 In that case, we cannot suppress the event. 在这种情况下,我们无法抑制该事件。

Now, we have two alternatives. 现在,我们有两种选择。 Based on your above question we cannot use Alternative One . 根据您的上述问题,我们无法使用Alternative One So you may directly skip to Alternative 2 因此,您可以直接跳至Alternative 2

ALTERNATIVE 1 替代方案1

Switch Off Events 关闭事件

Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    On Error GoTo Whoa

    Application.EnableEvents = False

    '
    '~~> YOUR CODE
    '

Letscontinue:
    Application.EnableEvents = True
    Exit Sub
Whoa:
    MsgBox Err.Description
    Resume Letscontinue
End Sub

ALTERNATIVE 2 替代方案2

Instead of using SpecialCells to find the last row or the last column, we will use .Find . 而不是使用SpecialCells查找最后一行或最后一列,我们将使用.Find

Sub test()
    Dim ws As Worksheet
    Dim rSrcMatrix As Range
    Dim Lrow As Long, LCol As Long

    Set ws = ThisWorkbook.Sheets("Code Matrix")

    With ws
        If Application.WorksheetFunction.CountA(.Cells) <> 0 Then
            Lrow = .Cells.Find(What:="*", _
                          After:=.Range("A1"), _
                          Lookat:=xlPart, _
                          LookIn:=xlFormulas, _
                          SearchOrder:=xlByRows, _
                          SearchDirection:=xlPrevious, _
                          MatchCase:=False).Row

            LCol = .Cells.Find(What:="*", _
                          After:=.Range("A1"), _
                          Lookat:=xlPart, _
                          LookIn:=xlFormulas, _
                          SearchOrder:=xlByColumns, _
                          SearchDirection:=xlPrevious, _
                          MatchCase:=False).Column
        Else
            Lrow = 1
        End If

        Set rSrcMatrix = .Range("Xfer_To_Xfer_Matrix").Range("A1")
        Set rSrcMatrix = rSrcMatrix.Resize(Lrow, LCol)

        Debug.Print rSrcMatrix.Address
    End With
End Sub

Based on @Siddharth Rout technique, here is a method that will return the last cell of a Worksheet.UsedRange (see my comments below his answer)基于@Siddharth Rout 技术,这是一个返回Worksheet.UsedRange的最后一个单元格的方法(请参阅我在他的回答下方的评论)

Function GetLastCellEmpty(rng As Range) As Range
    Set m_rngCheck = rng

    Set m_rngFound = m_rngCheck.Find(What:="", _
                            LookIn:=XlFindLookIn.xlFormulas, _
                            Lookat:=XlLookAt.xlPart, _
                            SearchDirection:=XlSearchDirection.xlPrevious)
    Set GetLastCellEmpty = m_rngFound
End Function

Function GetLastCellUsedRange(ws As Worksheet) As Range
    Set GetLastCellUsedRange = GetLastCellEmpty(ws.UsedRange.Offset(1, 1)).Offset(-1, -1)
End Function

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM