excelvba中的过滤器

excelvba中的过滤器,vba,excel,Vba,Excel,我在VBA中有一个循环,循环大约3000多条记录,并隐藏不符合条件的记录。它工作正常,但运行速度非常慢。是否有一种更快或更有效的方法根据以下标准进行过滤?任何帮助都将不胜感激 Dim i As Long, rng1 As Range, rng2 As Range, rng3 As Range, rng4 As Range, rng5 As Range, j As Long, sheetName As String, rng6 As Range, rng7 As Range, rng8 As Ra

我在VBA中有一个循环,循环大约3000多条记录,并隐藏不符合条件的记录。它工作正常,但运行速度非常慢。是否有一种更快或更有效的方法根据以下标准进行过滤?任何帮助都将不胜感激

Dim i As Long, rng1 As Range, rng2 As Range, rng3 As Range, rng4 As Range, rng5 As Range, j As Long, sheetName As String, rng6 As Range, rng7 As Range, rng8 As Range, rng9 As Range

Set rng1 = FindHeader("Client Exclusion List", Sheet8.Name)
Set rng2 = FindHeader("CLIENT NAME", Sheet5.Name)
Set rng3 = FindHeader("MARKET SEGMENT", Sheet5.Name)
Set rng4 = FindHeader("ARCHIVED", Sheet5.Name)
Set rng5 = FindHeader("FORMULARY NAME", Sheet5.Name)
Set rng6 = FindHeader("WEBSITE", Sheet5.Name)
Set rng7 = FindHeader("PDF", Sheet5.Name)
Set rng8 = FindHeader("HPMS EXPORTED", Sheet5.Name)
Set rng9 = FindHeader("SERFF EXPORTED", Sheet5.Name)

For i = 1 To rng2.Rows.Count
'Checks to see if the Client Name is in the Excluded list
    For j = 1 To rng1.Rows.Count

        If rng2.Cells(i, 1).Value = rng1.Cells(j, 1).Value Then
            rng2.Cells(i, 1).EntireRow.Hidden = True
        End If

    Next j

    'Checks For all CMS records and hides the ones that are not from current year

    If Left(rng3.Cells(i, 1).Value, 8) = "CMS Part" Then
        If rng3.Cells(i, 1).Value <> "CMS Part D (CY " & Year(Date) & ")" Then
            rng3.Cells(i, 1).EntireRow.Hidden = True
        End If
    End If
    'Checks if record is archived
    If rng4.Cells(i, 1).Value = "Yes" Then
        rng4.Cells(i, 1).EntireRow.Hidden = True
    End If
'Checks if record contains "Test" or "Demo" in the Name
    If InStr(1, CStr(rng5.Cells(i, 1).Value), "test") > 0 Or InStr(1, CStr(rng5.Cells(i, 1).Value), "Test") > 0 Or InStr(1, CStr(rng5.Cells(i, 1).Value), "demo") > 0 Or InStr(1, CStr(rng5.Cells(i, 1).Value), "Demo") > 0 Or InStr(1, CStr(rng5.Cells(i, 1).Value), "TEST") > 0 Or InStr(1, CStr(rng5.Cells(i, 1).Value), "DO NOT USE") > 0 Then
        rng5.Cells(i, 1).EntireRow.Hidden = True
    End If

