Всем дня. Столкнулся в работе с необходимостью выбора нужных параметров, перед формированием основного шаблона, решил глянуть, что пишет интернет. Важно, после сохранения шаблона отображать окно сохранения или прикрепления к документу.
Варианты решения следующие:
1. Использовать дополнительные параметры, которые в дальнейшем можно вывести в текст шаблона;
В целом удобно, ничего не надо писать, ввел данные, настроил шаблон, все заполнилось.
Почему не подходит в моем случае?
У меня есть параметры, которые нужно получать прям в момент формирования шаблона, выходит надо вклинится перед формированием шаблона и установить доп параметры этого документа. Пример параметров - долг клиента по заказу (сумма отгрузки - сумма оплат). Так же нельзя вывести только 3, 5 и 10 строку табличной части запасы.
2. Использовать заполнение шаблона ворда, который хранится в двоичных данных, с помощью подключения КомОбъекта;
В целом тоже не плохо, но есть ряд минусов. Нужен установленный ворд на сервере (не везде есть, думаю извечная проблема), нужно дописывать прикрепление документа шаблона к документу (типовой метод).
3. Использовать заполнение шаблона ворда, но с помощью разбора файла как архив;
Много кода :)
Есть так же способы, где файл шаблона нужно предварительно обработать, вставив конструкции типа <v8 что-то>.
Для себя нашел решение использовать типовой механизм БСП.
Опишу подробно данное решение в этой статье, возможно вернусь в будущем или помогу кому то. Если не учел моменты или можно сделать проще/оптимизированнее буду рад любым советам.
1. Определяю свою команду печати в модуле менеджера документа, функция ДобавитьКомандыПечати (в моем случае документ "Заказ покупателя", в расширении). Если интересно описание свойств команд печати см. УправлениеПечатью.СоздатьКоллекциюКомандПечати.
//ДОБАВИМ ФОРМУ ПРЕТЕНЗИИ
КомандаПечати = КомандыПечати.Добавить();
КомандаПечати.Идентификатор = "Претензия";
КомандаПечати.Представление = НСтр("ru = 'Претензия'");
//КомандаПечати.СписокФорм = "ФормаДокумента,ФормаСписка,ФормаЗаказНаряда,ФормаСпискаЗаказНаряда";
КомандаПечати.Обработчик = "ПечатьДокументовУНФКлиент.ПечатьПретензии";
КомандаПечати.ПроверкаПроведенияПередПечатью = ИСТИНА;
КомандаПечати.МестоРазмещения = "КомандыПечатиПодменюПриложения";
Место размещения "КомандыПечатиПодменюПриложения" это группа команд, которую создал заранее, находится в корневой группе "ПодменюПечать".
Примечание. Если команда отображается сразу в нескольких формах (ФормаСписка, ФормаДокумента), то данную группу надо создать в двух формах. Иначе команда будет лежать в "корне" группы печати.
2. Создал в общем модуле "ПечатьДокументовУНФКлиент" (использовал типовой модуль, предназначен для подобных команд печати) свою фунцию "ПечатьПретензии".
// Процедура обработки команды "ПечатьПретензии".
//
// Параметры:
// ПараметрКоманды - Массив - печатаемые документы.
// Возвращаемое значение:
// Неопределено - всегда возвращает Неопределено.
Функция ПечатьПретензии(ПараметрКоманды) Экспорт
Если ПараметрКоманды.Количество() > 0 Тогда
СтруктураПараметры = Новый Структура("ОбъектыПечати", ПараметрКоманды.ОбъектыПечати[0]);
ОткрытьФорму("Обработка.ПечатьЗаказаПритензия.Форма.Форма", СтруктураПараметры, , Новый УникальныйИдентификатор);
КонецЕсли;
Возврат Неопределено;
КонецФункции
Функция открывает форму новой обработки, ответственной за запрос параметров и вывод готового документа.
3. Создал новую обработку "ПечатьЗаказаПритензия";
На форму обработки вывел нужные мне параметры (фото в основных).
Теперь по коду обработки.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
ОбъектПечати = Параметры.ОбъектыПечати;
//ЗАПОЛНИМ ДАННЫЕ ЧТО СМОЖЕМ ВЫТАЩИТЬ НА ОСНОВАНИИ ДОКУМЕНТА
ЗаявлениеОт = ОбъектПечати.Контрагент.Наименование;
ДатаПолученияТовара = ОбъектПечати.ДатаОтгрузки;
ТелефонСвязи = УправлениеКонтактнойИнформацией.ПредставлениеКонтактнойИнформацииОбъекта(
ОбъектПечати.Контрагент.КонтактноеЛицо,
Справочники.ВидыКонтактнойИнформации.ТелефонКонтактногоЛица);
АдресПочтовойКорреспонденции = УправлениеКонтактнойИнформацией.ПредставлениеКонтактнойИнформацииОбъекта(
ОбъектПечати.Контрагент,
Справочники.ВидыКонтактнойИнформации.ЮрАдресКонтрагента);
ПредставлениеДокумента = "Заказ клиента № " + ОбъектПечати.Номер + " от " + ОбъектПечати.Дата;
Для каждого СтрокаТабличнойЧасти Из ОбъектПечати.Запасы Цикл
НоваяСтрока = СписокТовара.Добавить();
НоваяСтрока.НазваниеТовараУслуги = СтрокаТабличнойЧасти.Номенклатура;
НоваяСтрока.Количество = СтрокаТабличнойЧасти.Количество;
НоваяСтрока.Стоимость = СтрокаТабличнойЧасти.Сумма;
КонецЦикла;
КонецПроцедуры
При создании документа заполняю те данные, которые мне заранее известны и запоминаю объект печати из параметров формы.
Команда на форме "Сформировать заявление".
&НаКлиенте
Процедура СформироватьЗаявление(Команда)
ДанныеФайла = ЗаполнитьИПрикрепитьСервер();
ОбъектыПечати = Новый Массив;
ОбъектыПечати.Добавить(ОбъектПечати);
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ДанныеФайла", ДанныеФайла);
ПараметрыФормы.Вставить("ОбъектыПечати", ОбъектыПечати);
ОткрытьФорму("Справочник.ШаблоныПечатиОфисныхДокументов.Форма.ФормаПечати", ПараметрыФормы);
КонецПроцедуры
Команда формирует файл используя типовой механизм БСП и открывает форму сохранения или прикрепления к документу. По умолчанию при открытии справочника ШаблоныПечатиОфисныхДокументов нужно передать параметр "ШаблонПечати", на основании которого формируется документ шаблона. Для того, чтобы обработать уже сформированный документ добавляю параметр "ДанныеФайла" и немного изменяю функцию открытия через расширение.
&НаСервере
Процедура ДоработкиПриСозданииНаСервереВместо(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("ДанныеФайла") Тогда
ДанныеФайла = Параметры.ДанныеФайла;
ОбъектПечати = Параметры.ОбъектыПечати[0];
Иначе
Если ТипЗнч(Параметры.ОбъектыПечати) <> Тип("Массив") ИЛИ Параметры.ОбъектыПечати.Количество() = 0 Тогда
Возврат;
КонецЕсли;
ДействиеСФайлом = "СохранитьЛокально";
ОбъектПечати = Параметры.ОбъектыПечати[0];
ДанныеФайла = ШаблоныПечатиОфисныхДокументов.СФормироватьДокумент(ОбъектПечати, Параметры.ШаблонПечати, УникальныйИдентификатор);
СообщенияПользователю = ПолучитьСообщенияПользователю(Истина);
КонецЕсли;
Если ДанныеФайла = Неопределено Тогда
Отказ = Истина;
Возврат;
КонецЕсли;
ИмяФайла = ДанныеФайла.ИмяФайла;
Элементы.ФорматФайлаDOCX.Видимость = (ДанныеФайла.Расширение = "docx");
Элементы.ФорматФайлаODT.Видимость = (ДанныеФайла.Расширение = "odt");
КонецПроцедуры
Вернемся к коду обработки. Функция формирования нужных нам шаблонов и вспомогательные.
Функция ЗаполнитьИПрикрепитьСервер()
Шаблон = Справочники.ШаблоныПечатиОфисныхДокументов.НайтиПоКоду("1");
СвоиПараметры = Новый Массив;
ЗаполнитьСвоиПараметры(СвоиПараметры);
ДанныеФайла = ШаблоныПечатиОфисныхДокументов.СФормироватьДокумент_Доработки(ОбъектПечати,
Шаблон,
УникальныйИдентификатор,
СвоиПараметры);
Возврат ДанныеФайла;
КонецФункции
Функция ЗаполнитьСвоиПараметры(СвоиПараметры)
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "Имя";
НовыйПараметр.Ключ = "Имя";
НовыйПараметр.Значение = ЗаявлениеОт;
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "Адрес";
НовыйПараметр.Ключ = "Адрес";
НовыйПараметр.Значение = АдресПочтовойКорреспонденции;
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ТелефонДляСвязи";
НовыйПараметр.Ключ = "ТелефонДляСвязи";
НовыйПараметр.Значение = ТелефонСвязи;
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "НазваниеДокумента";
НовыйПараметр.Ключ = "НазваниеДокумента";
НовыйПараметр.Значение = ПредставлениеДокумента;
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ДатаПолученияТовара";
НовыйПараметр.Ключ = "ДатаПолученияТовара";
НовыйПараметр.Значение = Формат(ДатаПолученияТовара, "ДЛФ=DD");
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ЗаказПокупателя.Запасы.НомерСтроки";
НовыйПараметр.Ключ = "ЗаказПокупателя.Запасы.НомерСтроки";
НовыйПараметр.ТаблицаВладелец = "ЗаказПокупателя.Запасы";
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ЗаказПокупателя.Запасы.Номенклатура";
НовыйПараметр.Ключ = "ЗаказПокупателя.Запасы.Номенклатура";
НовыйПараметр.ТаблицаВладелец = "ЗаказПокупателя.Запасы";
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ЗаказПокупателя.Запасы.Количество";
НовыйПараметр.Ключ = "ЗаказПокупателя.Запасы.Количество";
НовыйПараметр.ТаблицаВладелец = "ЗаказПокупателя.Запасы";
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ЗаказПокупателя.Запасы.Сумма";
НовыйПараметр.Ключ = "ЗаказПокупателя.Запасы.Сумма";
НовыйПараметр.ТаблицаВладелец = "ЗаказПокупателя.Запасы";
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ЗаказПокупателя.Запасы.Сумма";
НовыйПараметр.Ключ = "ЗаказПокупателя.Запасы.Сумма";
НовыйПараметр.ТаблицаВладелец = "ЗаказПокупателя.Запасы";
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ОписаниеДоставки";
НовыйПараметр.Ключ = "ОписаниеДоставки";
НовыйПараметр.Значение = ?(ДоставкаПроизводилась, " производилась " + Формат(ДоставкаДата, "ДЛФ=DD"),
" самостоятельная");
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ОписаниеМонтажа";
НовыйПараметр.Ключ = "ОписаниеМонтажа";
НовыйПараметр.Значение = ?(МонтажПроизводился, " производился " + Формат(МонтажДата, "ДЛФ=DD"),
" производился самостоятельно");
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ОписаниеНедостатков";
НовыйПараметр.Ключ = "ОписаниеНедостатков";
НовыйПараметр.Значение = ОписаниеНедостатков;
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ТребованияПокупателя";
НовыйПараметр.Ключ = "ТребованияПокупателя";
НовыйПараметр.Значение = ТребованиеПокупателя;
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "ТребованияПокупателя";
НовыйПараметр.Ключ = "ТребованияПокупателя";
НовыйПараметр.Значение = ТребованиеПокупателя;
СвоиПараметры.Добавить(НовыйПараметр);
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "Приложения";
НовыйПараметр.Ключ = "Приложения";
НовыйПараметр.Значение = ПриложенияПримечания;
СвоиПараметры.Добавить(НовыйПараметр);
КонецФункции
Функция НовыйОписаниеПараметраШаблона()
Описание = Новый Структура;
Описание.Вставить("Ключ", "");
Описание.Вставить("Представление", "");
Описание.Вставить("Формат", "");
Описание.Вставить("ДопустимыеФорматы", Новый СписокЗначений);
Описание.Вставить("ОписаниеТипов", Неопределено);
Описание.Вставить("Элементы", Неопределено);
Описание.Вставить("Значение", Неопределено);
Описание.Вставить("ТаблицаВладелец", Неопределено);
Описание.Вставить("Вид", "");
Описание.Вставить("ДополнительныеПараметры", Новый Структура);
Описание.Вставить("ПараметрыКартинки", Неопределено);
Описание.Вставить("СовместимыеПараметры", Новый Массив);
Возврат Описание;
КонецФункции
Особое внимание обращу на функцию заполнения своих параметров.
НовыйПараметр = НовыйОписаниеПараметраШаблона();
НовыйПараметр.Вид = "Текст";
НовыйПараметр.Представление = "Имя";
НовыйПараметр.Ключ = "Имя";
НовыйПараметр.Значение = ЗаявлениеОт;
СвоиПараметры.Добавить(НовыйПараметр);
Ключ и представление должно совпадать с именем шаблона в документе шаблона (Скриншот 2).
Если значение нужно установить вручную, то его необходимо указать в поле "Значение". Если значение можно получить из документа, тогда можно уставить ключ и имя в значение "ЗаказПокупателя.Дата", а в документе шаблона поле "Текст по умолчанию" так же в значение "ЗаказПокупателя.Дата", в таком случае значение подтянется автоматом. Тоже самое работает и для табличных частей (не забудьте указать таблицу владельца см. пример).
Основная функция СФормироватьДокумент_Доработки это немного измененная типовая функция СФормироватьДокумент, располагать необходимо в том же общем модуле ШаблоныПечатиОфисныхДокументов (я сделал в расширении).
Функция СФормироватьДокумент_Доработки(Знач ОбъектПечати, Шаблон, УникальныйИдентификатор, ДопПараметры = Неопределено) Экспорт
ДополнительныеПараметры = ОпределитьВспомогательныеПараметрыПечати(ОбъектПечати, Шаблон);
Если НЕ ЗначениеЗаполнено(ОбъектПечати) Тогда
ОбщегоНазначения.СообщитьПользователю(СтрШаблон(НСтр("ru='Документ по шаблону (%1) не сформирован: не заполнен договор контрагента.'"), Шаблон));
Возврат Неопределено;
КонецЕсли;
ДанныеШаблона = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(Шаблон, "Ссылка,Наименование,ФайлШаблон,Назначение,НеВыделятьПоляДокументаЦветом");
ПараметрыДанныхФайла = РаботаСФайламиКлиентСервер.ПараметрыДанныхФайла();
ПараметрыДанныхФайла.ИдентификаторФормы = УникальныйИдентификатор;
ПараметрыДанныхФайла.ПолучатьСсылкуНаДвоичныеДанные = Истина;
ДанныеФайла = РаботаСФайлами.ДанныеФайла(ДанныеШаблона.ФайлШаблон, ПараметрыДанныхФайла);
СтруктураДокумента = СтруктураДокумента(ДанныеФайла, УникальныйИдентификатор);
СтруктураДокумента.Вставить("Шаблон", Шаблон);
Если СтруктураДокумента.Расширение = "docx" Тогда
ВыбранныеПараметры = ПараметрыИзДокументаDOCX(СтруктураДокумента.ПутьКФайлу);
ИначеЕсли СтруктураДокумента.Расширение = "odt" Тогда
ВыбранныеПараметры = ПараметрыИзДокументаODT(СтруктураДокумента.ПутьКФайлу);
КонецЕсли;
ДополнитьСписокСклоняемыхПараметровИсходными(ВыбранныеПараметры);
//ИЗМЕНЕННЫЙ КУСОЧЕК
Если ДопПараметры = Неопределено Тогда
ОписаниеПараметров = ПолучитьЗначенияНайденныхПараметров(ОбъектПечати, ДанныеШаблона, ВыбранныеПараметры, ДополнительныеПараметры);
Иначе
ОписаниеПараметров = ДопПараметры;
КонецЕсли;
//
Ошибки = Неопределено;
Если СтруктураДокумента.Расширение = "docx" Тогда
ЗаполнитьПараметрыДокументаDOCX(ДополнительныеПараметры, ОписаниеПараметров, СтруктураДокумента, Ошибки);
ЗаписатьФайлСвязейДокументаDOCX(СтруктураДокумента);
ЗаписатьФайлТипыКонтентаДокументаDOCX(СтруктураДокумента);
ИначеЕсли СтруктураДокумента.Расширение = "odt" Тогда
ЗаполнитьПараметрыДокументаODT(ДополнительныеПараметры, ОписаниеПараметров, СтруктураДокумента, Ошибки);
КонецЕсли;
ПереместитьФайл(СтруктураДокумента.ПутьКФайлуЗамены, СтруктураДокумента.ПутьКФайлу);
СтруктураДокумента.ВременныеФайлы.Добавить(СтруктураДокумента.ПутьКФайлуЗамены);
Если ДанныеШаблона.НеВыделятьПоляДокументаЦветом И СтруктураДокумента.Расширение = "docx" Тогда
ОтключитьЗатемнениеПолейДокументаDOCX(СтруктураДокумента);
КонецЕсли;
УдалитьВременныеФайлы(СтруктураДокумента.ВременныеФайлы);
ДвоичныеДанныеФайла = ПолучитьДвоичныеДанныеДокументаИзСтруктурыФайлов(СтруктураДокумента.КаталогСтруктураФайла, СтруктураДокумента.Расширение);
ДанныеФайла = ПолучитьДанныеНовогоФайла(ОбъектПечати, ДанныеШаблона, СтруктураДокумента.Расширение, ДвоичныеДанныеФайла, УникальныйИдентификатор);
ОбщегоНазначенияКлиентСервер.СообщитьОшибкиПользователю(Ошибки);
Возврат ДанныеФайла;
КонецФункции
Как сделать вывод только произвольных строк табличной части?
Для этого необходимо немного доработать функцию "ПриВыводеТаблицыПараметровШаблона" в модуле нужного объекта (в моем случае в документе "ЗаказПокупателя").
Для каждого СтрокаЗапасы Из СтрокиЗапасы Цикл
//ПРОВЕРИМ НУЖНО ИЛИ ВЫВОДИТЬ ЭТИ СТРОКИ
Если ПараметрыПечати.Свойство("ВывестиСтроки") Тогда
СписокСтрок = СтрРазделить(ПараметрыПечати.ВывестиСтроки, ",");
НайденныйИндекс = СписокСтрок.Найти(СтрокаЗапасы.НомерСтроки);
Если НайденныйИндекс = Неопределено Тогда
Продолжить;
КонецЕсли;
КонецЕсли;
//
ЗаполнитьДанныеПечатиПоСтрокеТабличнойЧастиДокумента(СтрокаЗапасы, ОписаниеПараметров, СтруктураИтогов, ИмяТаблицы + ".", ПараметрыВывода);
Если ЭтоВыводВФайл Тогда
ШаблоныПечатиОфисныхДокументов.ВывестиСтрокуТаблицыДокумента(ОписаниеПараметров, ПараметрыВывода);
КонецЕсли;
КонецЦикла;
Так же добавим в функцию СФормироватьДокумент_Доработки новый параметр функции и добавим вставку его в "ДополнительныеПараметры".
Функция СФормироватьДокумент_Доработки(Знач ОбъектПечати, Шаблон, УникальныйИдентификатор, ДопПараметры = Неопределено, НомераСтрок) Экспорт
ДополнительныеПараметры = ОпределитьВспомогательныеПараметрыПечати(ОбъектПечати, Шаблон);
//ДОБАВИМ ПАРАМЕТРЫ
ДополнительныеПараметры.Вставить("ВывестиСтроки", НомераСтрок);
Так же немного изменим функцию "ЗаполнитьИПрикрепитьСервер"
Функция ЗаполнитьИПрикрепитьСервер()
Шаблон = Справочники.ШаблоныПечатиОфисныхДокументов.НайтиПоНаименованию("Претензия");
СвоиПараметры = Новый Массив;
ЗаполнитьСвоиПараметры(СвоиПараметры);
НомераСтрок = "";
Для каждого СтрокаТабличнойЧасти Из СписокТовара Цикл
Если ЗначениеЗаполнено(НомераСтрок) Тогда
НомераСтрок = НомераСтрок + ",";
КонецЕсли;
НомераСтрок = НомераСтрок + СтрокаТабличнойЧасти.НомерСтроки;
КонецЦикла;
ДанныеФайла = ШаблоныПечатиОфисныхДокументов.СФормироватьДокумент_Доработки(ОбъектПечати,
Шаблон,
УникальныйИдентификатор,
СвоиПараметры,
НомераСтрок);
Возврат ДанныеФайла;
КонецФункции
Надеюсь, кому то данный механизм будет полезен :)