开发者

Looping a Word macro over many list paragraphs causes memory issue

开发者 https://www.devze.com 2023-02-10 07:48 出处:网络
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 th

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, 开发者_C百科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'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


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:

For Each curlist in Lists
    For each curPar in curList.ListParagraphs
       With curPar.Range.ListFormat.ListTemplate
          .....
       End With
    Next curPar
Next curList


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消