【问题标题】:Alternative to very slow vba vlookup to closed network files替代非常慢的 vba vlookup 来关闭网络文件
【发布时间】:2016-12-20 20:42:23
【问题描述】:

该项目的基础是提供一个位于 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 过程,所以我不确定它是否可能。

我也想过让宏打开项目工作簿,复制数据,然后再次关闭它们,但这似乎太麻烦且不可靠,尽管我不怀疑它会更快。

有人有什么建议吗?

【问题讨论】:

  • “出于这个原因,我希望在从中读取数据的同时关闭项目表。”这样做有什么好处?最好的办法是遍历每个文件并在本地提取所有数据,然后从那里进行任何计算。

标签: performance excel vlookup vba


【解决方案1】:

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

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

不过,可能还有更好的方法。根据您要比较的数据结构(运行宏的工作表和作为 VLookup 数据源的工作表),您可以先对工作表进行排序(基于公共键),然后运行使用 GoTo 的带有类似 continue 语句的嵌套循环。示例:

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

【讨论】:

    猜你喜欢
    • 2012-10-29
    • 2014-08-11
    • 2020-03-03
    • 2012-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-09
    • 2011-05-15
    相关资源
    最近更新 更多