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