Генерация документа шаблона из данных пользователя. Генерируем документы Microsoft Word на PHP

Мы живем в мире, где PHP разработчикам приходится время от времени взаимодействовать с операционной системой Windows. WMI (Windows Management Interface, Интерфейс управления Windows) - один из таких примеров - взаимодействие с Microsoft Office.

В данной статье мы рассмотрим простую интеграцию между Word и PHP: генерацию документа Microsoft Word на основе полей ввода в HTML-форме с помощью PHP (и его расширения Interop).

Подготовительные шаги

Первым делом убедимся, что у нас настроено базовое окружение WAMP. Так как Interop присутствует только в Windows, то нам необходимо, чтобы наш сервер Apache и инсталляция PHP были развернуты на Windows машине. В этом качестве я использую EasyPHP 14.1 , который крайне прост в установке и настройке.

Следующим делом необходимо установить Microsoft Office. Версия не очень важна. Я использую Microsoft Office 2013 Pro, но любая версия Office старше 2007 должна подойти.

Также необходимо убедиться, что у нас установлены библиотеки для разработки приложения Interop (PIA, Primary Interop Assemblies, Основные Сборки Interop). Узнать это можно открыв Проводник Windows, и перейдя в директорию \assembly , и там мы должны увидеть набор установленных сборок:

Здесь можно увидеть элемент Microsoft.Office.Interop.Word (подчеркнут на скриншоте). Это будет та сборка, которую мы будем использовать в нашей демонстрации. Пожалуйста, обратите особое внимание на поля “Assembly name (Имя сборки)”, “Version (Версия)” и “Public key token (Токен публичного ключа)”. Их мы скоро будем использовать в нашем PHP скрипте.

