RU|DTP - настольные издательские системы
Home | FAQ | Литература | Статьи | Документы ICC | Prepressure | Download | Форум Восстановленная копия сайта RuDtp.ru

СТАТЬИ

Сергей Горбачев
Спуск полос из Word-a с использованием VBA.

В предыдущей статье описано, как с помощью печати на виртуальный принтер можно осуществить спуск полос из Word. Но там же было упомянуто, что «ручное» определение диапазона страниц для печати не только достаточно трудоемко, но и весьма ненадежно, поскольку ошибка даже в одной цифре безнадежно «завалит» всю работу.

Чтобы решить эту проблему, следует использовать возможности программирования на языке Visual Basic for Application (VBA), который является неотъемлемой частью офисного пакета Microsoft Office.

О Basic-е мощном замолвите слово...

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

Прежде всего – маленький исторический экскурс. Уже в ранних версиях офисного пакета присутствовала возможность записи и использования макросов (то есть наборов команд, выполняющих определенные функции). Сейчас макросы заменены полноценным языком программирования, но название осталось, и в пункте главного меню «Сервис» присутствует подменю «Макрос». Пусть вас это скромное название не вводит в заблуждение – под ним скрывается целый клад удивительно эффективных возможностей, которыми просто грех не воспользоваться.

Если вы пока еще не знакомы с языком программирования VBA – не беда, сама «конструкция» офисного пакета дает пользователю прекрасную возможность освоить элементарные приемы работы с ним, записывая макросы и анализируя их. Конечно, таким способом вряд ли можно стать полноценным программистом, но подобная задача перед нами и не стоит. Нам всего лишь нужно с помощью VBA автоматизировать рутинные операции подготовки изданий к печати. А с этой задачей нам справиться вполне по силам. Повторюсь: VBA – полноценный и очень мощный язык программирования, для полного описания которого потребуется многотомное издание, поэтому в статье будем говорить только о тех возможностях и особенностях языка, которые мы будем использовать.

Начнем с самого простого – запишем макрос и посмотрим на его структуру (чуть позже мы эту структуру будем редактировать; кстати, запись макроса и еще последующий анализ – лучший способ первоначально изучения VBA).

Необходимое примечание. Программа, которая сейчас будет описана, довольно проста и потому требует некоторого «ручного» контроля, в частности, нужно внимательно следить, чтобы количество страниц в документе было кратно четырем и нумерация начиналась с первой страницы. Если эти условия не будут выполнены, то порядок страниц в выходном файле будет неправильным. Когда читатели познакомятся с общей концепцией построения такой программы, они самостоятельно могут дописать необходимые модули контроля (у автора они написаны). Пока что – основы.

Запись действий пользователя в макрос (программу VBA)

Поскольку нам предстоит написать программу для печати на виртуальный принтер, давайте с этого и начнем.

Начать запись макроса можно, как минимум, двумя способами.

  • выбрав «Сервис» - «Макрос» - «Начать запись»
  • нажав кнопку «ЗАП» в строке состояния Word (Рис 1.)

  • Рис. 1

И в том, и в другом случае появится диалоговое окно записи макроса (Рис.2.)..


Рис. 2

Назовем макрос «Спуск_полос». При именовании макроса очень важно помнить, что имя макроса можно записывать и кириллицей, но в нем не должно быть пробелов: все пробелы следует заменить нижней черточкой «_», иначе при попытке исполнения будет выдана ошибка и программа остановится. Укажем, что этот макрос будет доступен для всех документов (шаблон Normal.dot) и нажмем кнопку Ok. На экране появится маленькая панель инструментов (Рис. 3. Панель состояния записи макроса), указывающая, что программа находится в состоянии записи макроса. На ней всего две кнопки: «Остановить запись» и «Пауза». Теперь до того момента, пока пользователь не нажмет кнопку «Остановить запись», практически все наши действия с документом будут записываться.

Отправим на виртуальный принтер наш документ (как установить виртуальный принтер и как настроить систему для корректной подготовки и обработки PostScript-файлов, описано в предыдущей статье).

