【问题标题】:Filter all (multiple) workbooks in a folder with a sheet from different workbook使用来自不同工作簿的工作表过滤文件夹中的所有(多个)工作簿
【发布时间】:2018-05-03 01:20:41
【问题描述】:

我有一个带有 S5 工作表的(过滤)工作簿。我有 56 个带有 S1 表的 excel 文件,每个文件夹中有 300 到 40 万条记录。如果过滤工作簿的 S5 表的 C 列与文件夹中 excel 文件列表(全部)的 AG 列匹配,我想从多个文件中复制匹配数据和 S5 的列数据 A(过滤条件文件“)在新摘要表的同一行。我从朋友那里得到的以下宏在一定程度上有效。我必须像文件 1、2、3 ... 56 一样运行它 56 次。但它需要一个多小时并跳过记录。有没有更好的方法可用?非常感谢您的帮助。

Sub FilterData ()

    Set kFS = CreateObject("Scripting.FileSystemObject")
    Set kF = kFS.GetFile("C:\Users\Tech\Desktop\TEST\SrcFile.xlsx")
    Dim mainWB As Workbook
    Set mainWB = Workbooks.Open("C:\Users\tech\Desktop\TEST\SrcFile.xlsx")
    mainWB.Sheets("S5").Select
    Dim newLastRow As Long

    'File1
    Set desFS = CreateObject("Scripting.FileSystemObject")
    Set desF = kFS.GetFile("C:\Users\tech\Desktop\TEST\Report\File1.xlsx")
    Dim desWB As Workbook
    Set desWB = Workbooks.Open("C:\Users\tech\Desktop\TEST\Report\File1.xlsx")
    desWB.Sheets("S1").Select

    Dim rng1 As Range, rng2 As Range, rngName As Range, rngName1 As Range, i As Integer, j As Integer
    For i = 1 To mainWB.Sheets("S5").Range("A" & Rows.Count).End(xlUp).Row
        Set rng1 = mainWB.Sheets("S5").Range("C" & i)
        Set rngName1 = mainWB.Sheets("S5").Range("A" & i)
        For j = 1 To desWB.Sheets("S1").Range("A" & Rows.Count).End(xlUp).Row
            Set rng2 = desWB.Sheets("S1").Range("AG" & j)
            Set rngName = desWB.Sheets("S1").Rows(j)
            If rng1.Value = rng2.Value Then
                rngName.Copy Destination:=mainWB.Sheets("New").Range("A" & i)
                rngName1.Copy Destination:=mainWB.Sheets("New").Range("AH" & i)

            End If

            Set rng2 = Nothing
        Next j
        Set rng1 = Nothing
    Next i
    desWB.Close

    newLastRow = mainWB.Sheets("New").Range("A" & Rows.Count).End(xlUp).Row
End Sub

【问题讨论】:

  • “有更好的方法吗?” 是的,使用特定的数据库工具。可能是 Access 或其他(只需 google 即可)

标签: excel vba file filter


【解决方案1】:

未经测试并假设您在工作表“S5”列“C”中没有任何重复项,并且它在您的 56 个文件中仅存在一次。

Sub test()
    Application.ScreenUpdating = False

    Dim mainWB As Workbook, Wb As Workbook
    Dim P1 As Range, c As Range, P2 As Range

    Set D1 = CreateObject("scripting.dictionary")
    Set mainWB = Workbooks.Open("C:\Users\tech\Desktop\TEST\SrcFile.xlsx") 'This is your file with sheet "S5" and "New"
    Folder = "C:\Users\tech\Desktop\TEST\Report\" 'This is the folder with all 56 workbooks with sheet "S1"
    File = Dir(Folder & "*.xlsx")

    Set P1 = mainWB.Sheets("S5").Range("C1:C" & mainWB.Sheets("S5").Range("C999999").End(xlUp).Row)

    For Each c In P1: D1(c.Value) = c.Row: Next c

    Do While File <> ""
        Set Wb = Workbooks.Open(Folder & File)
        Set P2 = Wb.Sheets("S1").Range("A1", Wb.Sheets("S1").UsedRange.SpecialCells(xlCellTypeLastCell))
        T1 = P2

        For i = 1 To UBound(T1)
            If D1.exists(T1(i, 33)) Then
                For j = 1 To 33
                    mainWB.Sheets("New").Cells(D1(T1(i, 33)), j) = T1(i, j)
                Next j
                mainWB.Sheets("New").Cells(D1(T1(i, 33)), 34) = mainWB.Sheets("S5").Cells(D1(T1(i, 33)), 1)
            End If
        Next i

        Wb.Saved = True
        Wb.Close
        File = Dir()
    Loop

    Application.ScreenUpdating = True