В этой директории также присутствуют и другие сборки (включая и все семейство Office), доступные для использования в своих программах (не только для PHP, но также и для VB.net, C#, и т.д.).

Если список сборок не включает весь пакет Microsoft.Office.Interop , то нам нужно либо переустановить Office, добавив PIA, или вручную загрузить пакет с сайта Microsoft и установить его. Для более детальных инструкций обратитесь к этой странице на MSDN .

Замечание : к загрузке и установке доступен только дистрибутив PIA Microsoft Office 2010. Версия сборок в этом пакете 14.0.0, а 15 версия поставляется только с Office 2013.

И, наконец, необходимо включить расширение php_com_dotnet.dll в php.ini и перезапустить сервер.

Теперь можно перейти к программированию.

HTML форма

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

У нас есть текстовое поле для имени, группа переключателей для пола, слайдер для возраста, и область ввода текста для ввода сообщения, а также небезызвестная кнопка “Отправить”.

Сохраните этот файл как “index.html” в директории виртуального хоста, чтобы до него можно было добраться по адресу типа http://test/test/interop .

Серверная часть

Файл-обработчик на серверной стороне - это основная цель нашего разговора. Для начала я приведу полный код этого файла, а потом объясню его шаг за шагом.

visible = true; $fn = __DIR__ . "\\template.docx"; $d = $w->Documents->Open($fn); echo "Документ открыт.


"; $flds = $d->Fields; $count = $flds->Count; echo "В документе $count полей.
"; echo "
    "; $mapping = setupfields(); foreach ($flds as $index => $f) { $f->Select(); $key = $mapping[$index]; $value = $inputs[$key]; if ($key == "gender") { if ($value == "m") $value = "Mr."; else $value = "Ms."; } if($key=="printdate") $value= date ("Y-m-d H:i:s"); $w->Selection->TypeText($value); echo "
  • Назначаю полю $index: $key значение $value
  • "; } echo "
"; echo "Обработка завершена!

"; echo "Печатаю, пожалуйста, подождите...
"; $d->PrintOut(); sleep(3); echo "Готово!"; $w->Quit(false); $w=null; function setupfields() { $mapping = array(); $mapping = "gender"; $mapping = "name"; $mapping = "age"; $mapping = "msg"; $mapping = "printdate"; return $mapping; }

После того, как мы записали в переменную $inputs значения, полученные из формы, а также создали пустой элемент с ключом printdate (зачем мы это сделали - обсудим позже), мы переходим к четырем очень важным строкам:

$assembly = "Microsoft.Office.Interop.Word, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"; $class = "Microsoft.Office.Interop.Word.ApplicationClass"; $w = new DOTNET($assembly, $class); $w->visible = true;

Манипулятор COM в PHP требует создания экземпляра класса в рамках “сборки”. В нашем случае мы работаем с Word. Если взглянуть на первый скриншот, то можно записать полную сигнатуру сборки для Word:

  • “Name”, “Version”, “Public Key Token” - все это берется из информации, которую можно просмотреть в “c:\Windows\assembly“ .
  • “Culture” всегда neutrual

Класс, на который мы хотим ссылаться, всегда называется “имя.сборки”+ “ .ApplicationClass “.

Установив два этих параметра мы сможем получить объект для работы с Word.

Этот объект может оставаться в фоне, или мы можем перевести его в рабочий режим установкой атрибута visible в true .

Следующим шагом открываем документ, требующий обработки, и записываем экземпляр “документа” в переменную $d .

Чтобы создать в документе содержимое, основанное на данных с формы, можно пойти несколькими путями.

Самым неправильным было бы жестко прописать содержимое документа в PHP, а потом вывести его в документ Word. Я настоятельно рекомендую этого не делать по следующим причинам:

  1. Вы теряете гибкость. Любые изменения в выходном файле потребуют изменения кода PHP.
  2. Это нарушает разделение управления и вида
  3. Применение стилей к содержимому документа (выравнивание, шрифты, стили, и т.д.) в скрипте сильно увеличит количество строк кода. Программное изменение стилей чересчур громоздко.

Другим вариантом будет использование поиска и замены. У PHP есть хорошие встроенные средства для этого. Мы можем создать документ Word, в котором разместим метки со специальными разделителями, которые в последствии будут заменены. Например, мы можем создать документ, который будет содержать следующий фрагмент:

а с помощью PHP мы легко можем заменить его на содержимое поля “Имя”, полученное с формы.

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

Я рекомендую третий способ, и он основывается на более глубоком знании Word. В качестве заполнителей мы будем использовать поля, а с помощью PHP кода будем непосредственно обновлять значения в полях соответствующими значениями.

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

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

В этом демонстрационном уроке мы будем использовать документ с 5 полями MERGEFIELD . Шаблонный документ разместим там же, где и наш скрипт-обработчик.

Прошу заметить, что поле printdate не имеет соответствующего поля на форме. Вот зачем мы добавили пустой элемент printdate в массив $inputs . Без этого скрипт все же будет запускаться и работать, но PHP будет выдавать предупреждение, что индекс printdate отсутствует в массиве $inputs .

После замены полей новыми значениями мы отпечатаем документ с помощью

$d->PrintOut();

Метод PrintOut принимает несколько необязательных параметров, и мы используем самую простую его форму. Так будет отпечатана одна копия документа на принтере по умолчанию, который присоединен к Windows-машине.

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

Необходимо подождать некоторое время, прежде чем завершить работу с приложением Word, так нужно время на то чтобы поставить в очередь задание на печать. Без delay(3) метод $w->Quit выполняется незамедлительно, и задание не ставится в очередь.

Наконец, мы вызываем $w->Quit(false) , что закрывает приложение Word, которое было вызвано нашим скриптом. Единственным параметром, передаваемым в метод, является указание сохранить файл перед выходом. Мы сделали правки в документе, но мы не хотим их сохранять, так как нам нужен чистый шаблон для последующей работы.

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

Улучшение скорости обработки и немного подробнее о PIA

PHP - слабо типизированный язык. Объект COM типа Object . Во время написания скрипта у нас нет возможности получить описание объекта, будь оно приложением Word, документом или полем. Мы не знаем, какие свойства есть у этого объекта, или какие он поддерживает методы.

Это сильно замедлит скорость разработки. Чтобы ускорить разработку, я бы рекомендовал писать функции сначала на C#, а после переводить код в PHP. Я могу рекомендовать бесплатную IDE для разработки на C# под названием “#develop”. Найти ее можно . Я предпочитаю ее Visual Studio, так как #develop меньше, проще и быстрее.

Миграция C# кода в PHP не так страшна, как кажется. Давайте я покажу вам пару строк на C#:

Word.Application w=new Word.Application(); w.Visible=true; String path=Application.StartupPath+"\\template.docx"; Word.Document d=w.Documents.Open(path) as Word.Document; Word.Fields flds=d.Fields; int len=flds.Count; foreach (Word.Field f in flds) { f.Select(); int i=f.Index; w.Selection.TypeText("..."); }

Можно заметить, что код на C# очень похож на код PHP, который я показывал ранее. C# - строго типизированный язык, так что в этом примере можно заметить несколько операторов приведения типов, а также переменным необходимо указывать тип.

С указанием типа переменной, можно наслаждаться более понятным кодом и автодополнением, и скорость разработки существенно повышается.

Другой способ повысить скорость разработки на PHP - вызывать макрос в Word. Мы проводим ту же последовательность действий, а после сохраняем ее как макрос. Макрос написан на Visual Basic, который также просто перевести в PHP.

И, что самое важное - документация по Office PIA от Microsoft , особенно документация по пространствам имен каждого приложения Office является самым детальным справочным материалом. Наиболее используемые три приложения:

  • Excel 2013: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.excel(v=office.15).aspx
  • Word 2013: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word(v=office.15).aspx
  • PowerPoint 2013: http://msdn.microsoft.com/en-us/library/microsoft.office.interop.powerpoint(v=office.15).aspx

Заключение

В этой статье мы показали, как заполнить данными документ Word с помощью библиотек PHP COM и возможностями взаимодействия Microsoft Office.

Windows и Office широко используются в повседневной жизни. Знать силу Office/Window и PHP будет полезно каждому PHP и Windows разработчику.

С помощью расширения PHP COM вам открывается дверь к использованию этой комбинации.

Все мы имеем дело с текстами, так или иначе. Иногда возникает потребность сгенерировать большое или не очень большое количество текста для каких-либо задач, например, поиграться с форматированием, а текста под рукой нет, самому писать лень. Что делать? Ответ простой: воспользоваться встроенным в Word генератором случайных текстов!

В редакторе Microsoft Word можно генерировать текст достаточно быстро и легко с помощью специальных команд. В качестве подопытного кролика буду использовать Word 2007. Эти команды должны работать во всех версиях Word. Расскажу о трех методах генерации текста.

Метод 1. Использование rand()

Функция rand() вставляет локализованный образец текста, 3 абзаца по 3 предложения. Откройте ваш Word, поставьте курсор в то место, где скоро появится куча текста и введите команду:

и нажмите Enter. Сама функция rand исчезнет и вместо нее появится 3 абзаца текста:

Но это еще не все. Если вам нужно много текста, то можно использовать функцию rand с дополнительными аргументами, вот в таком виде:

=rand(x,y)

где «x » означает количество абзацев, а «y » — количество предложений в каждом абзаце. Например, =rand(20,5) вставит 20 абзацев с пятью фразами в каждом. А =rand(7) вставит 7 абзацев по 3 предложения на каждый.

Метод 2. Использование lorem()

Чтобы вставить старый добрый Lorem Ipsum в качестве образца — применяем функцию lorem(). Введите следующую команду и нажмите Enter:

И получим вот такой всевдо-латинский текст

Функция lorem() также охотно принимает дополнительные аргументы, как и rand(), в виде количества абзацев и предложений. Без аргументов функция вставляет по умолчанию 3 абзаца с тремя предложениями в каждом.

Метод 3. Функция rand.old()

Использование аналолгично предыдущим командам:

=rand.old()

и нажать Enter.

Функция rand.old() оставлена для совместимости со старым офисом, до 2003 включительно. Способ применения такой же, как и у предыдущих двух, только текст будет состоять из одинаковых фраз «Съешь ещё этих мягких французских булок, да выпей чаю». Эту фразу знает каждый, кому приходилось иногда работать со шрифтами.

Можно передавать аргументы, как и в первых двух методах.

Вот и все, текстов нагенерили, теперь можно съесть еще этих мягких французских булок да выпить чаю:)

