【问题标题】:Delete named ranges used for chart series when deleting the chart删除图表时删除用于图表系列的命名范围
【发布时间】:2020-05-03 15:49:08
【问题描述】:

在删除图表时,有什么方法可以删除图表系列中使用的命名范围? 我在日常工作中非常广泛地使用命名范围,也用于制图。当我创建图表时,我经常命名数据范围,然后将它们用于图表系列。

我正在寻找一种在删除图表时删除 USED 命名范围的方法。我想过图表“删除”事件,但我找不到任何关于它的信息(它甚至存在吗???)。 第二个问题是如何确定图表系列使用了哪些范围?删除命名范围很容易,但如何真正确定图表系列中使用了哪些范围?

非常感谢所有帮助。抱歉,我无法为您提供任何代码,因为我不知道如何设置

【问题讨论】:

  • 如果命名范围用于图表系列和图表系列以外的东西怎么办?
  • @SmileyFtW 不删就好了,但是如果让代码更简单的话可以删。我的一般用途命名范围以“常识”方式调用,例如“Input_discount_rate”,而我倾向于使用更复杂的图表名称来避免您正在谈论的这种重复......如果您知道如何检测到复制然后它只会使代码更适用于一般目的,而不仅仅是我的特定需求。
  • @NareshBhople 感谢您的链接。然而,它对我没有帮助。我不知道如何提取在我的图表系列中用作值的命名范围的名称。或者反过来 - 如何遍历所有命名范围(我知道怎么做)并删除那些具有特定前缀且未在图表中使用的范围。例如,遍历所有以“Chart_”前缀开头的名称并检查这些名称是否在图表中使用。如果没有,则删除它们。我想在图表本身被删除时自动执行此操作(此处 chart.delete 事件开始发挥作用),但我可以没有它。
  • SO 可以帮助您修复特定错误(代码不会运行或给出意外结果)。请编写一些代码来做你想做的事情,然后当它不做你想做的事情时,在这里发布并解释问题。
  • @SmileyFtW 我知道 SO 的目的,我并不是故意粗鲁之类的。我很乐意提供代码,但我找不到有关图表删除事件的任何信息。这就是为什么我决定在这里写一个问题。

标签: excel vba events named-ranges


【解决方案1】:

请尝试下一个代码。无法直接提取 USED 命名范围。我使用了一个技巧来从SeriesCollection 公式中提取范围。然后将它们与名称RefersToRange.Address 进行比较并删除匹配的名称。它(现在)在匹配的情况下返回一个布尔值(仅在即时窗口中查看它),但对于您的目的不是必需的。该代码还删除了无效名称(丢失了它们的引用)。

已编辑:我做了一些研究,恐怕无法创建BeforeDelete event... 它是能够为图表对象创建的事件的枚举,但缺少这个。我愿意相信我找到了解决您问题的方法:

  1. 创建一个能够启用BeforeRightClick 事件的类。将其命名为CChartClass 并编写下一段代码:

    Option Explicit

    Public WithEvents ChartEvent As Chart

    Private Sub ChartEvent_BeforeRightClick(Cancel As Boolean) Dim msAnswer As VbMsgBoxResult msAnswer = MsgBox("Do you like to delete the active chart and its involved Named ranges?" & vbCrLf & _ " If yes, please press ""Yes"" button!", vbYesNo, "Chart deletion confirmation") If msAnswer <> vbYes Then Exit Sub Debug.Print ActiveChart.Name, ActiveChart.Parent.Name testDeleteNamesAndChart (ActiveChart.Parent.Name) End Sub

  2. 创建另一个能够处理工作簿和工作表事件的类,将其命名为 CAppEvent 并复制下一个代码:

    Option Explicit

    Public WithEvents EventApp As Excel.Application

    Private Sub EventApp_SheetActivate(ByVal Sh As Object) Set_All_Charts End Sub

    Private Sub EventApp_SheetDeactivate(ByVal Sh As Object) Reset_All_Charts End Sub

    Private Sub EventApp_WorkbookActivate(ByVal Wb As Workbook) Set_All_Charts End Sub

    Private Sub EventApp_WorkbookDeactivate(ByVal Wb As Workbook) Reset_All_Charts End Sub

  3. 将下一个代码放在标准模块中(需要创建一个类数组才能启动所有现有工作表嵌入图表的事件):

Option Explicit

Dim clsAppEvent As New CAppEvent
Dim clsChartEvent As New CChartClass
Dim clsChartEvents() As New CChartClass

