如何引用具有相同名称的图表,但在不同的工作表上?

我有两个包含图表的工作表,并使用macros来运行所有工作表中的图表,并更新绘制的值。

不过,当我试图在第一个图表中引用图表时遇到了一个问题 – 虽然工作表的引用发生了变化,但对图表的引用却没有。

循环如下所示:

For Each ws In ThisWorkbook.Worksheets Debug.Print ws.Name Debug.Print ws.ChartObjects("Kortsone").Chart.Name With ws.ChartObjects("Kortsone").Chart ... End With Next ws 

我得到的直接窗口的输出如下:

 Grafar ovn 3 Grafar ovn 3 Kortsone Grafar ovn 4 Grafar ovn 3 Kortsone 

您可以看到对工作表的引用更改,但图表引用没有。

有没有办法解决这个问题,或者我将不得不重新命名我的所有图表的独特名称?

我正在使用Excel 2013

– 编辑 –我现在已经根据评论中的build议做了一些testing,看起来打印到即时窗口的内容取决于当前活动工作表的内容。

试图for each chartobject遇到了与我以前相同的问题:

 Sub test2() Dim ws As Worksheet Dim ch As ChartObject For Each ws In ThisWorkbook.Worksheets For Each ch In ws.ChartObjects If ws.CodeName = "Graf4" Then Debug.Print ws.Name Debug.Print ch.Name Debug.Print ch.Chart.Name End If Next ch Next ws End Sub 

放弃:

 Grafar ovn 4 Kortsone Grafar ovn 3 Kortsone Grafar ovn 4 Langsone Grafar ovn 3 Langsone ... 

正如您发现的, Workheet.ChartObjects方法将find正确的ChartObject,但访问Chartobject.Chart属性将返回ActiveSheet的图表。 如果通过名称或索引号引用ChartObject,则无关紧要。

如果使用Worksheet.Shapes方法查找ChartObject,则行为是相同的。

此行为与早期版本的Excel不同。 我确认该代码在Excel XP / 2002中工作,并且在2016年不起作用。我不确定行为何时更改。 这可能是2013年,也可能是2013年和2016年的补丁? Office for mac 2016中的行为是相同的(即不起作用)

在Microsoft提出修复之前,您必须先激活工作表或激活ChartObject, 然后才能访问Chart属性。

 Sub test() Dim ws As Worksheet Dim co As ChartObject For Each ws In ThisWorkbook.Worksheets Debug.Print ws.Name Set co = ws.ChartObjects("Kortsone") ws.Activate 'or co.Activate Debug.Print co.Chart.Name With ws.ChartObjects("Kortsone").Chart End With Next ws End Sub 

我build议你暂时禁用ScreenUpdating,并在完成后重新激活最初的活动页面。

GetChart将返回特定工作表上的图表对象。

getChart将图表对象存储在Static CollectionStatic Collection将保留在内存中,直到出现代码中断或工作簿closures。

第一次调用getChart所有的图表对象都会被激活,并且每个工作表上的每个图表都被添加到集合中。 之后,图表只是在静态集合中查找。

在一个图表(例如,在调用该函数后添加了一个图表)不在该集合中的情况下,该函数将自动重新加载。

获取图表

 Function getChart(ChartName As String, WorkSheetName As String, Optional Reload As Boolean) As Chart Dim ws As Worksheet, ActiveWS As Worksheet Dim co As ChartObject Static ChartCollection As Collection If ChartCollection Is Nothing Or Reload Then Application.ScreenUpdating = False Set ChartCollection = New Collection Set ActiveWS = ActiveSheet For Each ws In ThisWorkbook.Worksheets ws.Activate For Each co In ws.ChartObjects ChartCollection.Add co.Chart, ws.Name & "!" & co.Name Next Next ws ActiveWS.Activate Application.ScreenUpdating = True End If On Error Resume Next Set getChart = ChartCollection(WorkSheetName & "!" & ChartName) If Err.Number <> 0 And Not Reload Then Set getChart = getChart(ChartName, WorkSheetName, True) On Error GoTo 0 End Function 

testing

 Sub Test() Dim ws As Worksheet Dim ch As Chart Dim msg As String Dim Start: Start = Timer For Each ws In ThisWorkbook.Worksheets Set ch = getChart("Kortsone", ws.Name) If Not ch Is Nothing Then msg = msg & ws.Name & "!" & ch.Name & " - Validated:" & (ws.Name = ch.Parent.Parent.Name) & vbCrLf End If Next ws msg = msg & "Time in Seconds: " & Timer - Start MsgBox msg End Sub 

ChartWorksheet.ChartObject.Chart是有区别的。

说清楚

  • 当您工作表中创build图表 ,Excel将创build一个ChartObject以包含Chart 。 所以ChartChildObject一个子对象,而ChildObject又是Worksheet一个子对象。
  • 当您创build图表作为图表时,它是一个等同于WorksheetChart (或者您可以称之为“图表”)。

因此, Worksheet.ChartObject.ChartChart不同之处在于:

  • Worksheet.ChartObject.Chart中的Chart包含Chart所有属性。
  • Chart表包含Chart所有属性和工作表的一些属性。

所以.Name属性应该是Chart表,但不适用于Worksheet.ChartObject.Chart

在调用ChartObject.Chart.Name时,我会说额外显示的activesheet名称不是一个错误,而是一个debugging错误。 ChartObject.Chart不会也不应该有一个Name 。 您可以调用ChartObject.Chart.Name因为在Chart对象模型的intellisense中存在重叠。 如果微软没有考虑到这个问题,就会有一个bug。

所以简而言之,请记住, 图表没有名称,它是ChartObject或带有名称的Sheet 。 为了对比,一个图表有ChartTitle