根据多个标准有效地复制和粘贴细胞块

时间:2015-11-11 16:27:11

标签: excel vba excel-vba search criteria

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

我想避免使用find函数所需的唯一列,因为这会使数据的结尾难以找到。我考虑过尝试使用某种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

1 个答案:

答案 0 :(得分:0)

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 2为假,clause 1也会被评估。这是浪费处理,没有任何好处。在您的原始设置中,由于单个细胞的读取速度缓慢而导致废物被放大。优化是将条款分解为单独的行。这样,如果第一个失败,则永远不会评估第二个。通过在第一行放置最有可能失败的子句,可以进一步确定这一概念。我不知道哪种情况最有可能在你的场景中失败,所以我把你的第一个条款放在第一行。