Небольшая история (ну как без нее), с чего все началось. В году так 2010 делал подсистему учета договоров и заявок на технологическое присоединение на УПП. Печатные формы выводил в Word через com соединение. Когда с этим всем стало работать людей под 50+ начались постоянные проблемы с производительностью. Макеты формировались от 30 секунд и до 15 минут (!). Надо было что-то менять. В БСП к тому времени появилась возможность заполнять макеты по-новому. Но примеры были реализованы внешними подключаемыми обработками. А макетов нужно было сделать больше 40! Нужна была простая схема. Дал задание сотруднику разобраться и доложить, как сделать проще. Сотрудник разбирался месяц и доложил то, что я и так знал: "Вот тебе внешняя обработка и ей пользуйся, так все делают!". Молодец, думаю, далеко пойдет. Ладно. Разобрался сам. Убрал все лишнее, добавил нужное. Получилось на мой взгляд хорошо. Перевел формы на новые рельсы и макеты стали формироваться за максимум 10 секунд стабильно.
Статья размещена в учебных целях. Цель обидеть кого-то автором не ставилась.
Пример, представленный в статье содержит весь необходимый код. Можно скачать обработку с этим работающим примером.
Будем считать, что word-макет у вас уже есть.
Шаг 1. Делаем кнопку с командой СформироватьПечатнуюФорму. Выводим на форму кнопку. В модуле формы описываем:
// ***
&НаСервере
Функция ПечатьСервер()
ИмяМакета = "ПФ_ПечатнаяФормаWord";
_Объект = РеквизитФормыВЗначение("Объект");
ДанныеЗаполнения = _Объект.ПолучитьДанныеДляЗаполнения(); // Получайте данные из любого нужного объекта
ДвоичныеДанныеМакета = _Объект.ПолучитьМакет(ИмяМакета);
АдресХранилищаОфисныйДокумент = "";
// Метод лучше разместить в общем модуле. В данном примере он размещен в модуле объекта обработки:
_Объект.ВывестиДанныеДокументаВТабличныйДокумент(ДанныеЗаполнения, ДвоичныеДанныеМакета, АдресХранилищаОфисныйДокумент);
Возврат АдресХранилищаОфисныйДокумент;
КонецФункции
// ***
&НаКлиенте
Процедура СформироватьПечатнуюФорму(Команда)
АдресХранилищаОфисныйДокумент = ПечатьСервер();
ИмяФайла = ПолучитьИмяВременногоФайла(".docx");
ПолучитьФайл(АдресХранилищаОфисныйДокумент, ИмяФайла, Ложь);
УдалитьИзВременногоХранилища(АдресХранилищаОфисныйДокумент);
ЗапуститьПриложение(ИмяФайла);
КонецПроцедуры
Шаг 2. Функция ПолучитьДанныеДляЗаполнения() возвращает структуру с заполненными переменными для вывода в макет. Т.е. ключ это название тэга в макете, значение - это то, что будем выводить в макет. Учитывайте то, что значение должно быть в строковом типе.
В нашем примере функция расположена в модуле объекта обработки. В рабочих вариантах располагайте в модулях менеджеров своих объектов.
Функция ПолучитьДанныеДляЗаполнения(МассивОбъектов = Неопределено) Экспорт
// здесь происходит заполнение данными для ПФ
Данные = Новый Структура;
Данные.Вставить("НаименованиеДокумента", "План-график некоторой организации по некоторому списку работ");
Данные.Вставить("СтрокаРазослать", "Всем по @");
//Данные.Вставить("Реквизит2", _ЗначениеРеквизита2);
//Данные.Вставить("Реквизит3", _ЗначениеРеквизита3);
// Заполнение первой таблицы в макете
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("Пункт");
ТаблицаДанных.Колонки.Добавить("Наименование");
ТаблицаДанных.Колонки.Добавить("ДатаКон");
ТаблицаДанных.Колонки.Добавить("Исполнители");
ТаблицаДанных.Колонки.Добавить("Примечание");
Для а = 1 По 10 Цикл
Строка = ТаблицаДанных.Добавить();
Строка.Пункт = Строка(а);
Строка.Наименование = "Работа № 00" + а;
Строка.ДатаКон = Формат(ТекущаяДата(), "ДЛФ=D");
Строка.Исполнители = "Исполнитель" + а;
Строка.Примечание = "";
КонецЦикла;
// Заполнение второй таблицы в макете
ТаблицаДанных1 = Новый ТаблицаЗначений;
ТаблицаДанных1.Колонки.Добавить("Пункт");
ТаблицаДанных1.Колонки.Добавить("Согласователь");
ТаблицаДанных1.Колонки.Добавить("Дата");
ТаблицаДанных1.Колонки.Добавить("Подпись");
ТаблицаДанных1.Колонки.Добавить("Примечание");
Для а = 1 По 3 Цикл
Строка = ТаблицаДанных1.Добавить();
Строка.Пункт = Строка(а);
Строка.Согласователь = "Согласователь" + а;
Строка.Дата = Формат(ТекущаяДата(), "ДЛФ=D");
Строка.Подпись = "";
Строка.Примечание = "";
КонецЦикла;
Данные.Вставить("ТаблицаДанных", ОбщегоНазначения.ТаблицаЗначенийВМассив(ТаблицаДанных));
Данные.Вставить("ТаблицаДанных1", ОбщегоНазначения.ТаблицаЗначенийВМассив(ТаблицаДанных1));
Возврат Данные;
КонецФункции
Шаг 3. Процедуру ВывестиДанныеДокументаВТабличныйДокумент() лучше разместить в общем модуле. В нашем примере процедура размещена в модуле объекта обработки.
Стоит отметить, что этот вариант описания процедуры позволяет выводить две табличные части.
Процедура ВывестиДанныеДокументаВТабличныйДокумент(МассивДанныхЗаполнения, ДвоичныеДанныеМакета, АдресХранилищаОфисныйДокумент) Экспорт
//ДвоичныеДанныеМакета = ПолучитьМакет(ИмяМакета);
Если ДвоичныеДанныеМакета <> Неопределено Тогда
// Инициализируем печатную форму
ПечатнаяФорма = Новый Структура;
ПечатнаяФорма.Вставить("ТабличныйДокумент");
//ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "НазваниеКоманды");
// Наличие пустого табличного документа в коллекции обязательно
ПечатнаяФорма.ТабличныйДокумент = Новый ТабличныйДокумент;
Макет = УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента(ДвоичныеДанныеМакета,Неопределено);
ПечатнаяФормаДокумента = УправлениеПечатью.ИнициализироватьПечатнуюФорму(Неопределено, Макет.НастройкиСтраницыМакета, Макет);
// Определим какие области в документе Word хотим заполнить
// Для этого у нас документ должен быть размечен конструкциями
// {v8 Область.НазваниеОбласти}
// {/v8 Область.НазваниеОбласти}
// наличие областей обязательно
// Область для заполнения обычных параметров в тексте
ОбластьЗаголовок = Новый Структура;
ОбластьЗаголовок.Вставить("ИмяОбласти", "Заголовок");
ОбластьЗаголовок.Вставить("ТипОбласти", "Общая");
ОбластьПодвал = Новый Структура;
ОбластьПодвал.Вставить("ИмяОбласти", "Подвал");
ОбластьПодвал.Вставить("ТипОбласти", "Общая");
ОбластьРазрыв = Новый Структура;
ОбластьРазрыв.Вставить("ИмяОбласти", "РазделительРаздела");
ОбластьРазрыв.Вставить("ТипОбласти", "Общая");
// Пример определения областей коллекций (таблица и нумерованный или обычный списки)
ОбластьШапкаТаблицы = Новый Структура;
ОбластьШапкаТаблицы.Вставить("ИмяОбласти", "ШапкаТаблицы");
ОбластьШапкаТаблицы.Вставить("ТипОбласти", "Общая");
ОбластьСтрокаТаблицы = Новый Структура;
ОбластьСтрокаТаблицы.Вставить("ИмяОбласти", "СтрокаТаблицы");
ОбластьСтрокаТаблицы.Вставить("ТипОбласти", "СтрокаТаблицы");
// вторая таблица
ОбластьШапкаТаблицы1 = Новый Структура;
ОбластьШапкаТаблицы1.Вставить("ИмяОбласти", "ШапкаТаблицы1");
ОбластьШапкаТаблицы1.Вставить("ТипОбласти", "Общая");
ОбластьСтрокаТаблицы1 = Новый Структура;
ОбластьСтрокаТаблицы1.Вставить("ИмяОбласти", "СтрокаТаблицы1");
ОбластьСтрокаТаблицы1.Вставить("ТипОбласти", "СтрокаТаблицы");
// Область должна быть определена первым элементом списка
// {v8 Область.НумерованныйСписок}
// 1.{v8 Номенклатура}
// {/v8 Область.НумерованныйСписок}
ОбластьНумерованныйСписка = Новый Структура;
ОбластьНумерованныйСписка.Вставить("ИмяОбласти", "НумерованныйСписок");
ОбластьНумерованныйСписка.Вставить("ТипОбласти", "Список");
// Область должна быть определена первым элементом списка
// {v8 Область.МаркированныйСписок}
// • {v8 Номенклатура}
// {/v8 Область.МаркированныйСписок}
ОбластьМаркированногоСписка = Новый Структура;
ОбластьМаркированногоСписка.Вставить("ИмяОбласти", "МаркированныйСписок");
ОбластьМаркированногоСписка.Вставить("ТипОбласти", "Список");
// Пример определения областей колонтитулов, эти области в документе есть по умолчанию,
// если колонтитулы определены в самом документе
ОбластьВерхнийКолонтитул = Новый Структура;
ОбластьВерхнийКолонтитул.Вставить("ИмяОбласти", "ВерхнийКолонтитул");
ОбластьВерхнийКолонтитул.Вставить("ТипОбласти", "ВерхнийКолонтитул");
ОбластьНижнийКолонтитул = Новый Структура;
ОбластьНижнийКолонтитул.Вставить("ИмяОбласти", "НижнийКолонтитул");
ОбластьНижнийКолонтитул.Вставить("ТипОбласти", "НижнийКолонтитул");
// Передаем данные заполнения для заполнения печатной формы
// Имена параметров данных заполнения должны совпадать с размеченными параметрами в документе в виде
// {v8 НазваниеПараметра}
Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьЗаголовок);
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения, Ложь);
Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьРазрыв);
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения, Ложь);
Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьВерхнийКолонтитул);
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения);
Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьНижнийКолонтитул);
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения);
//Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьШапкаТаблицы);
//УправлениеПечатью.ПрисоединитьОбласть(ПечатнаяФормаДокумента, Область, Ложь);
Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьШапкаТаблицы);
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения);
Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьСтрокаТаблицы);
УправлениеПечатью.ПрисоединитьИЗаполнитьКоллекцию(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения.ТаблицаДанных);
Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьНумерованныйСписка);
УправлениеПечатью.ПрисоединитьИЗаполнитьКоллекцию(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения.ТаблицаДанных);
Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьМаркированногоСписка);
УправлениеПечатью.ПрисоединитьИЗаполнитьКоллекцию(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения.ТаблицаДанных);
// вторая таблица
Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьШапкаТаблицы1);
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения);
Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьСтрокаТаблицы1);
УправлениеПечатью.ПрисоединитьИЗаполнитьКоллекцию(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения.ТаблицаДанных1);
Область = УправлениеПечатью.ОбластьМакета(Макет, ОбластьПодвал);
УправлениеПечатью.ПрисоединитьОбластьИЗаполнитьПараметры(ПечатнаяФормаДокумента, Область, МассивДанныхЗаполнения, Ложь);
// Поместим получившийся документ в коллекцию печатных форм, в раздел ОфисныеДокументы
// так БСП поймет что нужно открывать Word при формировании печатной формы
АдресХранилищаОфисныйДокумент = УправлениеПечатью.СформироватьДокумент(ПечатнаяФормаДокумента);
УправлениеПечатью.ОчиститьСсылки(ПечатнаяФормаДокумента, Ложь);
УправлениеПечатью.ОчиститьСсылки(Макет);
ОфисныеДокументы = Новый Соответствие;
ОфисныеДокументы.Вставить(АдресХранилищаОфисныйДокумент, НСтр("ru = 'Название документа'"));
КонецЕсли;
КонецПроцедуры
Все. Больше ничего делать не нужно.
Пример создавался на БСП 3.1.9.302.
Ставьте плюсики, если вам помогло.
Проверено на следующих конфигурациях и релизах:
- 1С:Библиотека стандартных подсистем, редакция 3.1, релизы 3.1.9.302
Вступайте в нашу телеграмм-группу Инфостарт