Зацикливание макроса Word над многими абзацами списка приводит к проблемам с памятью - PullRequest
0 голосов
/ 15 февраля 2011

У меня возникла проблема с достаточно простым макросом vba для Microsoft Word, который предназначен для решения некоторых проблем, с которыми мы сталкиваемся при использовании отступов в списке при создании версий PDF-документов из документа Word.

Макрос в основном циклически проходит по каждому списку в документе, и для каждого абзаца списка, связанного со списком, он устанавливает маркер и позицию текста шаблона списка в соответствии с тем, что применяется на уровне абзаца (код должен использоваться с 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

Ответы [ 3 ]

1 голос
/ 16 февраля 2011

Я нашел грязное, грязное решение, которое несколько обошло проблему, но на самом деле это очень плохое решение.По сути, после того, как мы прошли один полный цикл макроса, закройте и сохраните документ и немедленно откройте его.Это тогда позволяет макросу быть перезапущенным немедленно или на любом этапе, потому что закрытие документа, кажется, в конечном счете очищает память должным образом.Очевидно, что это можно использовать только в том случае, если пользователь счастлив сохранить как часть макроса, но в моем случае это

0 голосов
/ 15 февраля 2011

Помимо UndoClear, вы также можете сохранять документ в каждом цикле.

Это может сильно повлиять на производительность вашего макроса.

Здесь есть похожая проблема http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/de7a88b4-914f-4895-a88a-659b732e8d87/

Надеюсь, это поможет.

0 голосов
/ 15 февраля 2011

Ваш код выглядит нормально, и мои предложения будут просто идеями, чтобы попытаться сделать то же самое другим способом ...
Идея 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...