我有两个工作表包含图表,并使用宏运行所有工作表中的图表,并更新绘制的值。
但是,在尝试引用第一个工作表之后的图表时,我遇到了一个问题--尽管工作表的引用发生了更改,但对图表的引用却没有改变。
循环如下所示:
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
...发布于 2016-09-10 08:42:06
正如您已经发现的,Workheet.ChartObjects方法将找到正确的ChartObject,但是访问Chartobject.Chart属性将返回ActiveSheet的图表。您是否按名称或索引号引用ChartObject并不重要。
如果使用Worksheet.Shapes方法查找ChartObject,则行为是相同的。
此行为与早期版本的Excel不同。我确认该代码在Excel /2002中有效,在2016年不起作用。我不确定行为是什么时候改变的。可能是2013年,还是2013年和2016年的补丁?2016年Office for mac的行为也是一样的(即。不起作用)
在微软想出解决方案之前,你必须先激活工作表,或者激活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,并在完成之后重新激活原来的激活表。
发布于 2016-09-14 13:43:57
GetChart将在特定工作表上返回图表对象。
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发布于 2016-09-17 01:02:57
Chart和Worksheet.ChartObject.Chart是有区别的。
清楚地表明
Chart的ChartObject。因此,Chart是ChildObject的子代,而后者又是Worksheet的子代。Chart (或者您可以称它为“图表表”),相当于Worksheet。因此,Worksheet.ChartObject.Chart与Chart工作表的区别如下:
Chart的Worksheet.ChartObject.Chart包含图表的所有属性。Chart工作表包含图表的所有属性和工作表的某些属性。所以.Name属性应该是Chart工作表的属性,而不是Worksheet.ChartObject.Chart的属性。
我想说,调用ChartObject.Chart.Name时激活表名称的附加显示不是bug,而是调试过的bug。ChartObject.Chart一开始不会也不应该有一个Name。您可以调用ChartObject.Chart.Name,因为在Chart的对象模型intellisense中存在重叠。如果微软没有考虑到这一点,就会有一个bug。
所以简单地说,记住一个图表没有名字,是ChartObject Sheet 或Sheet,它的名字是。对比一下,图表中有ChartTitle。
https://stackoverflow.com/questions/38916459
复制相似问题