我有一个大型数据集,并希望根据一组条件向另一个工作表查询列。我有一个工作方法,使用循环来查找开始,循环找到结束以获得所需的行,但这很慢。
我想避免使用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
答案 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线。您有a
和b
作为变体,它们应该是长的。
注意:最常放慢程序的是通过第2列和第3列逐个单元读取的内容。一次读取和写入单元格可能是Excel开发人员可用的效率最低的过程。我的代码所做的是将第2列和第3列的已使用部分转换为数组v
。这非常快,并且访问阵列的各个元素而不是单个单元格非常快。
注意:我更改了第一个Do While
循环。 VBA表达式评估不会使多个子句短路。因此,如果clause 1
和clause 2
必须为真(如您的情况),那么即使clause 2
为假,clause 1
也会被评估。这是浪费处理,没有任何好处。在您的原始设置中,由于单个细胞的读取速度缓慢而导致废物被放大。优化是将条款分解为单独的行。这样,如果第一个失败,则永远不会评估第二个。通过在第一行放置最有可能失败的子句,可以进一步确定这一概念。我不知道哪种情况最有可能在你的场景中失败,所以我把你的第一个条款放在第一行。