Как автоматически заполнить поле регистра сведений при создании записи из формы справочника?

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

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

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

Выясняем причину: почему не работает стандартная галка «Заполнять из данных заполнения»?

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

  1. Флаг автоматического заполнения должен быть включен в свойствах конкретного измерения регистра в конфигураторе.
  2. В динамическом списке на форме справочника должен быть установлен активный отбор по этому измерению с видом сравнения «Равно».
  3. Данный отбор должен быть наложен именно через стандартный компоновщик настроек динамического списка (свойство Отбор), а не прописан вручную в тексте произвольного запроса через параметры (например, ГДЕ ОсновноеСредство = &ОсновноеСредство). Если отбор задан через параметр запроса, платформа «не понимает», какому полю новой записи соответствует этот параметр, и автозаполнение не срабатывает.

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

Способ 1. Программная настройка стандартного отбора в динамическом списке

Рассмотрим наиболее простой и предпочтительный вариант, не требующий написания программного кода в форме самого регистра. Если ваш динамический список имеет в качестве основной таблицы нужный регистр сведений, нам достаточно правильно установить отбор на стороне формы справочника.

Разберем по шагам, как настроить такой отбор программно в модуле формы элемента справочника. В процедуре ПриСозданииНаСервере мы обратимся к компоновщику настроек нашего динамического списка:


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

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

Способ 2. Программный перехват события создания записи и ручная передача параметров

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

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


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

Данный подход позволяет гибко управлять передаваемыми данными и выполнять любые предварительные проверки перед открытием формы.

Способ 3. Безопасная обработка параметров на стороне формы записи регистра

Если мы передаем параметры заполнения вручную (как во втором способе), нам необходимо безопасно принять их в форме записи самого регистра сведений. Чтобы избежать критических ошибок при открытии формы напрямую, напишем правильный код в обработчике ПриСозданииНаСервере формы записи регистра:


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

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

Способ 4. Использование обработчика «ОбработкаЗаполнения» в модуле менеджера записи

Для создания чистого, соответствующего стандартам разработки «1С:Совместимо» решения, рекомендуется выносить логику инициализации данных в модули объектов или менеджеров. У независимых регистров сведений для этого существует предопределенный обработчик ОбработкаЗаполнения, расположенный в модуле менеджера записи.

Перенесем логику обработки входных параметров туда:


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

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

Способ 5. Альтернативное решение: использование набора записей вместо динамического списка

Рассмотрим важную проблему: что делать, если пользователь создает новый элемент справочника и хочет сразу добавить записи в регистр, еще не записав сам справочник в базу данных? В динамическом списке это невозможно, так как у нового элемента справочника еще нет ссылки (значение Объект.Ссылка пустое). При проектировании сложных интерфейсов со связанными данными без использования динамических списков может пригодиться прием сопоставления и связывания двух табличных частей на управляемой форме.

В этом случае отличной альтернативой будет отказ от динамического списка на форме в пользу использования реквизита формы с типом РегистрСведенийНаборЗаписей. Разберем этот сценарий по шагам:

  1. Добавим на форму элемента справочника реквизит формы с типом РегистрСведенийНаборЗаписей.ИмяВашегоРегистра и выведем его в виде таблицы.
  2. При открытии формы существующего элемента справочника будем программно считывать данные регистра в этот набор по отбору.
  3. Пользователь сможет свободно добавлять и редактировать строки в таблице на форме, даже если элемент справочника еще не записан в базу.
  4. В модуле формы справочника в обработчике события ПослеЗаписиНаСервере мы программно запишем наш набор в базу данных, заполнив измерение полученной ссылкой на справочник.

Посмотрим на пример реализации сохранения набора записей на сервере:


&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
    
    // Создаем и инициализируем набор записей для сохранения изменений
    НаборЗаписей = РегистрыСведений.ИмяВашегоРегистра.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.ОсновноеСредство.Установить(Объект.Ссылка);
    
    // Заполняем набор данными из нашей экранной таблицы
    Для Каждого СтрокаТЧ Из Объект.ТаблицаРегистра Цикл
        НоваяЗапись = НаборЗаписей.Добавить();
        ЗаполнительЗначенийСвойств(НоваяЗапись, СтрокаТЧ);
        НоваяЗапись.ОсновноеСредство = Объект.Ссылка; // Здесь ссылка уже гарантированно существует
    КонецЦикла;
    
    // Записываем данные в информационную базу
    НаборЗаписей.Записать();
    
КонецПроцедуры

Данный подход обеспечивает атомарность операции: если пользователь решит закрыть форму нового справочника без сохранения, лишние записи не останутся в базе данных «мусором».

Таким образом, мы детально изучили все возможные варианты настройки и программирования автозаполнения полей регистра сведений. Выбор конкретного метода зависит от архитектурных требований вашей задачи и необходимости работы с еще не записанными объектами справочника.

← На главную