То есть настройки меню печати должны выглядеть вот так:

  • Принтер ... имя: Linotronic 330
  • Масштаб .. число страниц на листе: 2
  • Масштаб … по размеру страницы: Текущий или А4
  • Страницы … номера: «16,1,2,15,14,3,4,13,12,5,6,11,10,7,8,9» (это в случае, если печатаем 16-страничную брошюру).

Нажимаем Ok – и программа просит указать папку, куда следует поместить создаваемый PostScript-файл. Укажем подкаталог In папки наблюдения (Watched Folder), которую мы определили ранее для Acrobat Distiller (см. предыдущую статью). Это означает, что при активном Acrobat Distiller любой корректно созданный PostScript-файл, помещенный в эту папку, будет автоматически преобразовываться в PDF-файл и помещаться в подкаталог Out той же папки. Папка наблюдения может находиться где угодно, хотя, чтобы не путаться, я, как правило, создаю ее в корневом каталоге системного диска и помещаю туда все создаваемые PostScript-файлы.

Теперь еще раз Ок – и будет создан PostScript-файл, а команда печати запишется в виде макроса. Нажмем кнопку «Остановить запись» (Рис. 3) – макрос печати записан, и можно его редактировать, дописывая необходимые команды.


Рис. 3

Вызовем окно макросов (либо нажав Alt-F8, либо через главное меню Сервис –> Макрос –> Макросы). Появится диалоговое окно Макрос (Рис.4 Окно Макрос). Поскольку наш макрос мы записали в общий шаблон Word (Normal.dot), то в списке Макросы из: укажем именно этот шаблон.


Рис. 4

Откроем макрос Спуск_полос, нажав кнопку «Изменить». Тем самым мы запускаем редактор программ VBA, где и будем редактировать нашу программу.

Пока что она имеет вот такой вид.

Sub Спуск_полос()
' Спуск_полос Макрос
' Макрос записан 04.06.02 *
'
  ActivePrinter = "Linotronic 330"

  Application.PrintOut FileName:="", Range:=wdPrintRangeOfPages, _
    Item:=wdPrintDocumentContent, Copies:=1, _
    Pages:="16,1,2,15,14,3,4,13,12,5,6,11,10,7,8,9", _
    PageType:=wdPrintAllPages, Collate:=True, _
    Background:=True, PrintToFile:=True, PrintZoomColumn:=2, PrintZoomRow:=1, _
    PrintZoomPaperWidth:=11907, PrintZoomPaperHeight:=16839, _
    OutputFileName:="", Append:=False
End Sub

Обратите внимание, что программа начинается строкой Sub с именем макроса и скобками после этого имени, а завершается строкой End Sub. Это – обязательное условие для работы программы на VBA. Отметим также, что некоторые строки начинаются со знака апострофа. Это – комментарии, они служат для пояснения как работы программы в целом, так и ее отдельных элементов. Как правило, в редакторе VBA строки комментариев отображаются зеленым цветом.

Редактирование записанного макроса

Имея записанный макрос, можем приступить к его редактированию. Но сначала определимся, что в нем должно быть для успешной работы.

Структурно наш макрос будет состоять из следующих частей:
I. Создание и инициализация переменных
II. Формирование переменных для печати
III. Исполняемая часть (печать документа)

Исполняемая часть уже готова – это две последние команды (определение активного принтера и собственно печать). А вот первые две части мы будем дописывать.

При этом в первой части мы создадим и инициализируем все необходимые нам переменные, а во второй – присвоим этим переменным необходимые значения. Но начнем редактировать наш макрос с последней – самой простой - команды печати. Это – третья часть нашей программы.

Редактирование команды печати

В этой части (да и пока что – во всей нашей программе) всего две команды: первая определяет активный принтер, на который будет печататься документ; вторая устанавливает параметры печати и печатает документ. Вторая команда довольно длинная, поэтому разбита на несколько строк с помощью символа подчеркивания (нижний дефис) «_». Этот знак говорит о том, что команда не завершена и продолжается в следующей строке.

