我有两个包含图表的工作表,并使用宏来运行包含图表的所有工作表,并更新图表中的值。
但是,在尝试在第一个工作表之后引用工作表中的图表时遇到问题 - 尽管工作表的引用发生了更改,但对图表的引用却没有。
循环如下:
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
- 编辑 - 我现在根据评论中的建议进行了一些测试,看来打印到即时窗口的内容取决于当前活动工作表的内容。
尝试使用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
...
答案 0 :(得分:5)
正如您所发现的,Workheet.ChartObjects
方法将找到正确的ChartObject,但访问Chartobject.Chart
属性将返回ActiveSheet的图表。如果按名称或索引号引用ChartObject,则无关紧要。
如果使用Worksheet.Shapes
方法查找ChartObject,行为是相同的。
此行为与早期版本的Excel不同。我确认代码在Excel XP / 2002中有效,并且在2016年不起作用。我不确定行为何时发生变化。它可能是2013年,或者它可能是2013年和2016年的补丁? Office for Mac 2016中的行为是相同的(即不起作用)
在Microsoft提出修复之前,您必须激活工作表,或者在访问Chart属性之前激活ChartObject 。
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
我建议您暂时禁用ScreenUpdating,并在完成后重新激活原始活动表。
答案 1 :(得分:1)
getChart
将图表对象存储在Static Collection
中。 Static Collection
将保留在内存中,直到代码中断或工作簿关闭为止。
第一次调用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
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
答案 2 :(得分:0)
Chart
和Worksheet.ChartObject.Chart
之间存在差异。
明确表示
ChartObject
以包含Chart
。因此,Chart
是ChildObject
的孩子,后者又是Worksheet
的孩子。Chart
(或者您可以称之为“图表工作表”),相当于Worksheet
。因此,Worksheet.ChartObject.Chart
与Chart
表格的区别在于以下方式:
Chart
中的Worksheet.ChartObject.Chart
包含图表的所有属性。Chart
工作表包含图表的所有属性和工作表的某些属性。因此.Name
属性应该是Chart
表,而不是Worksheet.ChartObject.Chart
。
我要说调用ChartObject.Chart.Name
时附加显示活动表名称不是错误,而是调试错误。 ChartObject.Chart
首先不会也不应该有Name
。您可以调用ChartObject.Chart.Name
,因为Chart
的对象模型的intellisense中存在重叠。如果微软不允许这样做,就会有一个错误。
简而言之,请记住图表没有名称,ChartObject
或Sheet
带有名称。为了对比,图表有ChartTitle
。