vba 在多个列表段落上循环 Word 宏会导致内存问题
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5002209/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Looping a Word macro over many list paragraphs causes memory issue
提问by Steven
I'm hitting problem with a reasonably straightforward vba macro for Microsoft Word which is designed to get around some issues we're seeing with list indentation when we create PDFs versions from the Word doc.
我遇到了一个用于 Microsoft Word 的相当简单的 vba 宏的问题,该宏旨在解决我们在从 Word 文档创建 PDF 版本时遇到的列表缩进问题。
The macro basically loops through each list in the document, and for each list paragraph associated with the list, it is setting the list template's bullet and text position to match what's applied at the paragraph level (code needs to be used with Word 2000 so not using list styles).
该宏基本上循环遍历文档中的每个列表,并且对于与列表关联的每个列表段落,它设置列表模板的项目符号和文本位置以匹配在段落级别应用的内容(代码需要与 Word 2000 一起使用,因此不是使用列表样式)。
When dealing with large documents (60+ lists, ~350 list paragraphs), the macro runs through fine first time, but second time dies half way through with a "This method or property is not available because there is a memory or disk problem".
处理大型文档(60+ 个列表,~350 个列表段落)时,宏第一次运行良好,但第二次运行到一半时出现“此方法或属性不可用,因为存在内存或磁盘问题” .
I've gone down the usual route of unsetting any object references used during the loop, so I can't see what might be holding on to the memory.
我已经按照通常的路线取消了循环期间使用的任何对象引用,所以我看不到什么可能会保留在内存中。
The code is quite simple and consists of a single procedure, currently stored in ThisDocument:
代码非常简单,由一个过程组成,当前存储在 ThisDocument 中:
Option Explicit
Sub test2()
Dim i As Integer, n As Integer
Dim curList As List, curPar As Paragraph, templ As ListTemplate
Dim gapSize As Double, level As Integer
Application.ScreenUpdating = False
Application.Options.Pagination = False
For i = 1 To Lists.Count
Set curList = Lists(i)
For n = 1 To curList.ListParagraphs.Count
Set curPar = curList.ListParagraphs(n)
Set templ = curPar.Range.ListFormat.ListTemplate
level = curPar.Range.ListFormat.ListLevelNumber
gapSize = templ.ListLevels(level).TextPosition - templ.ListLevels(level).NumberPosition
templ.ListLevels(level).NumberPosition = curPar.LeftIndent - gapSize
templ.ListLevels(level).TextPosition = curPar.LeftIndent
templ.ListLevels(level).TabPosition = curPar.TabStops.After(curPar.LeftIndent - gapSize).position
Set templ = Nothing
Set curPar = Nothing
Next n
UndoClear
Set curList = Nothing
Next i
Application.ScreenUpdating = True
Application.Options.Pagination = True
End Sub
回答by Steven
I've found a nasty, dirty solution that gets around the issue somewhat but is really a very poor fix. Basically, once we have gotten through one complete run of the macro, close and save the document and immediately reopen. This then allows the macro to be rerun immediately or at any stage because closing the document seems to eventually flush the memory properly. Obviously this can only be used if the user is happy to save as part of running the macro, but in my case it is
我发现了一个讨厌的、肮脏的解决方案,它在某种程度上解决了这个问题,但实际上是一个非常糟糕的解决方案。基本上,一旦我们完成了一次完整的宏运行,关闭并保存文档并立即重新打开。这将允许立即或在任何阶段重新运行宏,因为关闭文档似乎最终会正确刷新内存。显然,这只能在用户乐于将其保存为运行宏的一部分时使用,但在我的情况下
回答by Patrick Honorez
Your code looks OK and my sugestions will be just ideas to try doing the same another way...
Idea 1: insert a DoEvents somewhere in the innerloop, to facilitate garbage collection.
Idea 2: simplify your code by using FOR EACH constructs:
您的代码看起来不错,我的建议只是尝试以另一种方式做同样的事情的想法...
想法 1:在内循环中的某处插入一个 DoEvents,以促进垃圾收集。
想法 2:通过使用 FOR EACH 构造来简化您的代码:
For Each curlist in Lists
For each curPar in curList.ListParagraphs
With curPar.Range.ListFormat.ListTemplate
.....
End With
Next curPar
Next curList
回答by Tiago Cardoso
Besides UndoClear, you can also save the document at each loop.
除了 UndoClear,您还可以在每个循环中保存文档。
It might heavily impact in your macro performance, though.
不过,它可能会严重影响您的宏观性能。
There's a similar issue here http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/de7a88b4-914f-4895-a88a-659b732e8d87/
这里有一个类似的问题http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/de7a88b4-914f-4895-a88a-659b732e8d87/
Hope this helps.
希望这可以帮助。