Публикация - своего рода памятка, содержащая примеры кода для:
1. заполнение шаблона Word данными из 1С;
2. заполнение колонтитулов Word данными из 1С;
3. заполнение таблицы в Word данными из 1С;
Начало работы
В большинстве случаев перед нами ставится следующая задача:
Нужно открыть документ Word, заполненный данными из 1С.
Для этого нам нужно подготовить шаблон документа Word. Не путайте это с Word Template, специальные файлы Word, которые содержат настройки документов для многократного использования. Нам нужен обычный вордовский документ с расширениеми *.docx или *.doc. А далее поместить этот документ в макет с двоичными данными.
Попытка
//Получаем макет из двоичных данных
Шаблон = ПолучитьМакет(ДополнительныеПараметры.ВидДоговора);
ИмяФайла = ПолучитьИмяВременногоФайла(".docx");
Шаблон.Записать(ИмяФайла);
//Создаем COM-объект для работы с Word
ОбъектВорд = Новый COMОбъект("Word.Application");
ОбъектВорд.Documents.add(ИмяФайла);
//В Word можно открывать в одном приложении несколько документов, поэтому ОбъектВорд.Application.Documents - это коллекция открытых документов.
//В нашем случае документ открыт всегда один
ДокументВорд = ОбъектВорд.Application.Documents(1);
ДокументВорд.Activate();
Исключение Сообщить("Ошибка при запуске приложения "+ОписаниеОшибки());
КонецПопытки;
//Разумеется, получение COM-объекта нужно поместить в попытку. Мало ли, что-то пойдет не так.
Читатель может справедливо заметить, что используется модальный вызов, и погрозить автору пальцем. И будет прав.
//Создадим структуру параметров документа
ПараметрыДокумента = ПодготовитьСтрукутруПараметров();
//Заполним структуру параметров документа
ЗаполнитьСтруктуруПараметров(ПараметрыДокумента);
Далее я обычно создаю структуру полей, которые будут заполняться в шаблоне. Такой подход позволяет унифицировать процедуру заполнения шаблона, а также упростить последующее его изменение.
Углубимся немножко в принципы работы Word...
Каждый документ Word разделен на разделы, которые состоят из страниц.
Для каждого раздела есть возможность создавать свою нумерацию элементов, уникальные колонтитулы и настройки параметров страницы. Так, например, чтобы повернуть одну из страниц (вывести на печать как альбомную), нужно создать под неё отдельный раздел.
Каждая страница Word разделена на несколько областей:
- Верхний колонтитул
- Основной текст
- Нижний колонтитул
Нужно заметить, что в каждом разделе может быть уникальный колонтитул для первой страницы.
//Объект, содержит весь основный текст из всех разделов
ДокументВорд.Content
//Объект содержит коллекцию разделов документа
ДокументВорд.Sections
//В каждом разделе есть своя коллекция для верхних колонтитулов
ДокументВорд.Sections(1).Headers
//И своя коллекция для нижних колонтитулов
ДокументВорд.Sections(1).Footers
//При этом, если стоит галочка "Уникальный колонтитул для первой страницы", то коллекции Headers и Footers будут содержать два элемента
Заполнение пользовательских параметров
При обращении к этим коллекциям мы можем выполнять в них поиск и получать встроенные объекты, например, таблицы.
Теперь мы более-менее поняли, как обращаться к областям Word, можем в них пошуровать и выполнить замену наших параметров:
//Переберем все параметры и заменим их в документе
Для каждого Параметр Из ПараметрыДокумента Цикл
ВыполнитьЗамену(ДокументВорд.Content, Параметр.Ключ, Параметр.Значение);
//Ищим вхождения параметра в верхнем колонтитуле
ВыполнитьЗамену(ДокументВорд.Sections(1).Headers.Item(1).Range(), Параметр.Ключ, Параметр.Значение);
//Ищим вхождения параметра в нижнем колонтитуле первой и последующих страниц
ВыполнитьЗамену(ДокументВорд.Sections(1).Footers.Item(1).Range(), Параметр.Ключ, Параметр.Значение);
ВыполнитьЗамену(ДокументВорд.Sections(1).Footers.Item(2).Range(), Параметр.Ключ, Параметр.Значение);
КонецЦикла;
//Выполнить поиск и замену Функция
ВыполнитьЗамену(знач Object, Параметр, Значение)
Object.Find.Execute(Параметр,,,,,,,,,Значение,2)
КонецФункции
Рассмотри подробнее метод Execute. Его параметры идентичны диалоговуму окну при замене/поиске непоседресвенно из MS Word:
А вот и основные параметры (вольный перевод справки MSDN):
- Искомый текст - Строка - Текст для замены. Текст может содержать специальные параметры. Например, ^p - абзац, ^t - табуляция
- Чувствительность к регистру - Булево - Если истина, то поиск будет осуществляться с учетом регистра
- Слова целиком - Булево - Если истина, то ищутся слова целиком. Вхождение слов не учитываются. Например, при поиске слова дом будет пропущено слово домашний
- Использовать подстановочные знаки - Булево - Если истина, то используются встроенные регулярные выражения.
- Искать похожие - Булево - Если истина, то результат поиска будет содержать похожие слова
- Искать все формы - Булево - Если истина, то результат поиска будет содержать различные формы слов.
- Поиск сначала - Булево - Если истина, то будет осуществляться с начала до конца документа
- Охват - WdFindWrap - Опредяляет направление поиска
- Формат - Format - Формат искомого текста
- Строка замены - Строка - Строка, на которую будет заменен исходный текст
- Количество замен - WdReplace - Определяет сколько раз выполнять замену
- и т.д.
WdReplace - Constant Value:
wdReplaceAll 2
wdReplaceNone 0
wdReplaceOne 1
Данный метод не позволяет получить "Строка замены" как выделенную область, но он работает где-то в 10 раз медленнее. Для получения выделенной области можно воспользоваться немножко откорректированной типовой функцией:
//УправлениеПечатьюMSWordКлиент c незначительными изменениями для конфигурации УПП 1.3
Функция ВыполнитьЗамену(знач Object, Параметр, Значение)
СтрокаПоиска = "[" + Параметр + "]";
СтрокаЗамены = Строка(Значение);
//Необходимо выделить областей, в которой мы осуществляем замену
Object.Select();
//Получаем выделенную область
Selection = Object.Application.Selection;
//Найдем все вхождения параметра и заменим его на нужное нам значение
FindObject = Selection.Find;
FindObject.ClearFormatting();
Пока FindObject.Execute(СтрокаПоиска) Цикл
Если ПустаяСтрока(СтрокаЗамены) Тогда
Selection.Delete();
Иначе
Selection.TypeText(СтрокаЗамены);
КонецЕсли;
КонецЦикла;
//Отменим выделение
Selection.Collapse();
КонецФункции
Уже получив выделенную область можно отредактировать стиль текста, шрифт и т.д.
//Редактирование шрифта
Selection.Font
//Редактирование цвета
Selection.HighlightColorIndex
Также есть второй подход, использующий такой объект Word, как поля. Мне он не очень нравится, т.к. в больших документах, порядка 100 страниц, эти поля начинают глючить (исчезать, не подставлять нужные значения) и прочая ерунда. Ну по крайней мере в Word 2007. Но я его все равно приведу:
При подготовке шаблона в тело документа необходимо навставлять полей с типом DOCVARIABLE (можно вставлять горячими клавишими Ctrl+F9).
Доступ к таким полям можно получить следующим нехитрым образом:
ДокументВорд.Variables.Item(НазваниеПараметра).Values
Заполнение таблиц по шаблону
Итак, мы заполнили параметры в основном тексте документа, заменили параметры в колонтитулах, но у нас еще есть одна неприятность - нужно заполнить таблицу.
Подход, описанный ниже, годится только для таблиц с заранее известным форматом. Т.е. мы можем как угодно отформатировать таблицу и её строки изначально. Но потом изменять довольно-таки проблематично.
К таблицам можно получить доступ через области документа.
//Получаем доступ к первой таблице в основном тексте
Таблица = ДокументВорд.Content.Tables(1)
Далее, получив таблицу, мы работаем с ней по привычной схеме - строки, столбцы.
Для задания форматирования легче в шаблоне создать таблицу с пустой первой строкой, которую мы в последующем удалим.
//Данные для заполнения
ПараметрыТЧ = ПараметрыДокумента.ПриложениеТЧ;
//Нужно оставить шапку и первую строку нетронутой Итератор = 2;
Таблица = ДокументВорд.Content.Tables(3);
Для каждого Строка Из ПараметрыТЧ Цикл
//По умолчанию добавляет строку выше первой
Таблица.Rows.Add();
ЗаполнитьСтрокуТаблицы(Таблица, Итератор, Строка,"ПП,НоменклатураНаименование,ЕдИзмерения,ЦенаСтрокой",ПараметрыТЧ );
Итератор = Итератор + 1;
КонецЦикла;
//Структура шаблонов содержит Наименование колонок и их порядок
Процедура ЗаполнитьСтрокуТаблицы(Таблица, НомерСтроки, ЗначениеЗаполнения, СтруктураШаблонов,ТаблицаЗначений)
МассивСтрок = ОбщегоНазначения.РазложитьСтрокуВМассивПодстрок(СтруктураШаблонов,",");
Итератор = 1;
Для каждого Строка Из МассивСтрок Цикл
Если ТаблицаЗначений.Колонки.Найти(Строка) = Неопределено И Строка <> "ПП" Тогда
Итератор = Итератор + 1;
Продолжить;
//Не забываем, что Шапка тоже строка, а при нумерации нам нужно её исключить
ИначеЕсли Строка = "ПП" Тогда
Таблица.Cell(НомерСтроки, Итератор).Range().Text = Строка(НомерСтроки-1);
Итератор = Итератор + 1;
Продолжить;
КонецЕсли;
Таблица.Cell(НомерСтроки, Итератор).Range().Text = Строка(ЗначениеЗаполнения[Строка]);
Итератор = Итератор + 1;
КонецЦикла;
КонецПроцедуры
Вот, в принципе, и все. Основные вопросы, возникающие при работе с Word, я постарался осветить. Надеюсь, данный обзор поможет вам в работе =)
Спасибо за советы и комментарии:
v3rter, monkbest
Критика только приветствуется. Чем больше замечаний, тем лучше будет гайд =)
Готовое решение
Универсальная печать по шаблонам Word в 1С 8.3
Универсальная печать предназначена для формирования печатных форм на основе шаблонов в формате Word из любой конфигурации 1С. С помощью данного инструмента можно самостоятельно заполнить шаблон реквизитами справочника или документа 1С и сформировать печатные формы на основании ссылки на любой объект.