问题
I want a method to inquire, after changing the ActiveSheet
(EDIT: of any open Workbook
):
- Detect the type of
Selection
in the previous active sheet (of most importance, if it was aChartObject
orRange
). - If it is a
Range
, get the address.
Is this possible ...?
EDIT: ... (cont.)
- Without additional Activating/Deactivating to inquire (preferred).
- 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:
- You will probably need to close out of Excel and reopen for this to start working.
- 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.
- 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. 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.
- Use Application level events to handle
SelectionChange
andWorksheetDectivate
events - Use
Chart
events to handle selection of a Chart on a Worksheet - Use a global variable to track the current Selection, whichever worksheet/workbook it's in
- 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