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