Проблема создания сводной таблицы на всех машинах - PullRequest
0 голосов
/ 13 февраля 2020

Ошибка времени выполнения '438': объект не поддерживает это свойство или метод

Я создаю макрос Excel, который включает создание сводной таблицы и ее настройку. Макрос отлично работает на моей машине в книге, в которой я его создал, но он не работает на машине, на которой он будет использоваться в основном. Это машины одного типа с одинаковой версией Windows и Microsoft Office.

Ниже приведен фрагмент полной сводной таблицы кода VBA, и строка, которая выдает ошибку: ActiveSheet.PivotTables("PivotTable2").PivotFields("Meter Read Date").AutoGroup

Я подозреваю, что это может быть метод .AutoGroup, но я недостаточно хорошо знаю VBA или недостаточно разбираюсь в макросах, чтобы знать, как это исправить, и никакие другие онлайн-исследования не помогают.

Dim dataname As String
Dim newsheet As String

    dataname = ActiveSheet.ListObjects(1).Name

    Sheets.Add
    newsheet = ActiveSheet.Name

    ActiveWorkbook.PivotCaches.Create(SourceType:=xlDatabase, SourceData:= _
        dataname, Version:=xlPivotTableVersion14).CreatePivotTable TableDestination:=newsheet & "!R3C1", _
        TableName:="PivotTable2", DefaultVersion:=xlPivotTableVersion14
    Sheets(newsheet).Select
    Cells(3, 1).Select
    With ActiveSheet.PivotTables("PivotTable2").PivotFields("Type")
        .Orientation = xlRowField
        .Position = 1
    End With
    With ActiveSheet.PivotTables("PivotTable2").PivotFields("Meter Read Date")
        .Orientation = xlRowField
        .Position = 2
    End With
    ActiveSheet.PivotTables("PivotTable2").PivotFields("Meter Read Date").AutoGroup
    With ActiveSheet.PivotTables("PivotTable2").PivotFields("Type")
        .Orientation = xlPageField
        .Position = 1
    End With
    With ActiveSheet.PivotTables("PivotTable2").PivotFields("Meter Read Date")
        .Orientation = xlPageField
        .Position = 1
    End With
    ActiveSheet.PivotTables("PivotTable2").PivotFields("Years").Orientation = _
        xlHidden
    ActiveSheet.PivotTables("PivotTable2").PivotFields("Quarters").Orientation = _
        xlHidden
    With ActiveSheet.PivotTables("PivotTable2").PivotFields("Service Street Addr")
        .Orientation = xlRowField
        .Position = 1
    End With
    ActiveSheet.PivotTables("PivotTable2").AddDataField ActiveSheet.PivotTables( _
        "PivotTable2").PivotFields("kWh"), "Sum of kWh", xlSum
    ActiveSheet.PivotTables("PivotTable2").AddDataField ActiveSheet.PivotTables( _
        "PivotTable2").PivotFields("Therms"), "Sum of Therms", xlSum
    With ActiveSheet.PivotTables("PivotTable2").PivotFields("MMBtu")
        .Orientation = xlRowField
        .Position = 2
    End With
    ActiveSheet.PivotTables("PivotTable2").AddDataField ActiveSheet.PivotTables( _
        "PivotTable2").PivotFields("Bill Amt"), "Sum of Bill Amt", xlSum
    ActiveSheet.PivotTables("PivotTable2").AddDataField ActiveSheet.PivotTables( _
        "PivotTable2").PivotFields("MMBtu"), "Count of MMBtu", xlCount
    With ActiveSheet.PivotTables("PivotTable2").PivotFields("Count of MMBtu")
        .Caption = "Sum of MMBtu"
        .Function = xlSum
    End With
    ActiveSheet.PivotTables("PivotTable2").PivotFields("Type").ClearAllFilters
    ActiveSheet.PivotTables("PivotTable2").PivotFields("Type").CurrentPage = _
        "Agency Building"
    ActiveSheet.PivotTables("PivotTable2").PivotFields("Service Street Addr"). _
        AutoSort xlAscending, "Service Street Addr"

1 Ответ

2 голосов
/ 13 февраля 2020

Если вы наберете выражение 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
...