Воссоздайте исходные данные из кэша сводных таблиц

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

ThisWorkbook.Sheets.Add.Cells(1,1).CopyFromRecordset ThisWorkbook.PivotCaches(1).Recordset

Документация указывает, что PivotCache.Recordset является типом ADO, так что это должно работать. У меня включена библиотека ADO в ссылках.

Любые предложения о том, как этого добиться?


person Kuyenda    schedule 18.09.2009    source источник
comment
Каково значение во время выполнения ThisWorkbook.PivotCaches(1).Recordset?   -  person shahkalpeshp    schedule 18.09.2009
comment
Это набор записей с числом записей = 49, но если я попытаюсь сделать следующее, я также получу ошибку, определяемую приложением или объектом: Dim objRecordset As ADODB.Recordset Set objRecordset = ThisWorkbook.PivotCaches(1).Recordset   -  person Kuyenda    schedule 18.09.2009
comment
Поместите ThisWorkbook.PivotCaches(1).Recordset в окно наблюдения, чтобы узнать, какой именно это тип. Это должно помочь.   -  person shahkalpeshp    schedule 18.09.2009
comment
Во время выполнения тип переменной — Integer/Variant. Конечно, objRecordset — это тип набора записей. Как только приложение запускает ThisWorkbook.PivotCaches(1).Recordset, в окне просмотра отображается ошибка, определяемая приложением или объектом. Приводит меня к мысли, что, возможно, я забыл ссылку. Возможно, что-то конкретное для PivotCache? Спасибо за вашу помощь.   -  person Kuyenda    schedule 18.09.2009


Ответы (3)


К сожалению, похоже, что нет возможности напрямую манипулировать PivotCache в Excel.

Я нашел работу вокруг. Следующий код извлекает кэш сводной таблицы для каждой сводной таблицы, найденной в книге, помещает ее в новую сводную таблицу и создает только одно поле сводной таблицы (чтобы убедиться, что все строки из кэша сводной таблицы включены в общую сумму), а затем запускает ShowDetail, который создает новый лист со всеми данными сводной таблицы.

Я все еще хотел бы найти способ работать напрямую с PivotCache, но это выполняет свою работу.

Public Sub ExtractPivotTableData()

    Dim objActiveBook As Workbook
    Dim objSheet As Worksheet
    Dim objPivotTable As PivotTable
    Dim objTempSheet As Worksheet
    Dim objTempPivot As PivotTable

    If TypeName(Application.Selection) <> "Range" Then
        Beep
        Exit Sub
    ElseIf WorksheetFunction.CountA(Cells) = 0 Then
        Beep
        Exit Sub
    Else
        Set objActiveBook = ActiveWorkbook
    End If

    With Application
        .ScreenUpdating = False
        .DisplayAlerts = False
    End With

    For Each objSheet In objActiveBook.Sheets
        For Each objPivotTable In objSheet.PivotTables
            With objActiveBook.Sheets.Add(, objSheet)
                With objPivotTable.PivotCache.CreatePivotTable(.Range("A1"))
                    .AddDataField .PivotFields(1)
                End With
                .Range("B2").ShowDetail = True
                objActiveBook.Sheets(.Index - 1).Name = "SOURCE DATA FOR SHEET " & objSheet.Index
                objActiveBook.Sheets(.Index - 1).Tab.Color = 255
                .Delete
            End With
        Next
    Next

    With Application
        .ScreenUpdating = True
        .DisplayAlerts = True
    End With

End Sub
person Kuyenda    schedule 21.09.2009
comment
Это отличный обходной путь, спасибо за публикацию. Я только что попробовал это в Excel 2010 и по какой-то причине получил ошибку в строке .ShowDetail. Однако затем я мог бы вручную выполнить ShowDetails (через контекстное меню пользовательского интерфейса) в сводной таблице с одной ячейкой, сгенерированной этим кодом, и получить новый лист, созданный таким образом. - person David Korn; 20.10.2012
comment
По крайней мере, в Excel 2010 строка: .Range(B2).ShowDetail = True на самом деле должна быть: .Range(A2).ShowDetail = True (A2, а не B2) - person tbone; 10.07.2013

Перейдите в окно Immediate и введите

?thisworkbook.PivotCaches(1).QueryType

Если вы получите значение, отличное от 7 (xlADORecordset), то свойство Recordset не применяется к этому типу PivotCache и вернет эту ошибку.

Если вы получите сообщение об ошибке в этой строке, значит, ваш PivotCache вообще не основан на внешних данных.

Если ваши исходные данные поступают из ThisWorkbook (т. е. данные Excel), вы можете использовать

?thisworkbook.PivotCaches(1).SourceData

Чтобы создать объект диапазона и прокрутить его.

Если ваш QueryType равен 1 (xlODBCQuery), то SourceData будет содержать строку подключения и командный текст, которые вы должны создать, и набор записей ADO, например:

Sub DumpODBCPivotCache()

    Dim pc As PivotCache
    Dim cn As ADODB.Connection
    Dim rs As ADODB.Recordset

    Set pc = ThisWorkbook.PivotCaches(1)
    Set cn = New ADODB.Connection
    cn.Open pc.SourceData(1)
    Set rs = cn.Execute(pc.SourceData(2))

    Sheet2.Range("a1").CopyFromRecordset rs

    rs.Close
    cn.Close

    Set rs = Nothing
    Set cn = Nothing