Первую команду мы оставим неизменной, а некоторые части второй будем модифицировать.

Сразу же удалим часть команды FileName:="", – она нам не нужна.

Для выполнения поставленной задачи нам нужно изменить только два элемента в команде печати на виртуальный принтер (прочие части этой команды уже содержат необходимую информацию для печати двух страниц на листе А4, и мы их трогать не будем).

Пока что эти элементы, которые нужно изменить в команде печати, выглядят вот так:
а) список страниц для печати (Pages:= "16,1,2,15,14,3,4,13,12,5,6,11,10,7,8,9") и
б) полное имя создаваемого PostScript-файла, который затем будет преобразован в PDF (OutputFileName:="").

Сначала нам нужно вместо строк, определяющих параметры этих элементов подставим имена переменных: : sListOfPages – список страниц для печати и sFileNamePS – полное имя создаваемого PostScript-файла.

После первоначальной правки наш макрос примет вот такой вид (первые две части пока что пусты):

Sub Спуск_полос()

‘ Создание и инициализация переменных

‘ Формирование переменных для печати

‘ Исполняемая часть (печать документа)
  ActivePrinter = "Linotronic 330"
  Application.PrintOut Range:=wdPrintRangeOfPages, _
    Item:=wdPrintDocumentContent, Copies:=1, _
    Pages:= sListOfPages, _
    PageType:=wdPrintAllPages, Collate:=True, _
    Background:=True, PrintToFile:=True, _
    PrintZoomColumn:=2, PrintZoomRow:=1, _
    PrintZoomPaperWidth:=11907, PrintZoomPaperHeight:=16839, _
    OutputFileName:= sFileNamePS, _
    Append:=False
End Sub

Создание и инициализация переменных

Вообще-то, по строгим правилам программирования, следовало бы сначала определить все переменные, используемые в программе, и указать их тип. Но, поскольку у нас всего один небольшой модуль и вопросы экономии памяти и быстродействия программы для нас некритичны, предоставим VBA самостоятельно определять переменные при их создании и инициализации, то есть – в момент первого присвоение значения.

Ниже приведен список всех переменных, которые понадобятся нам для корректной работы программы. Обратите внимание, что все переменные в программе имеют префиксы, которые указывают на тип переменной: символьный (“s”) или численный (“n”). Это хотя и не обязательно, но весьма полезно, чтобы не путаться в идентификации переменных.

nPageStart = 1 ‘ номер ПЕРВОЙ страницы документа
nPageFinish = 16 ‘ номер ПОСЛЕДНЕЙ страницы документа
sPageStart = Str(nPageStart) ‘ представление номера ПЕРВОЙ страницы документа в СИМВОЛЬНОМ виде
sPageFinish = Str(nPageFinish) ‘ представление номера ПОСЛЕДНЕЙ страницы документа в СИМВОЛЬНОМ виде
sPagesPrint = "" ‘ символьная строка с номерами пар страниц для каждого листа
nPageMin = 0 ‘ МЕНЬШИЙ номер страницы документа в паре для печати на один лист
nPageMax = 0 ‘ БОЛЬШИЙ номер страницы документа в паре для печати на один лист
sPageMin = "" ‘ символьное представление МЕНЬШЕГО номера страницы в паре
sPageMax = "" ‘ символьное представление БОЛЬШЕГО номера страницы в паре
sDirIn = "" ‘ имя каталога для записи PostScript-файла
nCounter = 0 ‘ счетчик количества листов для печати
sListOfPages = "" ‘ символьная строка со списком номеров страниц для печати
sFileNamePS = "" ‘ полное имя файла для записи в PostScript
sFileNameDOC = "" ‘ «короткое» имя документа для записи в PostScript

Большая часть этих переменных нужна нам для расчетов, а в исполняемую часть программы нам подставим всего две «финишные» переменные: sListOfPages – диапазон страниц для печати и sFileNamePS – полное имя PostScript-файла.

