Detect the type of Selection in a Worksheet just deactivated, in any open Workbook

限于喜欢 提交于 2019-12-24 04:41:27

问题


I want a method to inquire, after changing the ActiveSheet (EDIT: of any open Workbook):

  1. Detect the type of Selection in the previous active sheet (of most importance, if it was a ChartObject or Range).
  2. If it is a Range, get the address.

Is this possible ...?

EDIT: ... (cont.)

  1. Without additional Activating/Deactivating to inquire (preferred).
  2. With additional Activating/Deactivating to inquire.

Note that adding code to ThisWorkbook only affects that Workbook. So, I guess that something like what Jon Peltier posted for Chart events may work (http://peltiertech.com/chart-events-microsoft-excel/). I was looking for something native of Excel VBA (first choice), or some insight on the option I mention or another alternative (second choice).

So far, by using code based on Section 4. Application Events to Enable All Charts on All Sheets In All Workbooks of the link above, I have managed to detect deactivation of any Sheet in any Workbook. Then, I can imagine code for point 2. With additional Activating/Deactivating to inquire. But I do not know about point 1.

(Marginally?) related question: VBA: Get selected Range in a Worksheet where the Selection is a Chart


回答1:


Try putting this under 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

EDIT

To detect the type of selection of a recently deactivated worksheet in any open workbook, add the following in your PERSONAL.XLSB file (PERSONAL.XLS if Windows XP):

Class Module named 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

Regular Module with whatever name you would like:

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

Under ThisWorkbook:

Private Sub Workbook_Open()

Set cXLEvents.EventApp = Application

End Sub

Notes:

  1. You will probably need to close out of Excel and reopen for this to start working.
  2. This will give you information on the previous selection across worksheets in any open workbook. However, it will not give you information on the previous selection if a new workbook is selected. More code can be added to capture that piece if necessary.
  3. This method uses additional Activating/Deactivating. Since there is no Workbook_BeforeSheetDeactivate, I'm not sure of a way to accomplish what you want without additional Activating/Deactivating.
  4. This will run on any workbook that you open, even if you do not want it to. You will most likely want to change the code in ThisWorkbook to something like this:

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

    Or take it out of the Workbook_Open event and run it only when you need it.




回答2:


You can piece together the required behaviour from answers to this and your other question.

  1. Use Application level events to handle SelectionChange and WorksheetDectivate events
  2. Use Chart events to handle selection of a Chart on a Worksheet
  3. Use a global variable to track the current Selection, whichever worksheet/workbook it's in
  4. Code can be put in a workbook of your choice, including an AddIn if desired.

Place this code in a ThisWorkbook module

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


来源:https://stackoverflow.com/questions/27973905/detect-the-type-of-selection-in-a-worksheet-just-deactivated-in-any-open-workbo

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!