Если вы наберете выражение ActiveSheet.PivotTables("PivotTable2").PivotFields("Meter Read Date").AutoGroup
, вы заметите, что после ActiveSheet.
вы не получите автозаполнения - это потому, что ActiveSheet
не обязательно является Worksheet
, и его тип данных Object
: каждый последующий вызов члена может быть разрешен только во время выполнения.
Это то, что я называю неявное позднее связывание , и это очень распространенная ловушка. .. с довольно простым решением: будьте максимально явным относительно типа данных all и отказывайтесь работать с Object
, если вы не должны .
Dim sheet As Worksheet
Set sheet = ActiveSheet
Теперь мы можем сделать проверенный во время компиляции вызов члена против sheet
. Проблема в том, что .PivotTables.Item
(скрытый, неявный элемент по умолчанию, который принимает параметр "PivotTable2"
) также возвращает Object
- поэтому нам нужна ссылка PivotTable
:
Dim pt As PivotTable
Set pt = sheet.PivotTables("PivotTable2")
Теперь мы можем сделать проверенные вызовы членов во время компиляции против pt
... и видим, что .PivotFields.Item
также дает Object
- поэтому нам нужна ссылка PivotField
:
Dim ptField As PivotField
Set ptField = pt.PivotFields("Meter Read Date")
И теперь мы можем сделать ранний вызов участника ...
ptField.AutoGroup
Теперь, кажется, PivotField.AutoGroup
было введено в Office 2016, так что раннее ограничение вызов участника не будет компилироваться вообще в более ранней версии - потому что член фактически не существует ... что объясняет вашу ошибку 438.
В любом случае, теперь мы можем повторно использовать все эти объекты везде, где они нам нужны, вместо того, чтобы повторно ссылаться на них каждый раз от ActiveSheet
. Ваш код с ранним ограничением, кроме вызова участника AutoGroup
, который будет работать только в том случае, если Excel версии 16.0 или выше:
Dim sheet As Worksheet
Set sheet = ActiveSheet 'TODO See https://rubberduckvba.wordpress.com/2019/12/19/code-name-sheet1/
Dim newSheet As Worksheet
Set newSheet = ActiveWorkbook.Worksheets.Add 'NOTE: .Add returns the new Worksheet object reference
Dim tableName As String
tableName = sheet.ListObjects(1).Name
Dim ptCache As PivotCache
Set ptCache = ActiveWorkbook.PivotCaches.Create( _
SourceType:=xlDatabase, _
SourceData:= tableName, _
Version:=xlPivotTableVersion14)
Dim pt As PivotTable
'NOTE: PivotCache.CreatePivotTable returns the new PivotTable reference
Set pt = ptCache.CreatePivotTable( _
TableDestination:=newSheet.Name & "!R3C1", _
TableName:="PivotTable2", _
DefaultVersion:=xlPivotTableVersion14)
Dim typeField As PivotField
Set typeField = pt.PivotFields("Type")
typeField.Orientation = xlRowField
typeField.Position = 1
Dim meterReadDateField As PivotField
Set meterReadDateField = pt.PivotFields("Meter Read Date")
meterReadDateField.Orientation = xlRowField
meterReadDateField.Position = 2
Dim lateBoundExcel2016 As Object
Set lateBoundExcel2016 = meterReadDateField
If Application.Version >= 16 Then
lateBoundExcel2016.AutoGroup
Else
'PivotField.AutoGroup member is not available in Excel < 2016.
End If
'TODO figure out if these are redundant
typeField.Orientation = xlPageField 'was set to xlRowField above
typeField.Position = 1
meterReadDateField.Orientation = xlPageField 'was set to xlRowField above
meterReadDateField.Position = 1 'was set to 2 above, and TypeField is 1??
Dim yearField As PivotField
Set yearField = pt.PivotFields("Years")
yearField.Orientation = xlHidden
Dim quarterField As PivotField
Set quarterField = pt.PivotFields("Quarters")
quarterField.Orientation = xlHidden
Dim serviceAddressField As PivotField
Set serviceAddressField = pt.PivotFields("Service Street Addr")
serviceAddressField.Orientation = xlRowField
serviceAddressField.Position = 1 'suspicious
Dim mmBtuField As PivotField
Set mmBtuField = pt.PivotFields("MMBtu")
mmBtuField.Orientation = xlRowField
mmBtuField.Position = 2
Dim kwhField As PivotField
Set kwhField = pt.PivotFields("kWh")
pt.AddDataField kwhField, "Sum of kWh", xlSum
Dim thermField As PivotField
Set thermField = pt.PivotFields("Therms")
pt.AddDataField thermField, "Sum of Therms", xlSum
Dim billAmountField As PivotField
Set billAmountField = pt.PivotFields("Bill Amt")
pt.AddDataField billAmountField, "Sum of Bill Amt", xlSum
pt.AddDataField mmBtuField, "Count of MMBtu", xlCount
typeField.ClearAllFilters
typeField.CurrentPage = "Agency Building"
serviceAddressField.AutoSort xlAscending ', serviceAddressField.Name '<~ optional argument is redundant