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

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

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

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

Способ 1. Декларативный метод платформы (без программирования)

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

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

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

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

Способ 2. Программный перехват события «ПередНачаломДобавления»

Рассмотрим ситуацию, когда стандартный механизм не справляется. Например, в вашем динамическом списке используется сложный произвольный запрос, отбор по иерархии, вид сравнения В списке, либо вам необходимо при создании новой записи заполнить не только контрагента, но и передать другие значения по умолчанию (например, текущего пользователя в поле Ответственный, текущую дату или статус по умолчанию), которых вообще нет в отборах списка.

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

Разберем алгоритм реализации:

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

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


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

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

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

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

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


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

Способ 4. Перенос бизнес-логики в модуль менеджера регистра (Best Practice)

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

Для этого используется предопределенный обработчик события ОбработкаЗаполнения. Он вызывается системой всегда, когда инициализируется создание новой записи с параметрами заполнения (как интерактивно через форму, так и программно через вызов метода Заполнить() у менеджера записи).

Рассмотрим пример кода в модуле менеджера регистра сведений РегистрВладельцев:


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

КонецПроцедуры

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

Резюме

Мы подробно проанализировали различные варианты решения задачи автозаполнения. Выбор конкретного подхода зависит от требований к гибкости вашей системы:

← На главную