Excel 捕获图表上的事件单击

Excel 捕获图表上的事件单击,excel,vba,Excel,Vba,单击图表时,我需要在Excel VBA中捕获事件 当图表被激活时,我想把它放在前面,但我找不到合适的事件 对于不在工作表上的图表(单独的全屏图表),存在chart\u Activate()事件 当图表位于某个工作表上时,如何调用同一事件?在工作表中创建处理程序: Public子图表选中(ByVal名称作为字符串) Me.ChartObjects(名称).BringToFront 端接头 右键单击图表并选择Assign macro,然后键入如下内容 'Sheet1.Chart选中“图表1” 其中

单击图表时,我需要在Excel VBA中捕获事件

当图表被激活时,我想把它放在前面,但我找不到合适的事件

对于不在工作表上的图表(单独的全屏图表),存在
chart\u Activate()
事件


当图表位于某个工作表上时,如何调用同一事件?

在工作表中创建处理程序:

Public子图表选中(ByVal名称作为字符串)
Me.ChartObjects(名称).BringToFront
端接头
右键单击图表并选择Assign macro,然后键入如下内容

'Sheet1.Chart选中“图表1”

其中
图表1
是图表的名称

要以编程方式分配此处理程序,请使用

ChartObject.OnAction = "'Sheet1.ChartSelected ""Chart 1""'"

如果您有一组图表需要自动化,无论是在特定的工作表上,还是在整个工作簿上,那么我建议您使用一个类模块来捕获,而不是逐个图表地绑定代码

Jon Peltier(按照正常情况)详细介绍了此图表代码选项,请参阅

在名为CEventChart的类模块中,输入:

Option Explicit
' Declare object of type "Chart" with events
Public WithEvents EvtChart As Chart    

Private Sub EvtChart_Activate()
EvtChart.ChartObjects msoBringToFront
End Sub
在普通模块中,输入

Option Explicit

Dim clsEventChart As New CEventChart
Dim clsEventCharts() As New CEventChart

Sub Set_All_Charts()
    ' Enable events on sheet if it is a chart sheet
    If TypeName(ActiveSheet) = "Chart" Then
        Set clsEventChart.EvtChart = ActiveSheet
    End If

    ' Enable events for all charts embedded on a sheet
    ' Works for embedded charts on a worksheet or chart sheet
    If ActiveSheet.ChartObjects.Count > 0 Then
        ReDim clsEventCharts(1 To ActiveSheet.ChartObjects.Count)
        Dim chtObj As ChartObject
        Dim chtnum As Integer

        chtnum = 1
        For Each chtObj In ActiveSheet.ChartObjects
            ' Debug.Print chtObj.Name, chtObj.Parent.Name
            Set clsEventCharts(chtnum).EvtChart = chtObj.Chart
            chtnum = chtnum + 1
        Next ' chtObj
    End If
End Sub

Sub Reset_All_Charts()
    ' Disable events for all charts previously enabled together
    Dim chtnum As Integer
    On Error Resume Next
    Set clsEventChart.EvtChart = Nothing
    For chtnum = 1 To UBound(clsEventCharts)
        Set clsEventCharts(chtnum).EvtChart = Nothing
    Next ' chtnum
End Sub
然后运行Set_All_Charts,选中要将图表发送到前端的工作表,Jon使用这些工作表事件设置并禁用特定工作表上的图表代码

Private Sub Worksheet_Activate()
    Set_All_Charts
End Sub

Private Sub Worksheet_Deactivate()
    Reset_All_Charts
End Sub

如果我理解这个问题,我也会面临同样的问题。当有多个重叠图表时,它们的可视化优先级遵循
ZOrder

在Excel2003中,当一个人选择一个图表时,它出现在前台(至少为了可视化,我不知道它的
ZOrder
是否被临时更改)。取消选择图表时,其可视化优先级返回“正常”

从Excel2007开始,选中图表时,图表不会临时出现在前台进行可视化,因此,如果它们隐藏在其他图表(或可能是其他
Shape
s)后面,完整查看它们的唯一选项是将它们放在前面。这有两个缺点:1)需要更多的点击,2)丢失(可能是有意的)
ZOrder

甚至在a中提到没有解决方法

我尝试了基于以下内容的解决方案:

  • 检测图表的激活
  • 存储其当前的
    ZOrder
    ,以备将来使用
  • 把它带到前面
  • 取消选择图表后,恢复其原始
    ZOrder
  • 这是基本思想,该方案运行得相当好,有一些小故障。我实际上是基于brettdj在这里引用的代码。 其中一项修改是

    Private Sub EvtChart_Activate()
        Application.EnableEvents = False
        ActivatedChart = EvtChart.name
        If (TypeName(EvtChart.Parent) = "ChartObject") Then
        ' Chart is in a worksheet
          Dim chObj As ChartObject
          Set chObj = EvtChart.Parent
          chObj.BringToFront
        Else
        ' Chart is in its own sheet
        End If
        Application.EnableEvents = True
    End Sub
    
    EvtChart\u停用
    使用类似的方法。
    
    我希望这个想法有用。

    非常简单。将此VBA过程放入常规代码模块:

    Sub ClickChart()
      ActiveSheet.ChartObjects(Application.Caller).BringToFront
    End Sub
    
    将宏
    ClickChart
    分配给您希望具有此行为的所有图表

    当您单击任何图表时,它会移动到工作表上所有其他图表的前面


    发帖后,我看到@timwilliams在对另一个答案的评论中提出了这一点。

    我不清楚你在找什么。如果用户单击了图表,则该图表必须已经位于最前面,否?您也可以只分配选中的图表,而不使用参数,然后使用sub中的Application.Caller获取图表名称。@JonPeltier I将上述代码复制到相应的模块中,并调用Set_All_Charts()。这工作正常,但当我调用Reset_All_Charts时,在Set clsEventChart.EvtChart=Nothing行上出现了一个编译器错误:“Variable not defined”。clsEventChart.EvtChart不是类的属性吗?将类属性设置为Nothing(相对于将类的对象设置为Nothing)意味着什么?为什么有必要。属性是静态成员吗?也许你可以从我的问题中猜到,我对VBA相当陌生。EvtChart并不完全是一种财产。它是类中声明的Chart类型的公共变量。作为类型图表,可以将其设置为实际图表,也可以不设置。错误在于您得到错误的行不属于,或者SetAllCharts需要更详细。如果工作表本身是图表,而不是常规工作表,则使用该行。我将把这个添加到我发布的代码中。@John Peltier。非常感谢你的帮助。我已经注释掉了冒犯性的行,这是有效的,但现在我明白了,哪一个更好。事件处理程序正在工作。工作得太好了,阿莫夫!哎呀,在幕后有很多激活和选择活动。我的代码中没有一个激活或选择,除非使用“set x=ActiveChart”计数。回答得很好!我将这里讨论的代码合并到一个工作演示工作簿中。这可能使许多人更容易理解这是如何工作的。不幸的是,我不能附加文件的答案,所以这里有一个链接