End Sub

Sub test()
    Application.ScreenUpdating = False

    Dim mainWB As Workbook, Wb As Workbook
    Dim P1 As Range, c As Range, P2 As Range, a As Integer
    Dim T2()

    Set D1 = CreateObject("scripting.dictionary")
    Set mainWB = Workbooks.Open("C:\Users\tech\Desktop\TEST\SrcFile.xlsx") 'This is your file with sheet "S5" and "New"
    Folder = "C:\Users\tech\Desktop\TEST\Report\" 'This is the folder with all 56 workbooks with sheet "S1"
    File = Dir(Folder & "*.xlsx")

    mainWB.Sheets("New").Cells.Clear

    Set P1 = mainWB.Sheets("S5").Range("C1:C" & mainWB.Sheets("S5").Range("C999999").End(xlUp).Row)
    a = 1

    For Each c In P1: D1(c.Value) = c.Offset(0, -2).Value: Next c

    Do While File <> ""
        Set Wb = Workbooks.Open(Folder & File)
        Set P2 = Wb.Sheets("S1").Range("A1", Wb.Sheets("S1").UsedRange.SpecialCells(xlCellTypeLastCell))
        T1 = P2

        For i = 1 To UBound(T1)
            If D1.exists(T1(i, 33)) Then
                ReDim Preserve T2(1 To 34, 1 To a)
                For j = 1 To 33
                    T2(j, a) = T1(i, j)
                Next j
                T2(34, a) = D1(T1(i, 33))
                a = a + 1
            End If
        Next i

        Wb.Saved = True
        Wb.Close
        File = Dir()
    Loop

    mainWB.Sheets("New").Range("A1").Resize(UBound(T2, 2), UBound(T2)) = Application.Transpose(T2)

    Application.ScreenUpdating = True
End Sub

【讨论】:

  • 这个宏很快。但没有拉任何记录。可能是我提供的信息不充分。工作表 S5 在 C 列中没有重复变量。但多个工作簿中的其他 S1 工作表可能有重复值,需要将它们拉到工作表“新建”中。
  • 当您说“在新汇总表的同一行”时,您是指与“来自 S1 和来自 S5 的数据在同一行”中的同一行,还是与 S5 中的匹配数据在同一行?我选择了第二个选项,这就是为什么如果有的话,你可能会在整个新工作表中得到结果。我要编辑这个。
  • 你没看错。我的意思是第二种选择。在匹配 S5 的 C 列和 S1 的 AG 后,应将 S5 数据的相应 A 列与多个工作簿的 S1 工作表中的数据一起复制。
  • 非常感谢安博。这是一个很好的解决方案。 56 个文件,200K 到 300K 文件。它在不到 3 分钟的时间内提取了数据。太棒了。
  • 它可以快速处理所有文件,除了一个今年有超过 500K 记录的大文件。令人惊讶的是,因为数据类型与其他 55 个文件相同。我检查了数据错误,没有找到。它在 mainWB.sheets 的最后一行代码中出现“类型不匹配(错误 13)”的错误......有什么解决方案吗?感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-04
  • 2022-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-07
相关资源
最近更新 更多