替代非常慢的vba vlookup到封闭的网络文件

时间:2016-12-20 11:09:51

标签: performance excel-vba vlookup vba excel

该项目的基础是提供位于Shrepoint站点的数据输入门户。管理人员将输入他们对每个工作职能的预期员工需求,并且该计划会将这些数据整理成易于阅读的图表和指标。

数据输入工作表每个都被输入到“总需求”中。每个项目中的标签'工作簿,但这不是我的问题。我的问题是试图从这些“总需求”中提取数据。工作表(每个项目工作簿一个)到具有类似格式的主工作簿。

这些工作表旨在尽可能自动化,针对的用户并不特别熟悉SUM()函数的任何复杂功能。出于这个原因,我希望在从中读取数据的同时关闭项目表。

我现在拥有的主工作簿中的代码首先运行一个子例程来格式化具有正确日期和项目的报表,然后循环遍历每一行,直到找到需要数据的行。从这里开始,它使用GetValue函数(在此处找到:http://spreadsheetpage.com/index.php/tip/a_vba_function_to_get_a_value_from_a_closed_file/)从各个报告中提取数据,例如带数据的第一个月。

然后循环遍历将公式写入每个单元格的列,以查找报告中找到的值。我在下面列出了此代码的精简版本。

job = Cells(rowindexA, 1).Value
targetSheetArray = "'" & path & "[" & file & "]" & ws & "'!" & Range(Cells(1, 2), Cells(100, 100)).Address(, , xlR1C1)

For ColIndex = 10 To numMonths + 9

    targetSheetColumn = ColIndex + monthsDif

    'This formula works but is incredibly slow (multiple seconds PER ENTRY)
    Cells(rowindexA + rowindexB, ColIndex).Formula = "=VLookup(" & Chr(34) & job & Chr(34) & "," & targetSheetArray & "," & targetSheetColumn & ",FALSE)"

    'This formula was from a similar idea than the one above, but Application.WorksheetFunction doesn't work on closed sheets
    'Cells(rowindexA + rowindexB, ColIndex).Value = Application.WorksheetFunction.VLookup(job, targetSheetArray, targetSheetColumn, False)                        

Next

现在提出我的问题。因为VLookup的速度非常慢,所以当每个项目都包含在内时,这个工作表需要几个小时才能运行,是否有更快的方法?

我想找到一种禁止宏计算查找值直到最后的方法,此时它可以一次读取所有数据。我试过了

Application.Calculation = xlCalculationManual

但这似乎并没有影响到VLookup程序,因此我不确定它是否可行。

我还想过让宏打开项目工作簿,复制数据,然后再次关闭它们,但这看起来太麻烦和不可靠,但我不怀疑它会更快。

有人有任何建议吗?

1 个答案:

答案 0 :(得分:0)

是的,有一种比使用VLookup更快的方式。

使用嵌套循环(循环遍历 ws 中的行)。如果可能的话,将嵌套循环包含在if语句中(如果它适用于您的问题,则不能确定您提出问题的方式)。它仍然是O(n ^ 2),但循环比VLookups快。

但是,可能还有更好的方法。根据您要比较的数据的结构(运行宏的工作表和作为VLookup数据源的工作表),您可能能够首先对工作表进行排序(基于公共密钥),然后运行使用GoTo的带有类似继续的语句的嵌套循环。例如:

Dim ws As Worksheet, compared As Worksheet
Dim i As Integer, j As Integer
j = 1

For i = 1 to wsLastrow
    While j <= comparedLastrow
        j = j + 1
        If ws.cells(i, relevantColumn) = compared(j, someColumn) Then
            ws.cells(i, targetColumn) = someValue 'from row j in compared worksheet
            GoTo Continue
        End If
    Wend
Continue:
Next