Почему не заполняется поле регистра сведений при его открытии из справочника?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке в среде 1С:Предприятие 8.3 программисты часто сталкиваются с задачей автоматического заполнения реквизитов новой записи регистра при открытии его формы из другого объекта — например, из карточки справочника. Типичный сценарий: пользователь открывает карточку основного средства (автомобиля), нажимает гиперссылку «Поставить на учет», открывается форма записи регистра «Регистрация транспортных средств», но одно или несколько полей (например, «Марка» или «Модель») остаются пустыми, в то время как другие реквизиты успешно заполняются.

В этой статье мы подробно проанализируем причины возникновения этой проблемы, разберем платформенные механизмы автоматического заполнения 1С и рассмотрим несколько надежных способов решения — как через настройку метаданных в конфигураторе, так и программным путем.

Анализ исходной ситуации

Рассмотрим код, который изначально использовался для открытия формы записи регистра сведений из формы элемента справочника:


Если ПоставитьНаУчет Тогда
    ЗначенияЗаполнения = Новый Структура;
    ЗначенияЗаполнения.Вставить("Период", ДатаСведений);
    ЗначенияЗаполнения.Вставить("Организация", Организация);
    ЗначенияЗаполнения.Вставить("ОсновноеСредство", Объект.Ссылка); 
    ЗначенияЗаполнения.Вставить("ВидЗаписи", ПредопределенноеЗначение("Перечисление.ВидЗаписиОРегистрации.Регистрация"));
    ЗначенияЗаполнения.Вставить("Марка", Объект.Ссылка); 
    
    СтруктураПараметров = Новый Структура;
    СтруктураПараметров.Вставить("ЗначенияЗаполнения", ЗначенияЗаполнения);
    
    ПараметрыФормы = Новый Структура("ЗначенияЗаполнения", ЗначенияЗаполнения);
    фНовыйДокумент = ПолучитьФорму("РегистрСведений.РегистрацияТранспортныхСредств.ФормаЗаписи", СтруктураПараметров, ЭтотОбъект);
    фНовыйДокумент.Открыть();
КонецЕсли;

При выполнении этого кода реквизиты Период, Организация и ОсновноеСредство заполняются без проблем, а поле Марка остается незаполненным. Давайте разберем по шагам, почему так происходит.

Причина №1: Несоответствие типов данных

Первое, на что необходимо обратить внимание при анализе заполнения полей — это строгое соответствие типов передаваемых данных типам реквизитов в базе данных. В исходном коде автора для заполнения параметра Марка передается значение Объект.Ссылка:

ЗначенияЗаполнения.Вставить("Марка", Объект.Ссылка);

Здесь кроется логическая ошибка. Реквизит ОсновноеСредство регистра ожидает ссылку на справочник основных средств (тип СправочникСсылка.ОсновныеСредства), и передача туда Объект.Ссылка (который как раз является основным средством) отрабатывает корректно. Однако ресурс или реквизит Марка в регистре сведений наверняка имеет совершенно другой тип данных — например, СправочникСсылка.МаркиАвтомобилей или аналогичный. Передача ссылки основного средства в поле, предназначенное для хранения марки, приведет к тому, что платформа 1С не сможет выполнить неявное приведение типов.

Важное поведение платформы 1С: При несовпадении типов данных в механизме заполнения платформа не выдает критическую ошибку выполнения. Вместо этого она просто игнорирует некорректное значение и оставляет поле пустым (приводит его к пустому значению целевого типа).

Для исправления этого момента необходимо передавать правильный реквизит, содержащий ссылку на марку, например:

ЗначенияЗаполнения.Вставить("Марка", Объект.ЛК_МаркаМодель);

Однако даже после исправления типов данных поле все еще может оставаться пустым. Это связано со вторым, более глубоким платформенным ограничением.

Причина №2: Отсутствие флага «Заполнять из данных заполнения»

Платформа 1С:Предприятие содержит встроенный механизм автоматического заполнения реквизитов создаваемых объектов на основе переданной структуры ЗначенияЗаполнения. Однако этот механизм работает избирательно в зависимости от настроек метаданных конкретного объекта конфигурации:

  1. Для измерений регистра сведений: Если измерение имеет свойство «Ведущее», платформа автоматически считает, что при открытии формы записи из владельца это измерение должно быть заполнено. Для таких измерений признак автоматического заполнения активен по умолчанию.
  2. Для ресурсов и дополнительных реквизитов регистра сведений: По умолчанию платформа считает их второстепенными данными, которые пользователь должен вносить вручную. Для них свойство автоматического заполнения в метаданных выключено.

Если для ресурса Марка в конфигураторе не установлено свойство «Заполнять из данных заполнения», платформа при создании формы записи просто проигнорирует ключ с именем Марка, переданный в структуре ЗначенияЗаполнения, даже если тип данных передан абсолютно верно.

Решение №1: Настройка свойств метаданных в конфигураторе

