...
...

Гигантские размеры документа

При постоянном редактировании документа, внесении в него глобальных и мелких изменений, например, при вставке, удалении или перемещении графических объектов, изменении последовательности разделов документа и многих других случаях, сохраняемый файл постоянно растет в размере. Дело, порой, доходит до смешного — документ размером в 30 килобайт вырастает в несколько раз до 400 и более килобайт. Такая проблема решается просто. Нужно выделить документ, скопировать его в буфер обмена, закрыть документ, создать новый, скопировать в него содержимое буфера обмена и сохранить под прежним именем. Задача, в принципе, не очень сложная и требует выполнения всего шести операций. Однако шесть операций можно сократить до одной, воспользовавшись приведенным в статье макросом на Visual Basic for Application.

(c) Компьютерная газета
Объект Document
Макрос, который выполняет перенос и сохранение содержимого одного документа в другой, невелик, однако прежде чем привести его, нужно познакомиться с новым объектом — Document.
В Word для управления документами существуют два объекта: Documents и Document. Объект Documents является семейством и содержит перечень всех открытых в Word документов. Если вы воспользуйтесь несложным макросом, то можете узнать, сколько документов открыто, а также получить их названия:

Sub CountDocs()
S = "Открыто документов: " + Format(Documents.Count) + " " + Chr(13)
For Each D In Documents
S = S + D.Name + " "
Next
MsgBox Prompt:=S, Title:="Открытые документы"
End Sub

Другой объект — Document — ссылается на определенный документ. Например, если в Word открыто два документа, то Documents(1) ссылается на первый документ, а Documents(2) — на второй документ.
На практике ссылка на индекс документа используется очень редко, поскольку документы могут открываться в разном порядке, в результате чего каждый раз индекс изменяется. Впрочем, вместо числового индекса, можно использовать ссылку на имя документа, например, конструкция Documents ("mymacros.doc") будет ссылаться на документ с именем "mymacros.doc".
Чаще применяется идентификатор ActiveDocument, возвращающий ссылку на текущий текстовый документ Word, то есть, по сути, ссылку на объект Document. С его помощью можно выполнять огромное количество операций над документом: сохранять, выводить на принтер, проверять орфографию, объединять несколько документов и многое другое. В рассматриваемом макросе используются несколько свойств и методов объекта Document:
FullName — Возвращает полное имя документа, содержащее имя и путь файла. Это имя представляет собой обыкновенное строковое значение, которое можно сохранить в переменной или вывести с помощью инструкции MsgBox на экран.
Close — Закрывает документ. В методе Close можно указать параметр SaveChanges и присвоить ему значение True, если при закрытии документа изменения записываются в файле, и False, если изменения игнорируются.
SaveAs — Сохраняет документ под новым именем.
В методе SaveAs обычно указывается параметр FileName, определяющий имя и путь файла документа.

Всего восемь строк
Алгоритм решения задачи не сложен и уже приводился ранее. Еще раз напомним его.
1. Выделить содержимое документа.
2. Скопировать содержимое документа в буфер обмена.
3. Закрыть текущий документ.
4. Создать новый документ.
5. Вставить в него текст и объекты из буфера обмена.
6. Сохранить документ под прежним именем.
Для каждой из этих операций в Visual Basic for Application есть отдельная конструкция, но поскольку необходимо максимально автоматизировать операцию копирования содержимого документа, в программе появляются дополнительные строки, обеспечивающие дополнительную функциональность. Команда On Error Resume Next блокирует вывод сообщений об ошибке при попытке, к примеру, запустить макрос при отсутствии открытых документов. Кроме того, в программе используется переменная OldName, которая сохраняет имя текущего файла — эта операция необходима, поскольку после закрытия документа его имя становится недоступным.

Sub SaveNewDocument()
On Error Resume Next
OldName = ActiveDocument.FullName
ActiveDocument.Select
Selection.Copy ' копируем выделенный документ в буфер обмена
ActiveDocument.Close SaveChanges:=True ' закрываем с сохранением
Documents.Add ' создаем новый документ
Selection.Paste ' вставляем из буфера обмена
ActiveDocument.SaveAs FileName:=OldName ' сохраняем документ
End Sub

Дополнительные штрихи

При неоднократном использовании макроса SaveNewDocument обнаружился ряд странностей, которые вполне могут быть отнесены к багам Word. Например, иногда возникали проблемы при копировании содержимого полей или терялось форматирование абзацев как списка — все эти проблемы никак не зависят от макроса, ибо в нем не используются какие-то необычные операции, вызываются лишь стандартные методы объектов Visual Basic for Application.
Тем не менее, перед копированием текста в буфер обмена, то есть перед командой Selection.Copy, рекомендуется добавить строку ActiveDocument. Fields.Update или Selection.Fields. Update. Эта строка обновляет содержимое полей внутри документа или внутри выделенной области (а поскольку предварительно был выделен весь документ целиком, то эти конструкции практически эквивалентны).

Необходимый сервис

Напоследок, как обычно, совет о том, как вводить и исполнять этот макрос. Наилучшее его местоположение — шаблон Normal.dot. Но если при создании документов используются другие шаблоны, макрос следует добавить к вашему собственному шаблону.
1. Запустите текстовый процессор Word.
2. Нажмите Alt-F11.
3. В окне проекта (если окно проекта закрыто, нажмите Ctrl-R) на строке Normal щелкните правой кнопкой мыши и укажите Вставить — Модуль.
4. В модуле вставьте процедуру SaveNewDocument.
5. Наберите строки между Sub и End Sub — см. выше.
6. Сохраните шаблон Normal.dot.
7. Теперь вы можете связать процедуру SaveNewDocument с кнопкой панели инструментов. Эта операция вам должна быть уже знакома, поскольку описывалась в предыдущих макросах.

Сергей Лосев

© Компьютерная газета

полезные ссылки
Оффшорные банковские счета