VBA - 循环数据透视表中的每个项目并粘贴到新工作表中

时间:2018-05-19 22:19:36

标签: excel vba excel-vba

我遇到了挑战...我在Sheet Lookup中有一个范围,其中包含Pivot表过滤器中的每个可能值“Owner:Full Name”。

名称范围是Sheets“Lookup”Range B2:B98。 (问题1:此范围可以更改,因为它在不同的代码中创建此列表,如何将其设置为动态范围?)

一旦它过滤了B2中的那个值,它应该将这个过滤后的枢轴复制到一个新的工作表中,并将该工作表命名为b2中的值。

然后它应该“取消选择”b2项并继续过滤b3中的值并继续。

问题2:正确设置过滤器以循环并过滤新动态查找范围中的每个单值。

这就是我现在所拥有的......

Option Explicit

    Dim wb As Workbook, ws, ws1, ws2 As Worksheet, PT As PivotTable, PTI As 
    PivotItem, PTF As PivotField, rng As Range

    Sub Filter_Pivot()

    Set wb = ThisWorkbook
    Set ws = wb.Sheets("Copy")
    Set ws1 = wb.Sheets("Lookup")
    Set PT = ws.PivotTables("PivotCopy")
    Set PTF = PT.PivotFields("Owner: Full Name")


        For Each rng In ws1.Range("B2:B98")
            With PTF
                .ClearAllFilters
                For Each PTI In PTF.PivotItems
                    PTI.Visible = (PTI.Name = rng)
                Next PTI
            Set ws2 = Sheets.Add
                ws1.Name = PTI
                .TableRange2.Copy
                ws2.Range("A1").PasteSpecial
            End With
        Next rng


    End Sub

2 个答案:

答案 0 :(得分:3)

您可以避免所有这些并使用PivotTable.ShowPages Method。它针对此类操作进行了优化。

注意:

  1. "Owner: Full Name" 必须 位于顶部的页面字段区域。
  2. 您可能想要检查表格名称是否已经存在。您可以执行将从pivot生成的工作表名称的初始循环,并尝试删除它们(包裹在On Error Resume Next, attempt delete, On Error GoTo 0内)以确保它们不会先存在。我在第二个例子中展示了如何做到这一点。
  3. 信息: PivotTable.ShowPages Method

      

    为页面字段中的每个项目创建新的数据透视表。每   新报告是在新工作表上创建的。

         

    语法表达式。 ShowPages(PageField)

         

    expression表示数据透视表对象的变量。

         

    [pageField的可选参数。]

    <强>代码:

    ThisWorkbook.Worksheets("Copy").PivotTables("PivotCopy").ShowPages "Owner: Full Name"
    

    这将为页面字段"Owner: Full Name"中的每个可能值生成一个工作表。如果您不想要所有这些,只需保存工作表中要保留的工作表的工作表名称列表,并在工作簿中的所有工作表上循环,如果不在数组中,则删除如下所示:

    ①循环表单的示例,如果不在数组中则删除:

    Option Explicit
    
    Public Sub GeneratePivots()
        Dim keepSheets(), ws As Worksheet
        keepSheets = Array("FilterValue1", "FilterValue2","Lookup","Copy") '<== List of sheet names to keep
    
        Application.ScreenUpdating = False
        Application.DisplayAlerts = False
    
        On Error GoTo errHand
    
        ThisWorkbook.Worksheets("Copy").PivotTables("PivotCopy").ShowPages "Owner: Full Name"
    
        For Each ws In ThisWorkbook.Worksheets
            If IsError(Application.Match(ws.Name, keepSheets, 0)) And ThisWorkbook.Worksheets.Count > 1 Then
                ws.Delete
            End If
        Next ws
    
    errHand:
        Application.DisplayAlerts = True
        Application.ScreenUpdating = True
    End Sub
    

    ②使用查找表:

    如果您仍然希望继续阅读工作表以保留Copy表单,则可以使用以下内容(一定要确保在B列的列表中包含该工作表名称CopyLookup,感兴趣的过滤器值以及您不想删除的任何其他工作表名称:

    <强>代码:

    Option Explicit
    
    Public Sub GeneratePivots()
        Dim ws As Worksheet, lookups As Range
    
        Application.ScreenUpdating = False
        Application.DisplayAlerts = False
    
        With ThisWorkbook.Worksheets("Lookup")
            Set lookups = .Range(.Range("B2"), .Range("B2").End(xlDown))
            If Application.WorksheetFunction.CountA(lookups) = 0 Then Exit Sub
            keepSheets = lookups.Value
        End With
    
        Dim rng As Range
        For Each rng In lookups
            On Error Resume Next
             Select Case rng.Value
             Case "Lookup", "Copy" '<=Extend for sheets to keep listed in lookups that aren't generated by the pivot filtering
             Case Else
                 ThisWorkbook.Worksheets(rng.Value).Delete
             End Select
            On Error GoTo 0
        Next rng
    
       On Error GoTo errHand
    
        ThisWorkbook.Worksheets("Copy").PivotTables("PivotCopy").ShowPages "Owner: Full Name"
    
        For Each ws In ThisWorkbook.Worksheets
            If IsError(Application.Match(ws.Name, Application.WorksheetFunction.Index(keepSheets, 0, 1), 0)) And ThisWorkbook.Worksheets.Count > 1 Then
                ws.Delete
            End If
        Next ws
    
    errHand:
        Application.DisplayAlerts = True
        Application.ScreenUpdating = True
    End Sub
    

    示例运行:

    Test run

答案 1 :(得分:1)

您可以尝试这样的事情......

Sub Filter_Pivot()
Dim wb As Workbook
Dim ws As Worksheet, ws1 As Worksheet, ws2 As Worksheet
Dim PT As PivotTable
Dim PTF As PivotField
Dim rng As Range
Dim lr As Long

Set wb = ThisWorkbook
Set ws = wb.Sheets("Copy")
Set ws1 = wb.Sheets("Lookup")
Set PT = ws.PivotTables("PivotCopy")
Set PTF = PT.PivotFields("Owner: Full Name")

lr = ws1.Cells(Rows.Count, 2).End(xlUp).Row

For Each rng In ws1.Range("B2:B" & lr)
    PTF.ClearAllFilters
    On Error Resume Next
    PTF.CurrentPage = rng.Value
    If Err = 0 Then
        Set ws2 = Sheets(rng.Value)
        ws2.Cells.Clear
        If ws2 Is Nothing Then
            Set ws2 = Sheets.Add
            ws2.Name = rng.Value
        End If
        PT.TableRange2.Copy ws2.Range("A1")
    End If
    PTF.ClearAllFilters
    Set ws2 = Nothing
    On Error GoTo 0
Next rng
End Sub