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