Уже здесь мы укажем значения для численных переменных nPageStart и nPageFinish (1 и 16 соответственно). Эти переменные созданы в начале списка неслучайно, поскольку, пока не написан модуль контроля количества страниц в документе, эти параметры нужно будет задавать явно. То есть – если количество страниц в документе не 16, а иное, то нужно просто открыть макрос для изменения (Alt-F8 => выбрать макрос «Спуск_полос» => Изменить) и ввести вместо числа 16 реальное количество страниц вашего документа. Сразу же после этого на основе переменных nPageStart и nPageFinish созданы переменные sPageStart и sPageFinish, содержащие те же данные, только преобразованные в символьный вид с помощью функции Str().

Формирование переменных для подстановки в команду печати

Переменная sListOfPages (список страниц для печати в PostScript-файл)

Содержимое переменной sListOfPages мы уже вводили вручную, осталось только придумать, как ее рассчитать автоматически.

В сущности, все очень просто – нужно, начиная с первой и последней страниц документа, идти от «краев» к «середине» и сформировать строку, состоящую из пар страниц; причем в каждой паре первой (левой страницей разворота) всегда должна стоять четная страница. Для этого в переменную sListOfPages будем последовательно добавлять пары страниц, присвоенные переменной sPagesPrint

Начнем цикл For ... Next, который будет “идти” по номерам страниц от первой (определенной в переменной nPageStart) до середины списка (номер последней страницы, деленный на два: nPageFinish / 2).

То есть цикл последовательно «переберет» номера страниц от 1 до 8, каждый раз присваивая переменной счетчика nCounter текущее значение.

For nCounter = nPageStart To nPageFinish / 2
    ... (сюда нужно вставить все описанные ниже в этом разделе команды)
Next

Для создания этой части программы выполним следующее:

1. Определим номера пар страниц для каждого печатного листа. Очевидно, что меньший из номеров в каждой паре – просто текущее значение счетчика. Для подстановки в строковую переменную номера страницы необходимо преобразовать численное значение счетчика в символьную строку, что мы и сделаем с помощью функции Str().
sPageMin = Str(nCounter)

А вот для определения большей страницы в текущей паре нужно от номера конечной страницы отнять текущее значение счетчика и прибавить единицу. Ну и, конечно, тоже преобразовать результат в символьную строку с помощью функции Str().
sPageMax = Str(nPageFinish – nCounter + 1)

Не лишним будет также убрать лишние пробелы из символьных переменных с помощью функции Trim(), после чего эти две строки приобретут вот такой вид:
sPageMin = Trim(Str(nCounter))
sPageMax = Trim(Str(nPageFinish – nCounter + 1))

2. Следующий шаг – составим пары страниц для каждого печатного разворота так, чтобы четная страница всегда была первой в паре, и запишем результат в переменную sPagesPrint. Для этого используем структуру ветвления (оператор условия) If … Then … … End If.

Если значение счетчика nCounter – нечетное число (остаток от деления значения счетчика на два, вычисляемый оператором Mod, больше нуля), то в паре страниц первой ставится большая по номеру страница, если значение четное – меньшая.

If nCounter Mod 2 > 0 Then
    ' если первая нечетная
    sPagesPrint = sPageMax + "," + sPageMin
Else
    ' если первая четная
    sPagesPrint = sPageMin + "," + sPageMax
End If

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

If nCounter = 1 Then
    sListOfPages = sListOfPages + sPagesPrint
Else
    sListOfPages = sListOfPages + "," + sPagesPrint
End If

На этом часть программы, формирующая список страниц для печати, завершена. В результате ее выполнения создана символьная переменная sListOfPages, содержащая следующую строку "16,1,2,15,14,3,4,13,12,5,6,11,10,7,8,9".

Переменная sFileNamePS (полный путь для записи PostScript-файла)

Переменная sFileNamePS (полное имя файла) должна выглядеть так: «C:\_Image\In\<Имя_документа>_спуск_1-16.ps».

