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