在任何打开的工作簿中检测刚停用的工作表中的选择类型

时间:2015-01-15 22:08:23

标签: excel vba excel-vba selection worksheet

在更改ActiveSheet编辑:任何公开Workbook )之后,我想要一种方法来查询:

  1. 检测上一个有效工作表中Selection的类型(最重要的是,如果它是ChartObjectRange)。
  2. 如果是Range,请获取地址。
  3. 这可能吗??

    编辑:...(续)

    1. 无需额外激活/取消激活以查询(首选)。
    2. 使用额外的激活/取消激活来查询。
    3. 请注意,向ThisWorkbook添加代码只会影响该工作簿。 所以,我想像Jon Peltier为Chart事件发布的内容可能有用(http://peltiertech.com/chart-events-microsoft-excel/)。 我正在寻找一些原生的Excel VBA(第一选择),或者对我提到的选项或其他选择(第二选择)的一些见解。

      到目前为止,通过使用基于Section 4的代码。应用事件以在the link above的所有工作簿中的所有工作表上启用所有图表,我已设法检测任何工作簿中任何工作表的停用。 然后,我可以想象点 2的代码。使用其他激活/取消激活来查询。 但我不知道第1点。

      (边缘?)相关问题:VBA: Get selected Range in a Worksheet where the Selection is a Chart

2 个答案:

答案 0 :(得分:3)

尝试将其放在ThisWorkbook

Private Sub Workbook_SheetDeactivate(ByVal Sh As Object)

Dim Sh2         As Worksheet
Dim rAddress    As String

Set Sh2 = ActiveSheet

Application.EnableEvents = False
Application.ScreenUpdating = False

Sh.Activate
If TypeName(Selection) = "Range" Then rAddress = Selection.Address
Sh2.Activate

MsgBox rAddress

Application.EnableEvents = True
Application.ScreenUpdating = True

End Sub

修改

要检测任何打开的工作簿中最近停用的工作表的选择类型,请在PERSONAL.XLSB文件中添加以下内容(如果是Windows XP,则为PERSONAL.XLS):

名为cAppEvent的类模块:

Option Explicit
Public WithEvents EventApp As Excel.Application

Private Sub EventApp_SheetDeactivate(ByVal Sh As Object)

Dim wb As Workbook
Dim ws As Worksheet

Set ws = Sh
Set wb = ws.Parent
CheckPreviousSelection ws, wb

End Sub

常规模块,您可以选择任何名称:

Public cXLEvents As New cAppEvent

Sub CheckPreviousSelection(Sh As Worksheet, wb As Workbook)

Dim Sh2 As Worksheet
Dim wb2 As Workbook
Dim r   As Range
Dim cht As ChartObject
Dim chk As Long

Set Sh2 = ActiveSheet
Set wb2 = Sh2.Parent

Application.EnableEvents = False
Application.ScreenUpdating = False

Sh.Activate
If TypeName(Selection) = "ChartArea" Then
    Set cht = Sh.ChartObjects(Right(ActiveChart.Name, Len(ActiveChart.Name) - Len(Sh.Name) - 1))
    chk = 1
ElseIf TypeName(Selection) = "Range" Then
    Set r = Selection
    chk = 2
End If
Sh2.Activate

If chk = 1 Then
    MsgBox wb.Name & vbNewLine & Sh.Name & vbNewLine & cht.Name
    'Do whatever you need to for a chart here.
ElseIf chk = 2 Then
    MsgBox wb.Name & vbNewLine & Sh.Name & vbNewLine & r.Address
    'Do whatever you need to for a range here.
End If

Application.EnableEvents = True
Application.ScreenUpdating = True

End Sub

在ThisWorkbook下:

Private Sub Workbook_Open()

Set cXLEvents.EventApp = Application

End Sub

备注:

  1. 您可能需要关闭Excel并重新打开才能开始工作。
  2. 这将为您提供有关任何打开的工作簿中的工作表之前的选择的信息。但是,如果选择了新工作簿,它将不会为您提供有关上一个选择的信息。如有必要,可以添加更多代码来捕获该部分。
  3. 此方法使用其他激活/取消激活。由于没有Workbook_BeforeSheetDeactivate,我不确定如何在没有额外激活/停用的情况下实现您想要的任何方式。
  4. 这将在您打开的任何工作簿上运行,即使您不希望这样。您很可能希望将ThisWorkbook中的代码更改为以下内容:

    If MsgBox("Turn on AppEvents?", vbYesNo) = vbYes Then Set cXLEvents.EventApp = Application

    或者将其从Workbook_Open事件中取出并仅在您需要时运行它。

答案 1 :(得分:0)

您可以将答案中的所需行为与此问题和其他问题拼凑在一起。

  1. 使用应用程序级事件处理SelectionChangeWorksheetDectivate事件
  2. 使用Chart事件处理工作表上图表的选择
  3. 使用全局变量跟踪当前的选择,无论是
  4. 中的工作表/工作簿
  5. 代码可以放在您选择的工作簿中,如果需要,还可以包含AddIn。
  6. 将此代码放在ThisWorkbook模块

    Private WithEvents App As Application
    Private WithEvents Cht As Chart
    
    Private sel As Variant
    
    
    Private Sub App_SheetActivate(ByVal Sh As Object)
        If Sh.ChartObjects.Count > 0 Then
            Set Cht = Sh.ChartObjects(1).Chart
        Else
            Set Cht = Nothing
        End If
    End Sub
    
    Private Sub Cht_Activate()
        Set sel = Cht
    End Sub
    
    Private Sub Workbook_Open()
        Set App = Application
        Set sel = Selection
        If ActiveSheet.ChartObjects.Count > 0 Then
            Set Cht = ActiveSheet.ChartObjects(1).Chart
        Else
            Set Cht = Nothing
        End If
    End Sub
    
    Private Sub App_SheetSelectionChange(ByVal Sh As Object, ByVal Target As Range)
        Set sel = Selection
    End Sub
    
    Private Sub App_WorkbookActivate(ByVal Wb As Workbook)
        Set sel = Selection
    End Sub
    
    
    Private Sub App_SheetDeactivate(ByVal Sh As Object)
        Debug.Print Sh.Name
        If TypeName(sel) = "Range" Then
            Debug.Print sel.Address
        Else
            Debug.Print TypeName(sel)
        End If
    
        Set sel = Selection
    End Sub