Чтобы создать ее, необходимо сделать следующее.

1. Запишем в переменную sFileNameDOC "короткое" (без указания каталога) имя файла активного документа. При этом все символы имени будут преобразованы в строчные (малые) буквы с помощью функции LCase(). Это преобразование хотя и не обязательно, но желательно, потому что при большом количестве файлов в папке проще находить нужный файл, когда все имена набраны в одном регистре.
sFileNameDOC = LCase(ActiveDocument.Name)

2. Заменим в «коротком» имени файла все точки на знак "_" с помощью функции Replace(). Это необходимо во избежание путаницы с определением места, где заканчивается файл и начинается его расширение. Из имени файла можно было бы удалить и само расширение, но делать этого не стоит, поскольку приходится работать с файлами разных типов (как *.doc, так и *.rft). А для надежной идентификации источника PDF-файла лучше видеть имя исходного файла полностью, с расширением.
sFileNameDOC = Replace(sFileNameDOC, ".", "_")

3. Дополним «короткое» имя словом ”_спуск_“и диапазоном страниц, которые выводятся на печать (эти данные, как вы помните, мы уже рассчитали в первой части программы, создав переменные sPageStart и sPageFinish).
sFileNameDOC = sFileNameDOC + "_спуск_" + sPageStart + "-" + sPageFinish

4. Укажем каталог для записи файлов печати PostScript. Это подпапка “In” той самой папки наблюдения, которую мы определили в установках Acrobat Distiller Я назвал ее “_Images”, но можно использовать любое другое имя, например “_Output” или “_Watched Folder”. Обратите внимание, что имена таких папок начинаются с подчеркивания. Это сделано для того, чтобы наша папка наблюдения находилась в начале списке папок на диске и ее не нужно было долго искать (а заглядывать в нее придется часто).
sDirIn = "C:\_Images\In\"

5. И, наконец, «соберем» полное (то есть – с указанием каталога) имя файла для печати и запишем его в переменную sFileNamePS. Для этого просто соединим имя каталога для записи PostScript-файла и «короткое» имя файла, добавив к ним расширение ".ps".
sFileNamePS = sDirIn + sFileNameDOC + ".ps"

В результате выполнения этой части программы создана символьная переменная sFileNamePS, содержащая следующую строку "<Имя_документа>_спуск_1-16.ps".

Это, собственно, и все. В конечном итоге наша программа должна выглядеть вот так.

Sub Спуск_полос()

‘ Создание и инициализация переменных
nPageStart = 1 ‘ номер ПЕРВОЙ страницы документа
nPageFinish = 16 ‘ номер ПОСЛЕДНЕЙ страницы документа
sPageStart = Str(nPageStart)
sPageFinish = Str(nPageFinish)
sPagesPrint = ""
nPageMin = 0
nPageMax = 0
sPageMin = ""
sPageMax = ""
sDirIn = ""
nCounter = 0
sListOfPages = ""
sFileNamePS = ""
sFileNameDOC = ""

‘ Формирование переменных для печати
For nCounter = nPageStart To nPageFinish / 2
  sPageMin = Trim(Str(nCounter))
  sPageMax = Trim(Str(nPageFinish – nCounter + 1))

  If nCounter Mod 2 > 0 Then
    ' если первая нечетная
    sPagesPrint = sPageMax + "," + sPageMin
  Else
    ' если первая четная
    sPagesPrint = sPageMin + "," + sPageMax
  End If

  If nCounter = 1 Then
    sListOfPages = sListOfPages + sPagesPrint
  Else
    sListOfPages = sListOfPages + "," + sPagesPrint
  End If
Next

sFileNameDOC = LCase(ActiveDocument.Name)
sFileNameDOC = Replace(sFileNameDOC, ".", "_")
sFileNameDOC = sFileNameDOC + "_спуск_" + sPageStart + "-" + sPageFinish
sDirIn = "C:\_Image\In\"
sFileNamePS = sDirIn + sFileNameDOC + ".ps"