Sub InitializeAppEvents()
  Set clsAppEvent.EventApp = Application
  Set_All_Charts
End Sub

Sub TerminateAppEvents()
  Set clsAppEvent.EventApp = Nothing
  Reset_All_Charts
End Sub

Sub Set_All_Charts()
    If ActiveSheet.ChartObjects.Count > 0 Then
        ReDim clsChartEvents(1 To ActiveSheet.ChartObjects.Count)
        Dim chtObj As ChartObject, chtnum As Long

        chtnum = 1
        For Each chtObj In ActiveSheet.ChartObjects
            Set clsChartEvents(chtnum).ChartEvent = chtObj.Chart
            chtnum = chtnum + 1
        Next
    End If
End Sub

Sub Reset_All_Charts()
    ' Disable events for all charts
    Dim chtnum As Long
    On Error Resume Next
     Set clsChartEvent.ChartEvent = Nothing
     For chtnum = 1 To UBound(clsChartEvents)
        Set clsChartEvents(chtnum).ChartEvent = Nothing
     Next ' chtnum
    On Error GoTo 0
End Sub

Sub testDeleteNamesAndChart(strChName As String)
  Dim rng As Range, cht As Chart, sFormula As String
  Dim i As Long, j As Long, arrF As Variant, nRng As Range

  Set cht = ActiveSheet.ChartObjects(strChName).Chart
  For j = 1 To cht.SeriesCollection.Count
    sFormula = cht.SeriesCollection(j).Formula: Debug.Print sFormula
    arrF = Split(sFormula, ",")
    For i = 0 To UBound(arrF) - 1
        If i = 0 Then
            Set nRng = Range(Split((Split(sFormula, ",")(i)), "(")(1))
        Else
            Set nRng = Range(Split(sFormula, ",")(i)) '(1)
        End If
        Debug.Print nRng.Address, matchName(nRng.Address)
    Next i

  ActiveSheet.ChartObjects(strChName).Delete
End Sub

Private Function matchName(strN As String) As Boolean
   Dim Nm As Name, strTemp As String
   For Each Nm In ActiveWorkbook.Names
     On Error Resume Next
        strTemp = Nm.RefersToRange.Address
        If Err.Number <> 0 Then
            Err.Clear
            Nm.Delete
        Else
            If strN = strTemp Then
                Nm.Delete
                matchName = True: Exit Function
            End If
        End If
    On Error GoTo 0
  Next
End Function
  1. 使用ThisWorkbook 模块中的下一个事件代码:

    Option Explicit

    Private Sub Workbook_Open() InitializeAppEvents End Sub

    Private Sub Workbook_BeforeClose(Cancel As Boolean) TerminateAppEvents End Sub

请确认它是否按您的需要工作

【讨论】:

  • 这就是我要找的。我找不到提取名称的方法,但是您的想法很好,非常感谢。也许您可以帮助解决我的第二个问题-您知道是否有任何方法可以通过 VBA 创建某种“图表删除”事件? Link我只找到了这个文档,它没有提到删除事件。这个事件对我有很大帮助,因为当我想删除特定图表时,我可以自动化整个过程。
  • (第二条评论)我曾尝试使用专用的类模块来执行此操作,但是在删除图表时没有运行宏的内置选项。您或阅读本文的任何人是否知道在删除图表时自动运行某些东西的任何方法?
  • @Rafał Kowalski:图表对象没有这样的事件,在 VBA 中创建自定义事件也不是那么简单......即使是这样,您也必须创建 BeforeDelete 事件.否则,您无法从已删除对象中获取任何信息,即使您使其引发此类事件。但是,我认为,您也可以在识别要删除的图表对象后将我的第一个子函数转换为要调用的函数。它将采用图表对象之类的参数。并且以这种方式使用它就不需要任何事件。
  • 这就是我的想法,很遗憾...您能否详细说明一下您的功能想法。如果我理解正确,您需要手动运行此函数来删除图表和相关名称,因为没有 Delete/BeforeDelete 事件就无法自动执行它吗?
  • @Rafał Kowalski:但是,如果我的代码回答了您的问题,那么勾选左侧复选框以使其被接受是正常的。这样,其他提出类似问题的人就会知道它有效。无论如何,图表对象不存在删除事件...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-30
  • 1970-01-01
  • 2014-08-30
  • 2023-03-15
  • 1970-01-01
相关资源
最近更新 更多