【问题标题】:VBA - Loop Each Item in Pivot Filter and Paste into new sheetVBA - 循环透视过滤器中的每个项目并粘贴到新工作表中
【发布时间】:2018-05-19 22:19:35
【问题描述】:

我有一个挑战...我在工作表查找中有一个范围,其中每个可能的值都在数据透视表过滤器“所有者:全名”中。

具有名称的范围是工作表“查找”范围 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

【问题讨论】:

  • 要使您的查找范围动态化,请考虑使用End 属性。你不是说ws2.Name,不是ws1吗?最后,您目前遇到了什么错误?

标签: vba excel


【解决方案1】:

您也许可以避免这一切并使用PivotTable.ShowPages Method。它针对这种操作进行了优化。


注意:

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

信息: PivotTable.ShowPages Method

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

语法表达式。 ShowPages(PageField)

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

[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 列的列表中包含表格名称 @ 987654331@,Lookup,感兴趣的过滤器值,以及您不想删除的任何其他工作表名称):

代码:

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

示例运行:

【讨论】:

  • 您好,我认为这很好用。但是,由于“所有者:全名”不是数据透视页面,所以它直接对我来说是错误的。所以它没有找到其中的项目。如果该字段不是页面,关于如何使用它的任何想法?
  • 除非在页面字段中,否则它将不起作用。是不是不能在页面字段中使用?
  • 另一种方法是遍历放置它的字段,选择项目。
  • 请记住,您可以在页面字段中的不同工作表中创建一个重复的数据透视表,并使用它来生成工作表,如果您想使用其现有布局保留原始数据。确保将代码指向重复的枢轴。
  • 我现在很好用。为此非常感谢。稍微调整了一下,现在效果很好!
【解决方案2】:

你可以试试这样的……

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

【讨论】:

  • 您好,谢谢。但是,它似乎并没有完全发挥作用。运行它似乎卡在“If Err = 0 Then”上,它一直跳过创建新工作表并粘贴......有什么想法吗?
  • 如果在数据透视字段中找不到项目,PTF.CurrentPage = rng.Value 将抛出错误。如果没有错误,则意味着找到了项目,并且将添加一个新工作表并将数据透视表范围复制到那里。只需在 Set ws2 = Nothing 行之后添加另一行 On Error GoTo 0,这将重置错误处理程序。
  • 试过了。仍然无法正常工作,当它试图在范围内查找值时出现错误(尽管它找到了 98 行的范围并且它们与枢轴值相同)。想法?
  • 什么不起作用?它不是为某些项目创建新工作表吗?如果是,请确保这些项目与 ws1 上 B 列中的项目完全相同。检查前导或尾随空格。否则我在代码中看不到任何问题。
  • 或者尝试使用F8 键调试代码并查看代码跳过创建新工作表的位置,然后检查rng.Value 并将其与页面字段中的项目进行比较,看看它们是否准确一样。
猜你喜欢
  • 1970-01-01
  • 2015-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多