Получилось ли у вас вставить текст с помощью вышеуказанных функций?

В предыдущих статьях цикла "Автоматизация заполнения документов" я рассказал о том, как сформировать пользовательский интерфейс приложения, организовать проверку вводимых данных и получить число прописью без использования кода VBA. В этой, заключительной статье речь пойдет о волшебстве - переносе всех необходимых значений из рабочей книги Excel в документ Word. Давайте я покажу Вам то, что должно получиться в итоге:

Описание механизма

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

Итак, обо всем по порядку.

Создание шаблона документа Word

Тут все предельно просто - создаем обычный документ, набираем и форматируем текст, в общем, добиваемся того, чтобы получить необходимую форму. В тех местах, куда необходимо будет подставить значения из Excel нужно создать закладки. Это делается следующим образом:

Таким образом нужно будет создать все закладки, то есть отметить все места, куда будут вставлены данные из Excel. Получившийся файл нужно сохранить как "Шаблон MS Word" с помощью пункта меню "Файл" -> "Сохранить как...".

Подготовка данных Excel

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

Часть этих значений получена напрямую из листа ввода данных, а часть - из вспомогательных таблиц, расположенных на листе Support . В этой статье я не буду разбирать формулы, рассчитывающие нужные значения, если что-то будет непонятно - задавайте вопросы в комментариях.

