Разработка внешних печатных форм (ВПФ) на базе шаблонов Microsoft Word — частая задача в среде «1С:Предприятие 8.3». Однако начинающие разработчики часто сталкиваются с аппаратными и архитектурными ограничениями платформы при попытке перенести старый код или логику из обычных форм в управляемое приложение (Тонкий клиент). В этой статье мы подробно разберем, почему возникают подобные ошибки, и рассмотрим пошаговые сценарии их исправления.
В управляемом приложении (Тонком клиенте) действует строгое разделение контекста исполнения кода на Клиент и Сервер. Рассмотрим две классические ошибки, упомянутые в теме:
ВыбранныйДок.Номер.
В Тонком клиенте переменная ВыбранныйДок представляет собой лишь ссылку на объект базы данных (тип ДокументСсылка.ЗаказКлиента). Тонкий клиент физически не имеет прямого доступа к базе данных и не может «разыменовать» ссылку через точку. Любая попытка получить значение реквизита напрямую по ссылке на клиенте вызовет ошибку выполнения.
Глобальный контекст Документы (а также Справочники, РегистрыСведений и т. д.) доступен исключительно на сервере. Попытка вызвать метод вроде Документы.ЗаказКлиента.РассчитатьСостояние(...) в клиентском коде формы всегда будет приводить к ошибке компиляции на клиенте.
Для решения этих проблем нам необходимо применить правильные архитектурные подходы и перенести получение данных на сторону сервера.
Проанализируем первый способ решения проблемы. Мы можем создать серверную функцию без контекста, которая будет принимать ссылку на документ, выполнять запрос к базе данных и возвращать требуемый номер на клиент.
Обратите внимание на распространенную ошибку: в запросе нельзя обращаться к имени макета или имени файла (например, к Документ.ДоговорКуплиПродажи100ЗаказКлиента). Запрос должен адресоваться к реальной таблице базы данных — в данном случае к Документ.ЗаказКлиента.
Разберем пример реализации этого механизма в модуле управляемой формы внешней обработки:
&НаКлиенте
Процедура Печать(ИдентификаторКоманды, ОбъектыНазначения) Экспорт
ВыбранныйДок = Объект.Ссылка; // Получаем ссылку на текущий документ
// Вызываем серверную функцию для получения номера
НомерДокумента = ПолучитьНомерДокумента(ВыбранныйДок);
Если НомерДокумента <> Неопределено Тогда
ПоказатьПредупреждение(, "Номер документа: " + НомерДокумента);
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьНомерДокумента(СсылкаНаДокумент)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ЗаказКлиента.Номер КАК Номер
|ИЗ
| Документ.ЗаказКлиента КАК ЗаказКлиента
|ГДЕ
| ЗаказКлиента.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", СсылкаНаДокумент);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
Возврат Выборка.Номер;
Иначе
Возврат Неопределено;
КонецЕсли;
КонецФункции
Если ваша конфигурация (например, «Управление торговлей», «ERP» или «Комплексная автоматизация») построена на базе БСП, то писать ручные запросы для получения простых реквизитов нет необходимости. В составе БСП есть готовые оптимизированные функции общего назначения.
Для получения одного или нескольких реквизитов на сервере мы можем использовать функцию ОбщегоНазначения.ЗначениеРеквизитаОбъекта(). Этот метод автоматически выполнит быстрый запрос на сервере.
Посмотрим на пример того, как упрощается серверная часть кода:
&НаСервереБезКонтекста
Функция ПолучитьНомерДокументаБыстро(СсылкаНаДокумент)
// Быстрое получение одного реквизита без написания ручного запроса
Возврат ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаНаДокумент, "Номер");
КонецФункции
Если вам требуется получить сразу несколько реквизитов (например, Номер, Дату и Организацию), используйте метод ОбщегоНазначения.ЗначенияРеквизитовОбъекта(), который возвращает структуру:
&НаСервереБезКонтекста
Функция ПолучитьДанныеДокумента(СсылкаНаДокумент)
// Получаем структуру реквизитов за один серверный вызов
Данные = ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СсылкаНаДокумент, "Номер, Дата, Организация");
Возврат Данные; // Доступ на клиенте: Данные.Номер, Данные.Дата
КонецФункции
Создание отдельной интерактивной формы для выбора документа внутри внешней обработки часто является избыточным решением. Правильный стандарт разработки печатных форм по требованиям БСП подразумевает, что форма регистрируется в справочнике «Дополнительные отчеты и обработки» и вызывается напрямую из стандартного меню «Печать» в документе Заказ клиента.
Рассмотрим структуру правильной внешней печатной формы без использования собственных окон диалога:
СведенияОВнешнейОбработке(), которая сообщает системе, к какому документу прикрепляется печатная форма.Пример структуры модуля объекта для внешней печатной формы:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиПечатнаяФорма();
ПараметрыРегистрации.Назначение.Добавить("Документ.ЗаказКлиента");
ПараметрыРегистрации.Наименование = "Договор купли-продажи (100% предоплата)";
ПараметрыРегистрации.БезопасныйРежим = Ложь;
ПараметрыРегистрации.Версия = "1.0";
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить();
НоваяКоманда.Представление = "Договор купли-продажи (Word)";
НоваяКоманда.Идентификатор = "ДоговорКуплиПродажи100ЗаказКлиента";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипЗапускаВызовСерверногоМетода();
НоваяКоманда.Модификатор = "ПечатьMXL";
Возврат ПараметрыРегистрации;
КонецФункции
Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
// Платформа сама передает список выделенных документов в МассивОбъектов на Сервер.
// Здесь мы пишем логику заполнения макета Договора Word для каждого документа из массива.
Для Каждого СсылкаНаДокумент Из МассивОбъектов Цикл
// Код получения данных через БСП и вывода в Word...
КонецЦикла;
КонецПроцедуры
Исторически для заполнения шаблонов использовался механизм COM-соединения (COMОбъект("Word.Application")). У этого подхода есть критические недостатки: он требует установленного MS Office на компьютере пользователя, работает только под Windows и не поддерживается в Веб-клиенте.
Мы рекомендуем использовать возможности БСП для работы с макетами офисных документов в формате .docx (на основе двоичных данных) напрямую на сервере. При таком подходе формирование договора происходит программным разбором xml-структуры файла, что гарантирует:
Для программной инициализации и заполнения полей такого макета на сервере используйте вызовы функций общего модуля УправлениеПечатью платформы.