Next i
尺寸i为长,rng1为范围,rng2为范围,rng3为范围,rng4为范围,rng5为范围,j为长,sheetName为字符串,rng6为范围,rng7为范围,rng8为范围,rng9为范围
设置rng1=FindHeader(“客户排除列表”,表8.Name)
设置rng2=FindHeader(“客户名称”,Sheet5.NAME)
集合rng3=FindHeader(“细分市场”,表5.名称)
设置rng4=FindHeader(“已存档”,Sheet5.Name)
Set rng5=FindHeader(“公式集名称”,Sheet5.NAME)
Set rng6=FindHeader(“网站”,表5.名称)
Set rng7=FindHeader(“PDF”,Sheet5.Name)
设置rng8=FindHeader(“HPMS导出”,Sheet5.Name)
设置rng9=FindHeader(“SERFF导出”,Sheet5.Name)
对于i=1到rng2.Rows.Count
'检查客户端名称是否在排除列表中
对于j=1到rng1.Rows.Count
如果rng2.Cells(i,1).Value=rng1.Cells(j,1).Value,则
rng2.Cells(i,1).EntireRow.Hidden=True
如果结束
下一个j
'检查所有CMS记录,并隐藏不是本年度的记录
如果左(rng3.单元格(i,1).值,8)=“CMS部分”,则
如果rng3.单元格(i,1)的值为“CMS D部分(CY)&年份(日期)&”),则
rng3.Cells(i,1).EntireRow.Hidden=True
如果结束
如果结束
'检查记录是否已存档
如果rng4.Cells(i,1).Value=“是”,则
rng4.Cells(i,1).EntireRow.Hidden=True
如果结束
'检查记录名称中是否包含“测试”或“演示”
如果InStr(1,CStr(rng5.Cells(i,1.Value),“test”)>0或InStr(1,CStr(rng5.Cells(i,1.Value),“test”)>0或InStr(1,CStr)(rng5.Cells(i,1.Value),“test”)>0或InStr(1,CStr)(rng5.Cells(i,1.Value),“test”)>0或InStr(1,CStr)(rng5.Cells(i,1.Cells)(i,1.Value),“则不使用0”
rng5.Cells(i,1).EntireRow.Hidden=True
如果结束
接下来我

一个应该有帮助的小变化是添加

Application.ScreenUpdating = False 
起初

Application.ScreenUpdating = True
最后

屏幕更新时间可能比逻辑时间长得多

编辑作为阵列循环的替代方案。在大循环之前创建一个字典,其中包含作为键的排除项。一套在这里会更好,因为你有一个无用的项目去与每个关键,但我不认为VBA有这些

您只需检查字典中是否存在键,而不是通过范围或数组进行循环

   'before loop
    Dim excludedList As Object
    Set excludedList = CreateObject("Scripting.Dictionary")
    For i = 1 To rng1.Rows.Count
        excludedList.Add rng1.Cells(i, 1).value, 1
    Next i

    '****************************************
    'in loop
    If excludedList.exists(rng2.Cells(i, 1).Value) Then
        rng2.Cells(i, 1).EntireRow.Hidden = True
    End If

下面是一个应该更快的例子。它使用数组、自动筛选,不处理rng2的每一行的所有其他范围:

Dim rng1                  As Range
Dim rng2                  As Range
Dim rng3                  As Range
Dim rng4                  As Range
Dim rng5                  As Range
Dim rng6                  As Range
Dim rng7                  As Range
Dim rng8                  As Range
Dim rng9                  As Range
Dim i                     As Long
Dim j                     As Long
Dim sheetName             As String
Dim vData1

Set rng1 = FindHeader("Client Exclusion List", Sheet8.Name)
Set rng2 = FindHeader("CLIENT NAME", Sheet5.Name)
Set rng3 = FindHeader("MARKET SEGMENT", Sheet5.Name)
Set rng4 = FindHeader("ARCHIVED", Sheet5.Name)
Set rng5 = FindHeader("FORMULARY NAME", Sheet5.Name)
Set rng6 = FindHeader("WEBSITE", Sheet5.Name)
Set rng7 = FindHeader("PDF", Sheet5.Name)
Set rng8 = FindHeader("HPMS EXPORTED", Sheet5.Name)
Set rng9 = FindHeader("SERFF EXPORTED", Sheet5.Name)

Application.ScreenUpdating = False

vData1 = rng1.Value

For i = 1 To rng2.Rows.Count
    'Checks to see if the Client Name is in the Excluded list
    For j = LBound(vdata1, 1) To UBound(vdata1, 1)

        If rng2.Cells(i, 1).Value = vdata1(j, 1) Then
            rng2.Cells(i, 1).EntireRow.Hidden = True
            Exit For
        End If

    Next j
Next i

'Checks For all CMS records and hides the ones that are not from current year

rng3.AutoFilter 1, "<>CMS Part*", xlOr, "CMS Part D (CY " & Year(Date) & ")"
'Checks if record is archived
rng4.AutoFilter 1, "<>Yes"
'Checks if record contains "Test" or "Demo" in the Name
rng5.AutoFilter 1, "<>*test*", xlAnd, "<>*demo*"

Application.ScreenUpdating = True
Dim rng1 As范围
变暗rng2 As范围
变暗rng3 As范围
变暗rng4 As范围
变暗rng5 As范围
变暗rng6 As范围
变暗rng7 As范围
变暗rng8 As范围
变暗rng9 As范围
我想我会坚持多久
Dim j尽可能长
将sheetName设置为字符串
Dim vData1
设置rng1=FindHeader(“客户排除列表”,表8.Name)
设置rng2=FindHeader(“客户名称”,Sheet5.NAME)
集合rng3=FindHeader(“细分市场”,表5.名称)
设置rng4=FindHeader(“已存档”,Sheet5.Name)
Set rng5=FindHeader(“公式集名称”,Sheet5.NAME)
Set rng6=FindHeader(“网站”,表5.名称)
Set rng7=FindHeader(“PDF”,Sheet5.Name)
设置rng8=FindHeader(“HPMS导出”,Sheet5.Name)
设置rng9=FindHeader(“SERFF导出”,Sheet5.Name)
Application.ScreenUpdating=False
vData1=rng1.Value
对于i=1到rng2.Rows.Count
'检查客户端名称是否在排除列表中
对于j=LBound(vdata1,1)到UBound(vdata1,1)
如果rng2.Cells(i,1).Value=vdata1(j,1),则
rng2.Cells(i,1).EntireRow.Hidden=True
退出
如果结束
下一个j
接下来我
'检查所有CMS记录,并隐藏不是本年度的记录
rng3.AutoFilter 1,“CMS零件*”,xlOr,“CMS零件D(CY)”和年份(日期)和“
'检查记录是否已存档
rng4.AutoFilter 1“是”
'检查记录名称中是否包含“测试”或“演示”
rng5.AutoFilter 1、“*测试*”、xlAnd、“*演示*”
Application.ScreenUpdating=True

谢谢。这会加快速度,但完成整个潜艇仍然需要7分钟以上的时间。有没有更快的方法呢?哇,太长了。我和j有多大?也许试着对某些部分进行计时,看看瓶颈在哪里?Debug.print“line id”&now()是的。我发现耗时的部分是我的第一个循环,因为它每次都在运行。我正在考虑使用自动过滤器或高级过滤器进行过滤。如何将条件转换为在其中一个过滤器中使用?实际使用自动过滤器或高级过滤器功能几乎肯定比循环更快。您的第一个循环看起来特别耗时,因为您一个单元格一个单元格地读取,并且一遍又一遍地读取相同的单元格。在内部循环中也应该有一个的退出,因为在隐藏同一行之后再检查它是没有意义的。使用数组也会加快速度。我如何将条件转换为与AutoFilter或Advanced Filter一起使用?它在第二个for循环的第一行上给了我类型不匹配的问题<代码>对于j=LBound(vdata,1)到UBound(vdata,1)而言,过滤器不会过滤任何内容。我刚刚更正了几个拼写错误-请再次测试。这修复了该错误。现在它给了我一个对象所需的错误:
如果rng2.Cells(i,1)。Value=vData1(j,1)。Value-Then
另一个输入错误-现在修复!(对不起)