【问题标题】:Speed up multiple replacement加快多次更换
【发布时间】:2014-11-22 03:52:54
【问题描述】:

我正在编写一个 Word 宏,它从 Excel 文件中读取大约 1000 个单词对,并相应地替换 Word 文件。一开始我使用下面的代码进行替换:

    Selection.Find.ClearFormatting
    Selection.Find.Replacement.ClearFormatting
    With Selection.Find
        .Text = SrcText
        .Replacement.Text = DestText
        .Forward = True
        .Wrap = wdFindContinue
        .Format = False
        .MatchCase = False
        .MatchWholeWord = False
        .MatchByte = False
        .MatchAllWordForms = False
        .MatchSoundsLike = False
        .MatchWildcards = False
        .MatchFuzzy = False
    End With
    Selection.Find.Execute Replace:=wdReplaceAll

它可以工作,但对于大型 Word 文件来说似乎有点慢。然后我尝试首先将整个内容读入一个字符串变量,在那里进行查找,然后在找到任何替换目标时更改 Word 文件(尽管我实际上不确定这是否会更快)。

在这样做时,我遇到了有点奇怪的不一致。例如,如果您创建的 Word 文件的第一行中只有一个单元格表格:

然后在 VBA 编辑器中,下面的代码将为您提供 2.

    Debug.Print Len(ActiveDocument.Characters(2))

我不知道是否存在其他这种不一致并卡在那里。

是否有任何解决方法或是否有任何其他方法可以加快更换速度?

【问题讨论】:

  • 单元格结尾和表格字符结尾。您甚至可以在图片中看到它们。
  • @Noodles 感谢您指出这一点。我很好奇为什么“Characters”和“Len”以不同的方式计算单元格的结尾和表格字符的结尾。你有什么线索吗?此外,这是唯一以不同方式计算的角色吗?

标签: vba replace ms-word


【解决方案1】:

首先,不要一遍又一遍地指定所有这些属性。除非你改变它们,否则它们不会改变。

With Selection.Find
    .ClearFormatting
    .Replacement.ClearFormatting
    .Forward = True
    .Wrap = wdFindContinue
    .Format = False
    .MatchCase = False
    .MatchWholeWord = False
    .MatchByte = False
    .MatchAllWordForms = False
    .MatchSoundsLike = False
    .MatchWildcards = False
    .MatchFuzzy = False

    For loop to go through each word pair
        .Text = SrcText
        .Replacement.Text = DestText
        .Find.Execute Replace:=wdReplaceAll
    Next

End With

尽量减少点

因此,如果您对性能感兴趣,请尽量减少点(每个点都是一个查找),尤其是在循环中。

有两种方法。一种是如果您要访问不止一次,则将对象设置为最低的对象。

例如(较慢)

set xlapp = CreateObject("Excel.Application")
msgbox xlapp.worksheets(0).name 

(更快,因为每次使用对象时都会省略一个点)

set xlapp = CreateObject("Excel.Application")
set wsheet = xlapp.worksheets(0)
msgbox wsheet.name

第二种方式是with。一次只能有一个处于活动状态。

这会跳过 100 次查找。

with wsheet
For x = 1 to 100
 msgbox .name
Next
end with

字符串连接

并且不要一次连接一个字符。从 VBScript 程序员那里看到这个。它需要 50,000 字节和多次分配和释放才能生成 100 个字符的字符串。

http://blogs.msdn.com/b/ericlippert/archive/2003/10/20/53248.aspx

读取属性

不要重新读取不会更改的属性,尤其是在进程外或后期绑定时。将它们放入变量中。

对象类型

这里有两个概念 - 进程内或进程外以及早期或晚期绑定。

exefiles 连接到进程外。所有调用都通过 RPC(一种网络协议)进行编组。 Dllfile 正在处理中,函数调用直接通过跳转进行。

早期绑定是set x = objecttype。编写程序时会查找函数。在执行时,程序被硬编码为跳转到存储在该函数的 vtable 中的地址。

延迟绑定设置为x = createobject("objecttype")。每个函数调用都是这样的。 “您好,您有打印命令吗”。 “是的”,它回答,“命令号 3”。 “嗨,对象,请你执行 3 号命令”。 “当然,这是结果”。

来自 Visual Basic 概念(帮助的一部分)

您可以通过优化 Visual Basic 解析对象引用的方式使您的 Visual Basic 应用程序运行得更快。 Visual Basic 处理对象引用的速度可能受以下因素影响:

ActiveX 组件是否已实现为进程内服务器或进程外服务器。

对象引用是早期绑定还是后期绑定。通常,如果一个组件已作为可执行文件(.exe 文件)的一部分实现,则它是一个进程外服务器并在其自己的进程中运行。如果它被实现为动态链接库,则它是一个进程内服务器,并与客户端应用程序在同一进程中运行。

使用进程内服务器的应用程序通常比使用进程外服务器的应用程序运行得更快,因为应用程序不必跨越进程边界来使用对象的属性、方法和事件。有关进程内和进程外服务器的更多信息,请参阅“进程内和进程外服务器”。

如果对象引用使用声明为特定类的变量的对象变量,则它们是早期绑定的。如果对象引用使用声明为通用 Object 类的变量的对象变量,则对象引用是后期绑定的。使用早期绑定变量的对象引用通常比使用后期绑定变量的对象引用运行得更快。

Excel 特定

查看来自 Microsoft 人员的此链接。这是特定于 excel 而不是 VBA。自动计算和其他计算选项/屏幕更新等。

http://blogs.office.com/2009/03/12/excel-vba-performance-coding-best-practices/

【讨论】:

  • 非常感谢您的详细回复!真是太棒了!我想我(一个编程新手希望在不使用独立 CAT 工具的情况下自动化他的部分翻译工作)需要一段时间来消化它:)
猜你喜欢
  • 1970-01-01
  • 2021-05-13
  • 2011-04-27
  • 2016-11-01
  • 2010-12-17
  • 1970-01-01
  • 1970-01-01
  • 2015-09-03
  • 1970-01-01
相关资源
最近更新 更多