На этом этапе важно правильно указать все названия закладок - от этого зависит правильность переноса данных.

Процедура переноса

А вот это - самое интересное. Существует два варианта выполнения кода переноса данных:

  • Код выполняется в рабочей книге Excel, данные передаются в Word по одному значению за раз и сразу же размещаются в документе.
  • Код выполняется в отдельном документе Word, все данные передаются из Excel одним пакетом.

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

Вот, что необходимо сделать:

  • Создать шаблон документа Word с поддержкой макросов. В этом шаблоне будет содержаться выполняемый код на VBA.
  • В созданный шаблон необходимо поместить программу, написанную на VBA. Для этого необходимо при редактировании шаблона нажать комбинацию клавиш Alt+F11 и ввести в открывшемся окне редактора Visual Basic код программы.
  • В рабочей книге Excel написать код, вызывающий процедуру заполнения из только что созданного шаблона Word .

Текст процедуры я приводить в статье не буду - его можно легко посмотреть в файле FillDocument.dotm , расположенном в папке Template в архиве с примером.

Как же воспользоваться всем этим для решения именно Вашей задачи?

Понимаю, что на словах это все выглядит очень просто, но что же получается на деле? Я предлагаю Вам просто воспользоваться уже готовым вариантом. Скачайте архив с примером, в рабочей книге Excel нажмите комбинацию клавиш Alt+F11, чтобы открыть редактор Visual Basic и прочитайте все мои комментарии к программе. Для того, чтобы изменить программу под свои нужды Вам понадобится всего лишь изменить значение нескольких констант, они вынесены в самое начало программы. Весь текст программы Вы можете свободно скопировать в свой проект.

Структура архива

В архиве, приложенном к этой статье, содержится несколько файлов.

Основной файл - рабочая книга Excel с названием "Создание подтверждений". В этой рабочей книге 4 рабочих листа, из которых отображаются только два: "Input" - лист ввода данных и "Database" - архив всех введенных документов.

В папке Templates находятся шаблоны документов Word. Один из них - шаблон, содержащий программу заполнения закладок, а второй - форма для заполнения. Вы можете использовать без изменений шаблон с программой, но форму для заполнения, естественно, придется переделать в соответствии с Вашими нуждами.

Как переработать пример "под себя"?

  1. Подготовить шаблон документа Word, который необходимо заполнить. Создать в нем все необходимые закладки и сохранить как "шаблон MS Word".
  2. Скопировать в папку с подготовленным шаблоном файл FillDocument.dotm из архива, приложенного к этой статье. Этот файл отвечает за заполнение закладок шаблона, и в нем ничего менять не нужно.
  3. Подготовить рабочую книгу Excel для ввода данных. Вам решать, будет ли она обладать каким-либо "продвинутым" пользовательским интерфейсом и осуществлять разные хитрые расчеты. Главное, чтобы в ней содержался рабочий лист с таблицей соответствия имени закладки в шаблоне Word и значения, которое нужно подставить.
  4. Вставить в подготовленную рабочую книгу код программы на VBA из файла-примера. Заменить все константы в соответствии с Вашим проектом.
  5. Протестировать правильность работы.
  6. Активно пользоваться!

Продолжаем, начатую ранее тему работы с формами в Word. В предыдущих статьях мы смотрели на формы только с точки зрения “продвинутого пользователя”, т.е. мы создавали документы, удобные для ручного заполнения. Сегодня же я хочу предложить расширить эту задачу и попробовать использовать механизм Content controls для генерации документов.

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

