0

我现在有一个程序可以合并来自多个工作簿的特定工作表。该程序必须处理大约 300 个工作簿并创建一个合并的工作簿。在合并的工作簿中,我必须向从其他工作簿复制的每一行添加更多数据点。目标工作簿中的行数可能约为 100,000。

我有另一个 XL,其中包含与客户相关的许多其他数据,如姓名、国家、货币等,我必须将其添加为其他列。

一个工作簿仅包含来自一位客户的数据。因此,对于从一个工作簿复制的数据,所有这些列的数据将基本相同。

现在,我正在考虑打开 customerData 工作簿并根据 customerID 有选择地复制数据,然后在粘贴每个工作表中的数据时将其粘贴到目标工作簿中。

现在代码将如下所示:

For each workbook in the source Folder
    Open source workbook
    Copy the range from worksheet1
    Copy the customerID from worksheet2
    Open target workbook
    Paste range from source.worksheet1 in the target worksheet
    Fill the range in the target worksheet with the first column as customerID
    Open workbook with customer master data
    Copy data based on customerID
    Paste in the target worksheet using fill range

另一种方法是完成粘贴所有工作表中的所有数据,然后查找客户数据 - 这里的优点是可以在多个文件中为客户提供数据,因此在避免多次查找方面有一定的效率。客户主数据文件只需打开一次。

我想知道我采取的方法是否正确,是否有任何改进可以做到。

具体来说,我有以下问题:

  • 有没有办法避免打开每个源文件?
  • 将源工作簿中的所有数据添加到内存中的数组并将其复制一次到目标工作簿中是否更好?
  • 如果我使用数组方法,我应该在粘贴之前将查找添加到数组中,还是应该在将数据粘贴到目标范围内之后执行?
4

1 回答 1

1

我写这个作为回复,因为它可能太长了作为评论。

1)没有办法避免打开源文件来检索数据。对于这样的操作,非常重要的是,对于您打开以进行检索的每个工作簿,您创建一个新的 Excel 实例(CreateObject 方法)并在完成后通过应用 .Quit 方法将其从内存中完全清除。Workbook.close 并不像您期望的那样完美(内存没有完美清除),并且您尝试在一个循环中打开/关闭的工作簿数量越多,您的应用程序在某个特定位置崩溃/冻结的可能性就越大观点。

2)读/写操作花费的时间最多,因此确实建议您尝试将它们的频率降低到最低限度。最好的方法确实是将每个检索到的工作簿的所有数据一次读取到单个范围(和数组)中并在内存中执行所有操作。当您执行了您想要执行的操作后,您可以将检索到的数组写入单个范围。
您可以按照您的建议一次将所有工作簿加载到一个数组中(据我所知,数组的大小仅受可用内存量的限制。出于实用的原因,我建议您编写每次关闭文件时都会将数据复制到目标工作簿。如果发生意外情况,您无需重新运行整个代码,但您可以将 for next 循环设置为上次的位置。

3)如果您想防止应用程序在每次遇到错误时停止(这很可能在您检索此数量的数据时),请使用

On Error goto ErrHandler
Err.Handler: 
    'Display error number / Description + place in logfile 
    Resume next 

建议您创建一个小的错误处理程序,将错误代码、描述和发生错误的位置写入单独的“日志”文件中,以便以后跟踪错误。但是这样你就可以在代码运行时喝咖啡。

4)至于查找,我不确定我是否正确理解您尝试做的事情。最快的查找自然是具有最短循环的查找。嵌套循环通常相当昂贵,当然当它们很长时。
我只想提一下(就像我通常做的那样),建议将来将 MS Access 用于用户 db(或任何其他 RDBMS)(当我听到“客户 ID”时,这是我首先想到的)。在性能领域的主要优势是可以通过应用索引直接访问记录。使用简单的 SQL 语句进行查询很容易,这比使用 VBA 自己编写所有程序并遍历数组要容易得多。SQL 语句可用于执行一般的 CRUD(创建、检索、更新、删除记录)操作,但还有更多。此外,您可以应用 VBA 来处理任何其他转换。

我希望我的回复对你有任何帮助,虽然我没有提供任何真实的代码。

于 2012-10-02T08:45:02.043 回答