‘ Исполняемая часть (печать документа)
  ActivePrinter = "Linotronic 330"
  Application.PrintOut Range:=wdPrintRangeOfPages, _
    Item:=wdPrintDocumentContent, Copies:=1, _
    Pages:= sListOfPages, _
    PageType:=wdPrintAllPages, Collate:=True, _
    Background:=True, PrintToFile:=True, _
    PrintZoomColumn:=2, PrintZoomRow:=1, _
    PrintZoomPaperWidth:=11907, PrintZoomPaperHeight:=16839, _
    OutputFileName:= sFileNamePS, _
    Append:=False
End Sub

Теперь откройте в Word файл, который нужно вывести на печать, нажмите Alt-F8, найдите в списке макросов «Спуск_полос» и кликните «Выполнить». PostScript-файл будет автоматически записан в указанный вами каталог. Если при этом Acrobat Distiller активен, то PDF-файл с именем "<Имя_документа>_спуск_1-16.pdf". будет сразу же создан и помещен в подпапку Out папки наблюдения.

Запускайте Adobe Acrobat, открывайте созданный PDF – и печатайте готовый спуск полос на любой принтер. Если не забыли, то драйвер виртуального принтера Linotronic 330 можно настроить так, чтобы сразу же делать «зеркальные» файлы для вывода пленок на обычном принтере.

Рекомендую перед печатью всего документа внимательно просмотреть его и напечатать на пробу парочку разворотов со страницами, где есть графические элементы (особенно – векторные). Очень редко, но бывают случаи, когда при печати таких элементов вокруг рисунка появляется тонкая линия. Способ решения этой проблемы – подобрать другой виртуальный принтер (например, Agfa или CreatePDF из нового и очень удачного пакета Adobe PressReady).

В общем, как и при использовании любого программного продукта в реальных (чуть не сказал «боевых») условиях необходимо экспериментировать. Очень скоро вы подберете нужные режимы и будете успешно готовить свои издания к печати, экономя свое время.

Вместо заключения

Представленная здесь программа, написанная на VBA – минимально необходимый набор команд для успешной печати спуска полос из Word. На самом деле написанная автором этой статьи программа значительно больше и включает в себя еще модули контроля количества страниц в документе (это количество должно быть кратно 4), экранные диалоговые окна для ввода начальных параметров (определение диапазона разворотов на вывод, например), настроенные панели инструментов для быстрого запуска макроса и т.д. Но описание всего этого заняло бы слишком много места, да и задача статьи, в общем-то, иная: показать коллегам потенциальные возможности автоматизации работы путем программирования на VBA для офисных приложений.

Кроме того, данная программа, если внимательный читатель заметил, предназначена для печати документов с небольшим количеством страниц. Дело в том, что внакидку (то есть – одной тетрадкой) можно печатать издания объемом до 80 страниц. Большее количество листов сложно сшивать, да и потом, такое издание будет выглядеть несуразно, его неудобно читать. Для изданий с большим количеством страниц применяется либо сборка на термобиндер, либо ниткошвейное соединение. Соответственно и спуск полос в таком случае следует делать не одной тетрадкой, а несколькими, в каждой из которых может быть от 4 до 32 страниц.

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

В следующей статье – описание приемов коррекции полей и масштаба подготовленных в Word публикаций без переверстки. Проблема, хотя и чрезвычайно болезненная для реальной практики фирм оперативной полиграфии, но вполне успешно решаемая с помощью VBA и программы Adobe Acrobat.

С автором статьи можно связаться по адресу: kpi_publish@ukrpost.net



Дата размещения: 2002-10-21 15:27:30
Видеокурс Допечатная подготовка журнала
Desktop Publishing на человеческом языке
Разделы: Home | FAQ | Литература | Статьи | Документы ICC | Prepressure | Download | Форум

О «мертвых» линках и ошибках сообщать вебмастеру бесполезно. Это восстановленная после аварии копия сайта.

Дизайн: N-design