Закономерный вопрос – а что такое itemProps1.xml и аналогичные компоненты? В этих компонентах хранятся описания источников данных. Скорее всего, по задумке разработчиков помимо встроенных в документ xml-ек, предполагалось использовать и другие, но пока реализован только этот способ.

Чем полезны нам itemPropsX.xml ? Тем, что в них перечислены xml-схемы (их targetNamespace ), которые используются в родительском itemX.xml . Это значит, что если мы подключили в документ не одну custom xml, то чтобы найти нужную, нам нужно пробежаться по itemPropsX.xml компонентам и найти нужную схему, а значит и нужный itemX.xml .

Теперь еще один момент. Мы не будем вручную анализировать связи между компонентами и искать нужные, используя только базовый Packaging API! Вместо этого мы воспользуемся Open XML SDK (его сборки доступны через NuGet). Конечно, ранее мы не словом не говорили про этот API, но для нашей задачи от него требуется минимум и весь код будет достаточно прозрачен.

Ну что ж, основное введение сделано, можно приступать к примеру.

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

А вот так, XML к которому привязывались поля документа

< meetingNotes xmlns ="urn:MeetingNotes" subject ="" date ="" secretary ="" > < participants > < participant name ="" /> < decisions > < decision problem ="" solution ="" responsible ="" controlDate ="" />

Шаг 1. Создание модели данных

Собственно наша задача не просто сгенерировать документ, а создать (хотя бы в черновом варианте) удобный инструмент для использования как разработчиком, так и пользователем.

Поэтому модель мы объявим в виде структуры С#-классов:

Public class MeetingNotes { public MeetingNotes() { Participants = new List(); Decisions = new List(); } public string Subject { get; set; } public DateTime Date { get; set; } public string Secretary { get; set; } public ListParticipants { get; set; } public List Decisions { get; set; } } public class Decision { public string Problem { get; set; } public string Solution { get; set; } public string Responsible { get; set; } public DateTime ControlDate { get; set; } } public class Participant { public string Name { get; set; } }

По большому счету ничего особенного, разве что добавлены атрибуты для управления XML-сериализацией (т.к. имена в модели и требуемой XML немного различаются).

Шаг 2. Сериализация приведенной выше модели в XML

Задача, в принципе, тривиальная. Что называется “берем наш любимый XmlSerializer и вперед”, если бы не одно но

К сожалению, в текущей версии Office, по всей видимости, присутствует баг, который заключается в следующем: если в custom xml перед объявлением основного namespace (того, из которого Word должен брать элементы для отображения), объявить еще какой-нибудь, то повторяющиеся Content controls начинают отображаться не верно (показывается только столько элементов, сколько было в самом шаблоне – т.е. repeating section не работает).

Т.е. вот такой xml работает:

< test xmlns ="urn:Test" attr1 ="1" attr2 ="2" > < repeatedTag attr ="1" /> < repeatedTag attr ="2" /> < repeatedTag attr ="3" />

и вот такой тоже:

< test xmlns ="urn:Test" attr1 ="1" attr2 ="2" xmlns:t ="urn:TTT" > < repeatedTag attr ="1" /> < repeatedTag attr ="2" /> < repeatedTag attr ="3" />

а вот такой, уже нет:

< test xmlns:t ="urn:TTT" xmlns ="urn:Test" attr1 ="1" attr2 ="2" > < repeatedTag attr ="1" /> < repeatedTag attr ="2" /> < repeatedTag attr ="3" />

я пробовал отправить баг в поддержку Microsoft на Connect , но у меня почему-то закрыт доступ для отправки багов по Office. А обсуждение на форуме MSDN тоже не помогло.

В общем, нужный обходной маневр. Если бы мы формировали XML руками, проблем бы не возникло – мы сделали бы все сами. Однако в данном случае очень хочется использовать стандартный XmlSerializer, который по-умолчанию добавляет несколько своих namespace в выходной XML, даже если эти namespace не используются.

Мы сделаем полное подавление вывода собственных namespace в XmlSerializer. Правда, этот подход сработает, только если они ему и правда будут не нужны (в противном случае они все равно будут добавлены и как раз ДО нашего ).

Собственно, весь код (при условии, что переменная meetingNotes содержит ранее заполненный объект типа MeetingNotes):

var serializer = new XmlSerializer(typeof (MeetingNotes));
var serializedDataStream = new MemoryStream();