End Sub

Вам нужна ссылка ADO, но вы сказали, что у вас уже есть этот набор.

person Dick Kusleika    schedule 18.09.2009
comment
Debug.Print ThisWorkbook.PivotCaches(1).QueryType выдает ошибку. PivotCaches(1).SourceData возвращает путь к внешней книге, в которой хранились исходные данные. Сводная таблица была создана с использованием данных из внешней книги (сводная таблица (1). SaveData имеет значение True), которая с тех пор была удалена. Я хочу воссоздать исходные данные из сводного кеша. Когда вы говорите создать объект диапазона из SourceData и пройтись по нему, я предполагаю, что вы имеете в виду использование Range(SourceData) для ссылки на объект диапазона, указанный SourceData, но это недоступно для меня. Спасибо за вашу помощь. - person Kuyenda; 19.09.2009
comment
Если дважды щелкнуть ячейку в сводной таблице или щелкнуть правой кнопкой мыши и выбрать «Показать подробности», Excel экспортирует исходные данные для этого расчета в новую электронную таблицу в той же книге. Однако вы можете делать это только по одной ячейке за раз. Мне нужно сделать это для всей сводной таблицы, а затем автоматизировать процесс. - person Kuyenda; 19.09.2009

У меня возникла та же проблема: мне нужно было программно очищать данные, поступающие из разных Excel с кэшированными сводными данными. Хотя тема немного устарела, похоже, прямого доступа к данным нет.

Ниже вы можете найти мой код, который является более обобщенным усовершенствованием уже опубликованного решения.

Основное отличие заключается в удалении фильтров из полей, так как иногда сводка поставляется с включенными фильтрами, и если вы вызовете .Showdetail, отфильтрованные данные будут пропущены.

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

Надеюсь, это полезно.

Отдайте ссылку на spadsheetguru.com в процедуре очистки фильтра (хотя, если честно, я не помню, сколько оригинала и сколько моего)

Option Explicit

        Sub ExtractPivotData(wbFullName As String, Optional wbSheetName As_
 String, Optional wbPivotName As String, Optional sOutputName As String, _
Optional sSheetOutputName As String)

    ' This routine extracts full data from an Excel workbook and saves it to an .xls file.

    Dim iPivotSheetCount As Integer

Dim wbPIVOT As Workbook, wbNEW As Workbook, wsPIVOT As Worksheet
Dim wsh As Worksheet, piv As PivotTable, pf As PivotField
Dim sSaveTo As String

Application.DisplayAlerts = False
calcOFF

Set wbPIVOT = Workbooks.Open(wbFullName)

    ' loop through sheets
    For Each wsh In wbPIVOT.Worksheets
        ' if it is the sheet we want, OR if no sheet specified (in which case loop through all)
        If (wsh.name = wbSheetName) Or (wbSheetName = "") Then
            For Each piv In wsh.PivotTables

            ' remove all filters and fields
            PivotFieldHandle piv, True, True

            ' make sure there's at least one (numeric) data field
            For Each pf In piv.PivotFields
                If pf.DataType = xlNumber Then
                    piv.AddDataField pf
                    Exit For
                End If
            Next pf

            ' make sure grand totals are in
            piv.ColumnGrand = True
            piv.RowGrand = True

            ' get da data
            piv.DataBodyRange.Cells(piv.DataBodyRange.Cells.count).ShowDetail = True

            ' rename data sheet
            If sSheetOutputName = "" Then sSheetOutputName = "datadump"
            wbPIVOT.Sheets(wsh.Index - 1).name = sSheetOutputName

            ' move it to new sheet
            Set wbNEW = Workbooks.Add
            wbPIVOT.Sheets(sSheetOutputName).Move Before:=wbNEW.Sheets(1)

            ' clean new file
            wbNEW.Sheets("Sheet1").Delete
            wbNEW.Sheets("Sheet2").Delete
            wbNEW.Sheets("Sheet3").Delete

            ' save it
            If sOutputName = "" Then sOutputName = wbFullName
            sSaveTo = PathWithSlash(wbPIVOT.path) & FilenameNoExtension(sOutputName) & "_data_" & piv.name & ".xls"
            wbNEW.SaveAs sSaveTo
            wbNEW.Close
            Set wbNEW = Nothing

            Next piv
        End If
    Next wsh

wbPIVOT.Close False
Set wbPIVOT = Nothing

calcON
Application.DisplayAlerts = True

End Sub


Sub PivotFieldHandle(pTable As PivotTable, Optional filterClear As Boolean, Optional fieldRemove As Boolean, Optional field As String)
'PURPOSE: How to clear the Report Filter field
'SOURCE: www.TheSpreadsheetGuru.com

Dim pf As PivotField

Select Case field

    Case ""
    ' no field specified - clear all!

        For Each pf In pTable.PivotFields
            Debug.Print pf.name
            If fieldRemove Then pf.Orientation = xlHidden
            If filterClear Then pf.ClearAllFilters
        Next pf


    Case Else
    'Option 1: Clear Out Any Previous Filtering
    Set pf = pTable.PivotFields(field)
    pf.ClearAllFilters

    '   Option 2: Show All (remove filtering)
    '   pf.CurrentPage = "(All)"
End Select

End Sub
person vale_p    schedule 06.05.2016