【问题标题】:Efficiently copy and paste block of cells based on multiple criteria基于多个条件有效地复制和粘贴单元格块
【发布时间】:2015-11-11 16:27:11
【问题描述】:

我有一个大型数据集,并希望根据一组条件查询到另一张工作表的列。我有一个工作方法,它使用循环来查找开始和循环来查找结束以获取所需的行,但这很慢。

我想避免查找函数所需的唯一列,因为这会使数据的结尾难以找到。我考虑过尝试使用某种 FindAll 函数,但似乎无法弄清楚如何启动它。

我已经看到很多关于过滤器的内容,但这些似乎可以通过复制整行来工作,我想避免这种情况。

就像我说的,这段代码运行良好,但速度很慢,因为它会在模型​​运行期间运行 1000 次。我也有几个类似的潜艇,我希望能够推出解决方案

Sub Join(CI, FI, FSD)
Dim a, b, LastRow As Long

LastRow = Fcst_Cust.Range("a1048576").End(xlUp).Row + 1

'find all values for that customer ID for dates greater than the forecast start date and copy onto forecast tab.

    a = 3
    b = 2

    Do Until ((Raw_IFcst.Cells(b + 1, 2) = CI) And (Raw_IFcst.Cells(b + 1, 3) >= FSD))
        a = a + 1
        b = b + 1
    Loop
    Do Until Raw_IFcst.Cells(b + 1, 2) <> CI
        b = b + 1
    Loop

    Raw_IFcst.Range("A" & a & ":AZ" & b).Copy
        Fcst_Cust.Range("C" & LastRow).PasteSpecial xlPasteValues
    Raw_IFcst.Range("BB" & a & ":CW" & b).Copy
        Fcst_Cust.Range("BG" & LastRow).PasteSpecial xlPasteValues

End Sub

【问题讨论】:

    标签: vba excel search criteria


    【解决方案1】:

    Range 对象的 AdvancedFilter 方法可能是最有效的……而且它绝对不需要复制整行。你可以选择你想要的列。

    但是,我重构了您的代码,但没有使用 AdvancedFilter。这应该会更快:

    Sub Join_(CI, FI, FSD)
        Dim a&, b&, LastRow&, v
    
        LastRow = Fcst_Cust.[a1048576].End(xlUp).Row + 1
    
        a = 3
        b = 2
    
        With Raw_IFcst
            v = .Cells(1, 2).Resize(.[b1048576].End(xlUp).Row, 2).Value2
    
            Do
                If If v(b + 1, 1) = CI Then
                    If v(b + 1, 2) >= FSD Then
                        Exit Do
                    End If
                End If
                a = a + 1
                b = b + 1
            Loop
    
            Do Until v(b + 1, 1) <> CI
                b = b + 1
            Loop
    
            .Range("A" & a & ":AZ" & b).Copy
                Fcst_Cust.Range("C" & LastRow).PasteSpecial xlPasteValues
    
            .Range("BB" & a & ":CW" & b).Copy
                Fcst_Cust.Range("BG" & LastRow).PasteSpecial xlPasteValues
        End With
    
    End Sub
    

    注意:我没有测试过这个,所以请做。

    注意:我已经更改了 Sub 的名称。使用现有 VBA 函数的名称作为过程的名称不是一个好习惯,除非您确实希望覆盖该函数。

    注意:我更改了 Dim 行。你有 ab 作为变体,当它们应该是长的时候。

    注意:最让您的程序变慢的原因是逐个单元格地读取第 2 列和第 3 列。一次读取和写入一个单元格可能是 Excel 开发人员可用的最低效的过程。我的代码所做的是将第 2 列和第 3 列的使用部分转移到一个数组中,v。这非常快,而且访问数组的单个元素而不是单个单元格非常快。

    注意:我更改了第一个 Do While 循环。 VBA 表达式求值不会使多个子句短路。因此,如果clause 1clause 2 必须为真(如您的情况),那么即使clause 1 为假,clause 2 也会被评估。那是零收益的处理浪费。在您的原始设置中,由于单个细胞的读取速度慢,浪费被放大了。优化是将子句分成单独的行。这样,如果第一个失败,则永远不会评估第二个。通过将最有可能失败的子句放在第一行,可以进一步优化这个概念。我不知道在你的场景中哪个最有可能失败,所以我把你的第一个子句放在第一行。

    【讨论】:

    • 我不得不将 If v(b + 1, 1 = CI) Then 更改为 If v(b + 1, 1) = CI Then 但否则代码可以工作并且看起来更快,谢谢。我会在其他潜艇上推出它,看看它是否足够快,不用担心搞清楚自动过滤
    • @Penelly 我已经用错字更正更新了答案。请记住通过单击答案旁边的大复选标记来接受答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 2021-02-17
    • 2021-08-25
    相关资源
    最近更新 更多