var namespaces = new XmlSerializerNamespaces();
namespaces.Add(“” , “” );

serializer.Serialize(serializedDataStream, meetingNotes, namespaces);
serializedDataStream.Seek(0, SeekOrigin.Begin);

Шаг 3. Заносим полученную XML в Word-документ.

Тут мы поступаем следующим образом:

  • копируем шаблон и открываем копию
  • находим в ней нужный custom xml (ищем по namespace “urn:MeetingNotes” )
  • замещаем содержимое компонента, на нашу XML

File.Copy(templateName, resultDocumentName, true ); using (var document = WordprocessingDocument.Open(resultDocumentName, true )) { var xmlpart = document.MainDocumentPart.CustomXmlParts .Single(xmlPart => xmlPart.CustomXmlPropertiesPart.DataStoreItem.SchemaReferences.OfType() .Any(sr => sr.Uri.Value == "urn:MeetingNotes"

Както раз после подведения итогов олимпиады, когда участникам требовалось разослать письмами с результаты по сданным (или не сданным) предметам, я заметил, что девушка сидит и руками вносит в шаблон письма результаты экзамена, ФИО школьника и прочую информацию. Перед ней лежало несколько распечатанных из Excel листов с фамилиями и оценками. Copy-Paste, Ctrl+C — Ctrl+V, перевод ФИО из именительного в родительный падеж и так уже была проделана работа с половиной первого из трех листов с данными. Сколько по вашему она могла бы еще просидеть копируя данные, а потом проверяя результат? Думаю довольно долго, да и ошибок было бы не мало. А ведь ей потом предстояло еще подписывать почтовые конверты... Мне стало жалко ее времени и за несколько минут я показал, как можно с помощью простых средств этот процесс автоматизировать. После небольшого экскурса ее работа была закончена за 20 минут.

В этом уроке я покажу Вам как можно быстро создавать документы (письма, приглашения) затрачивая на это минимум времени. В разных версиях языках этот описываемый процесс называется по-разному. Так в русском это «Слияние», а в английском - «Merge».

Надеюсь, что «письма счастья» от пенсионного фонда, налоговые уведомления создаются таким же способом:)

Инструменты

Для создания документов нам понадобится OpenOffice Writer. В нем мы будем создавать шаблон письма. Понадобиться так же OpenOffice Calc. В нем мы создадим базу с фамилиями и адресами тех лиц, которых мы, например, хотим пригласить на вечеринку. Вместо программ из пакета OpenOffice легко могут использоваться MS Word и Excel. База данных может легко лежать в MS Access. И так, приступаем.

Создание базы данных

База данных — это ничто иное как таблица в MS Excel или OpenOffice Calc, где данные располагаются в столбцах, а первая строка используется для именования столбцов. Заведем, например, столбцы «ФИО», «город», «индекс», «адрес». Введем данные и сохраним файл на диск.



В качестве баз данных могут использоваться и другие источники, например адресная книга Outlook, или база данных MS Access.

Создание шаблона письма

С созданием шаблона письма дело обстоит чуть сложнее. Поскольку в шаблон будут данные из таблицы (нашей базы данных) подставляться как есть, то и письмо надо писать соответствующим образом. Если у вас в базе данных ФИО идет в именительном падеже, то вряд ли Вам удастся использовать это поле в обращении «Дорогой, <ФИО>!» и для конверта в строке «Кому: <ФИО>». В последнем случае ФИО будет смотреться несколько коряво.

Составляя шаблон письма я рекомендую начать с составления письма какому-то реальному человеку. Можно самому себе. Затем в нем выделить цветом те данные, которые Вы будете брать из базы данных и заменить их на соответствующие поля. Перед тем как заменять выделенный текст на поле рекомендую обратить внимание на то, с какой буквы должно начинаться поле в базе данных (строчной или прописной). Конечно, можно составлять шаблон сразу с полями, но тогда Вы можете не заметить некоторых ляпов, как нестыковка падежей.



Уже в приведенном шаблоне видно, что нам потребуется ФИО в родительном падеже и поле, содержащие только имя и отчество. С первым полем мы можем заменить «Кому» на «Получатель» и тогда ФИО в именительном падеже нас вполне устроит. Со вторым полем все несколько сложнее и нам придется завести в базе данных еще один столбец и заполнить его соответствующими данными. В одном из следующих уроков я расскажу как это сделать автоматически, а пока будем считать что такое поле у нас уже есть.

Для вставки поля и привязки шаблона к базе данных необходимо выполнить следующую последовательность действий. В OpenOffice Writer выбрать базу данных



и нажать «Define» («Определить»).



Затем в нужное место вставить поле из подключенной базы данных. Для этого нажать Ctrl+F2, или в меню «Вставка» выбрать пункт «Поля» и «Другое». В открывшемся окне выбрать вкладку «Базы данных», в типе поля выбрать «Mail Merge fields», из базы данных выбрать соответствующее поле и нажать «Вставит». Собственно базу данных можно также выбрать в этом окне.



После того как одно поле вставлено, можно не закрывая текущего окна выделить текст для замены на следующего поля, выбрать поле и снова нажать «Вставить». И так для каждого из полей.

Для MS Word ситуация в чем-то похожа и, возможно, более удобна. После создания таблицы в MS Excel, запускаем MS Word и переходим на вкладку «Рассылки». На этой вкладке можно увидеть тре необходимых шага: «Начало слияния», «Составление документа и вставка полей» и «Завершение». Есть еще промежуточный шаг «Просмотр результата», но он является опциональным.

И так работа начинается с выбора документа. Это могут быть письма, наклейки, обычный документ Word. Тут же можно запустить мастер слияния, который проведет Вас через все стадии этого процесса. Следующий шаг — выбор получателя, то есть базы данных. Здесь Вы можете выбрать готовую базу данных (например, созданную на предыдущем этапе таблицу MS Excel), или создать новый список. После того как список выбран, становятся активными кнопки «Вставит поле слияния», «Изменить список получателей» и пр. Через диалог «Изменить список получателей», который открывается соответствующей кнопкой, можно выбрать из всего списка только необходимые для слияния записи.







При вставке полей мне кажется удобным подсветить все поля серым цветом, кликнув по кнопке «Выделить поля слияния». В противном случае, если таких полей много, то их можно потерять в тексте.

И так, шаблон готов.

Генерация писем

Последний этап — генерация писем. В OpenOffice для этого в меню «Инструменты» выбираем «Mail Merge Wizard...» и проходим все предлагаемые шаги по объединению нашего шаблона с базой данных.





В диалоговом окне мы видем, что из предложенных 8 пунктов нам некоторые пункты выполнять не придеться. Так документ мы уже создали и редактировать его нам не надо, блок адреса мы тоже уже вставили. Но давайте по-порядку.

Сначала выбираем, что создаем письма на основе текущего документа и жмем «Далее» внизу окна. Вторым пунктом выбираем будет ли у нас это бумажное письмо или e-mail. Для того, чтобы письмо можно было сохранить в файл следует выбрать первое. Жмем «Далее». Третим пунктом нам предлагают создать блок адреса, но поскольку мы его создали руками, то снимаем все галочки и переходим к следующему шагу. Здесь нам предлагают вставить обращение, но оно у нас тоже уже есть, поэтому жмем «Далее». Шестым пунктом можно отредактировать документ, посмотреть на документ со вставленными из базы данных полями и, если надо, какие-то поля исключить.



На шаге 7 предлагается отредактировать каждый из созданных в результате соединения шаблона с базой данных файлов. И наконец на последнем, 8 шаге, можно выбрать что сделать с полученными документам. Можно сохранить, распечатать или отправить по e-mail. При этом можно сохранять все документы в один файл, или каждый документ отдельно.

В MS Word процесс слияния заканчивается нажатием кнопки «Найти и объединить».



Из выпадающего меню очевидно, что все письма можно напечатать и послать через e-mail, но не очевидно, что все их можно сохранить в файл. Для сохранения надо выбрать первы пункт - «Изменить отдельные документы». При этом откроется новый документ, в котором каждое новое письмо будет располагаться с новой странице, а тут уже этот файл можно и сохранить.

Заключение

И так, в этом уроке Вы узнали как используя инструмент слияния создавать документы на основе шаблона. Давайте кратко запишем последовательность действий:

  1. Необходимо в табличном процессоре создать базу данных, из которой будут браться данные для заполнения полей.
  2. Необходимо создать шаблон письма.
  3. Произвести слияние и сохранить результат.