Самый простой и правильный с точки зрения архитектуры платформы способ решить эту проблему — включить стандартное свойство автозаполнения для нужного ресурса или реквизита регистра сведений. Выполните следующие шаги:

  1. Откройте информационную базу в режиме Конфигуратор.
  2. В дереве метаданных найдите нужный регистр сведений (в нашем примере это РегистрацияТранспортныхСредств).
  3. Раскройте ветку Ресурсы (или Реквизиты, в зависимости от того, где расположено поле Марка) и дважды кликните по реквизиту Марка, чтобы открыть палитру его свойств.
  4. В палитре свойств найдите раздел Использование.
  5. Установите флажок (значение Истина) напротив свойства «Заполнять из данных заполнения».
  6. Сохраните конфигурацию базы данных (клавиша F7).

После включения этой настройки платформа при инициализации формы записи регистра будет автоматически считывать значение из структуры ЗначенияЗаполнения и подставлять его в поле формы.

Решение №2: Программное заполнение в форме записи (без изменения метаданных)

В реальной практике разработчики часто сталкиваются с ситуациями, когда изменять свойства метаданных нежелательно или технически невозможно. Например, если конфигурация находится на поддержке поставщика без возможности редактирования (или включена возможность изменения, но с сохранением поддержки), либо это крупная корпоративная система (ERP, КА, УТ), где любое изменение метаданных усложняет последующие обновления.

В этом случае задачу автозаполнения можно решить программным путем непосредственно в коде формы записи регистра сведений. Мы можем перехватить переданные параметры при создании формы на сервере и вручную присвоить значение реквизиту записи.

Для этого в модуле формы записи регистра сведений необходимо переопределить стандартный обработчик события ПриСозданииНаСервере:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, что форма открывается именно для создания НОВОЙ записи, а не для редактирования существующей.
    // У новой записи период равен пустой дате, а источник копирования не заполнен.
    Если Не ЗначениеЗаполнено(Запись.ИсточникКопирования) И Запись.Period = '00010101' Тогда 
        
        // Извлекаем переданную структуру параметров заполнения из параметров формы
        Если Параметры.Свойство("ЗначенияЗаполнения") 
           И ТипЗнч(Параметры.ЗначенияЗаполнения) = Тип("Структура") Тогда
            
            // Проверяем наличие нашего ключа "Марка" в переданной структуре
            Если Параметры.ЗначенияЗаполнения.Свойство("Марка") Тогда
                
                // Напрямую заполняем реквизит основного реквизита формы "Запись"
                Запись.Марка = Параметры.ЗначенияЗаполнения.Марка;
                
            КонецЕсли;
            
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

Этот программный способ является абсолютно надежным, так как он обходит стандартные ограничения платформы и гарантирует заполнение реквизита вне зависимости от установленных флажков в конфигураторе.

Решение №3: Переход на современные стандарты вызова форм

Попутно проанализируем способ открытия формы записи, предложенный в исходном сообщении темы:


фНовыйДокумент = ПолучитьФорму("РегистрСведений.РегистрацияТранспортныхСредств.ФормаЗаписи", СтруктураПараметров, ЭтотОбъект);
фНовыйДокумент.Открыть();

Согласно актуальным стандартам разработки фирмы «1С» для управляемого приложения, использование метода ПолучитьФорму() в подобных сценариях считается устаревшим и не рекомендуется к использованию. Данный метод выполняет избыточный серверный вызов для создания контекста формы на сервере и передачи его на клиент, что может снижать производительность системы при медленном соединении.

Современным стандартом является использование метода ОткрытьФорму(), который берет на себя всю оптимизацию по созданию и открытию формы на клиенте за один проход. Давайте перепишем исходный код вызова в соответствии с лучшими практиками разработки:


// Подготавливаем структуру значений заполнения с контролем типов данных
ЗначенияЗаполнения = Новый Структура;
ЗначенияЗаполнения.Вставить("Период", ДатаСведений);
ЗначенияЗаполнения.Вставить("Организация", Организация);
ЗначенияЗаполнения.Вставить("ОсновноеСредство", Объект.Ссылка); 
ЗначенияЗаполнения.Вставить("ВидЗаписи", ПредопределенноеЗначение("Перечисление.ВидЗаписиОРегистрации.Регистрация"));

// Важно: Передаем ссылку на конкретную марку автомобиля, а не на само Основное Средство!
ЗначенияЗаполнения.Вставить("Марка", Объект.ЛК_МаркаМодель); 

// Помещаем структуру заполнения в параметры открытия формы
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ЗначенияЗаполнения", ЗначенияЗаполнения);

// Вызываем открытие формы записи регистра сведений по стандартам 1С
ОткрытьФорму("РегистрСведений.РегистрацияТранспортныхСредств.ФормаЗаписи", ПараметрыФормы, ЭтотОбъект);

Использование метода ОткрытьФорму делает код более лаконичным, производительным и полностью соответствующим требованиям стандартов сертификации «1С:Совместимо» и внутренним регламентам разработки крупных компаний.

Резюме и рекомендации

Подводя итог нашему разбору, выделим ключевые правила, которыми нужно руководствоваться при реализации механизмов заполнения реквизитов в 1С:

← На главную