Как мне сопоставлять диаграммы с тем же именем, но на разных листах?
У меня есть два рабочих листа, содержащих диаграммы, и используйте макрос для запуска по всем листам с диаграммами в них и обновляйте значения, указанные на рисунке.
Однако я столкнулся с проблемой при попытке ссылаться на диаграммы в листах после первого - хотя ссылка на рабочий лист меняется, ссылка на диаграмму не соответствует.
Цикл выглядит следующим образом:
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
- edit - Я уже провел некоторое тестирование на основе предложений в комментариях, и кажется, что то, что напечатано в непосредственном окне, зависит от того, что в настоящее время является активным листом.
Попытка использовать 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
...
Ответы
Ответ 1
Как вы обнаружили, метод Workheet.ChartObjects
найдет правильный ChartObject, но доступ к свойству Chartobject.Chart
вернет диаграмму ActiveSheet. Не имеет значения, ссылаетесь ли вы на объект ChartObject по имени или по индексу.
Поведение такое же, если вы используете метод Worksheet.Shapes
для поиска ChartObject.
Такое поведение отличается от предыдущих версий Excel. Я подтвердил, что код работал в Excel XP/2002 и не работает в 2016 году. Я не уверен, когда поведение изменилось. Возможно, это было 2013 год, или это мог быть патч к 2013 и 2016 годам? Поведение в Office для 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
Я предлагаю вам временно отключить ScreenUpdating и повторно активировать исходную таблицу действий после того, как вы закончите.
Ответ 2
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
Test
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
Ответ 3
Существует разница между Chart
и Worksheet.ChartObject.Chart
.
Выясните, что
- Когда вы создаете таблицу в, Excel создает
ChartObject
, чтобы содержать Chart
. Таким образом, Chart
является дочерним элементом ChildObject
, который, в свою очередь, является дочерним элементом Worksheet
.
- Когда вы создаете таблицу как, это
Chart
(или вы можете называть ее "лист диаграммы" ), эквивалентный Worksheet
.
Поэтому a Worksheet.ChartObject.Chart
отличается от листа Chart
следующим образом:
- A
Chart
from Worksheet.ChartObject.Chart
содержит все свойства диаграммы.
- Лист
Chart
содержит все свойства диаграммы и некоторые свойства листа.
Таким образом, свойство .Name
должно быть для листа Chart
, но не для Worksheet.ChartObject.Chart
.
Я бы сказал, что дополнительное отображение имени activesheet при вызове ChartObject.Chart.Name
не является ошибкой, а отлаженной ошибкой. ChartObject.Chart
не будет и не должен иметь Name
в первую очередь. Вы можете вызвать ChartObject.Chart.Name
, потому что в объектной модели Chart
есть перекрытие в объектной модели intellisense. Если бы Microsoft не допустила этого, была бы ошибка.
Итак, помните, что диаграмма не имеет имени, это ChartObject
или Sheet
, которое несет имя. Чтобы сопоставить это, диаграмма имеет ChartTitle
.