在多个列表段落上循环 Word 宏会导致内存问题
我遇到了一个相当简单的 Microsoft Word vba 宏问题,该宏旨在解决当我们从 Word 文档创建 PDF 版本时我们在列表缩进中遇到的一些问题。
该宏基本上循环遍历文档中的每个列表,并且对于与列表关联的每个列表段落,它设置列表模板的项目符号和文本位置以匹配在段落级别应用的内容(代码需要与 Word 2000 一起使用,因此不能使用列表样式)。
处理大型文档(60+列表,~350列表段落)时,宏第一次运行良好,但第二次中途终止,并显示“此方法或属性不可用,因为存在内存或磁盘问题” 。
我已经采用了取消设置循环期间使用的任何对象引用的常用方法,因此我看不到可能占用内存的内容。
代码非常简单,由一个过程组成,当前存储在 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
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.
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).
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".
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:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我找到了一个令人讨厌、肮脏的解决方案,可以在一定程度上解决这个问题,但实际上是一个非常糟糕的解决方案。基本上,一旦我们完成了宏的一次完整运行,关闭并保存文档并立即重新打开。然后,这允许立即或在任何阶段重新运行宏,因为关闭文档似乎最终会正确刷新内存。显然,只有当用户愿意在运行宏的过程中保存时才能使用此功能,但就我而言,它是
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
你的代码看起来不错,我的建议只是尝试以另一种方式做同样的事情的想法......
想法1:在内循环中的某处插入DoEvents,以方便垃圾回收。
想法 2:通过使用 FOR EACH 结构来简化代码:
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:
除了 UndoClear 之外,您还可以在每次循环时保存文档。
不过,它可能会严重影响您的宏观表现。
这里有一个类似的问题 http ://social.msdn.microsoft.com/Forums/en-US/vsto/thread/de7a88b4-914f-4895-a88a-659b732e8d87/
希望这有帮助。
Besides UndoClear, you can also save the document at each loop.
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/
Hope this helps.