При разработке внешних обработок в среде 1С:Предприятие 8.3 на управляемых формах программисты часто сталкиваются с необходимостью вывести печатную форму так, чтобы пользователь мог внести в неё изменения перед отправкой на принтер. Казалось бы, задача тривиальная, но она таит в себе несколько подводных камней, связанных с передачей данных между клиентом и сервером. В этой статье мы подробно разберем, почему возникает популярная ошибка «Ошибка отображения типов» и как правильно организовать формирование табличного документа.
Проанализируем ситуацию, с которой столкнулся автор темы. При попытке вызвать серверную процедуру и передать в неё ЭтотОбъект, система выдает ошибку: «ошибка отображения типов отсутствует отображение для типа "форма клиентского приложения"». Выясним причину этого поведения. В управляемом приложении 1С существует строгое разделение контекстов. На стороне клиента ЭтотОбъект — это объект типа УправляемаяФорма. Когда вы пытаетесь передать форму в качестве параметра в серверный метод, система пытается её сериализовать (преобразовать в поток данных), но объект «Форма» не предназначен для передачи между границами «Клиент-Сервер» таким способом.
Рассмотрим правильный подход к архитектуре вызова:
Главная особенность внешней обработки заключается в том, что её макеты не доступны напрямую через менеджеры объектов (как это бывает с документами или справочниками конфигурации). Чтобы получить доступ к макету, нам нужно преобразовать данные формы обратно в прикладной объект обработки. Для этого используется системная функция РеквизитФормыВЗначение.
Проанализируем пример кода для серверной функции:
&НаСервере
Функция СформироватьТабличныйДокументНаСервере()
// Преобразуем реквизит формы "Объект" в прикладной объект обработки
ОбъектОбработки = РеквизитФормыВЗначение("Объект");
// Теперь мы можем получить макет, созданный внутри обработки
Макет = ОбъектОбработки.ПолучитьМакет("ПримерПечатнойФормы");
// Создаем новый табличный документ
ТабДок = Новый ТабличныйДокумент;
// Получаем нужную область макета (например, Шапку)
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
// Здесь можно заполнить параметры области, если они есть
// ОбластьШапка.Параметры.ДатаПечати = ТекущаяДата();
// Выводим область в итоговый документ
ТабДок.Вывести(ОбластьШапка);
// Важный момент для редактирования:
ТабДок.ТолькоПросмотр = Ложь;
Возврат ТабДок;
КонецФункции
Теперь, когда сервер подготовил данные, нам нужно показать их пользователю. На клиенте мы вызываем нашу функцию и используем метод Показать(). Обратите внимание, что мы не передаем никакие параметры типа ЭтотОбъект в функцию, так как серверный контекст формы и так имеет доступ к своим реквизитам.
&НаКлиенте
Процедура КомандаПечать(Команда)
// Получаем сформированный документ с сервера
ТабличныйДокумент = СформироватьТабличныйДокументНаСервере();
// Отображаем его в отдельном окне
ТабличныйДокумент.Показать("Заголовок окна редактирования");
КонецПроцедуры
Чтобы пользователь действительно мог редактировать поля, недостаточно просто вызвать метод Показать(). Разберем дополнительные настройки ТабличногоДокумента, которые сделают работу удобной:
ТолькоПросмотр: Как мы уже отметили в коде выше, установите его в значение Ложь. Если это свойство будет Истина, пользователь не сможет даже поставить курсор в ячейку.Защита. В макете в свойствах ячеек на закладке «Защита» снимите флажок «Защита» для пустых полей. Затем в коде установите ТабДок.Защита = Истина;. В этом случае редактируемыми останутся только те ячейки, где защита была снята вручную.ТолькоПросмотр установлено корректно, иначе события расшифровки могут перехватывать фокус.Иногда открытие нового окна через Показать() неудобно. Рассмотрим более профессиональный подход — размещение поля табличного документа непосредственно на управляемой форме вашей обработки.
Для этого выполним следующие действия:
РезультатПечати.В этом случае код формирования упрощается, так как нам не нужно возвращать объект с сервера на клиент — реквизит формы обновится автоматически. Посмотрим, как это выглядит:
&НаСервере
Процедура СформироватьНаФормеСервер()
ОбъектОбработки = РеквизитФормыВЗначение("Объект");
Макет = ОбъектОбработки.ПолучитьМакет("ПримерПечатнойФормы");
// Обращаемся напрямую к реквизиту формы
РезультатПечати.Очистить();
Область = Макет.ПолучитьОбласть("Шапка");
РезультатПечати.Вывести(Область);
// Разрешаем редактирование прямо на форме
РезультатПечати.ТолькоПросмотр = Ложь;
КонецПроцедуры
&НаКлиенте
Процедура КомандаСформировать(Команда)
СформироватьНаФормеСервер();
КонецПроцедуры
Подведем итоги нашего анализа. Чтобы избежать ошибок при выводе макетов во внешних обработках, придерживайтесь следующих правил:
ЭтотОбъект на клиенте) в параметры серверных процедур.РеквизитФормыВЗначение("Объект") на сервере для доступа к метаданным внешней обработки (макетам).ТолькоПросмотр и Защита у итогового ТабличногоДокумента.Применяя эти методы, вы создадите надежный и удобный инструмент для пользователей, который позволит им гибко управлять печатными данными, сохраняя при этом стабильность работы системы.