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