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

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

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

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

Почему не работает автозаполнение при использовании параметров запроса?

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


ВЫБРАТЬ
    Регистр.ЛабораторныйПоказатель КАК ЛабораторныйПоказатель,
    Регистр.ВидНоменклатуры КАК ВидНоменклатуры
ИЗ
    РегистрСведений.ЛабораторныеПоказателиВидовНоменклатур КАК Регистр
ГДЕ
    Регистр.ЛабораторныйПоказатель = &ФильтрПоЛП

При таком подходе мы передаем значение в параметр динамического списка ФильтрПоЛП. На экране пользователь видит отфильтрованные данные. Однако при нажатии кнопки «Создать» или клавиши Insert открывается пустая форма записи, где поле ЛабораторныйПоказатель остается незаполненным.

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

Ниже мы разберем правильные методы решения этой задачи.

Способ 1. Использование стандартного механизма отборов платформы (Рекомендуемый)

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

Для реализации этого способа выполним несколько последовательных шагов.

Шаг 1. Настройка метаданных в конфигураторе

Прежде всего необходимо убедиться, что у объекта конфигурации правильно настроены свойства:

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

Шаг 2. Настройка динамического списка

Убедитесь, что в форме списка регистра сведений у реквизита Список (тип ДинамическийСписок) в свойствах заполнено поле «Основная таблица» (должно быть указано: РегистрСведений.ЛабораторныеПоказателиВидовНоменклатур). Если основная таблица не заполнена, платформа не сможет связать элементы отбора с полями создаваемой записи.

Шаг 3. Правильное открытие формы списка

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


&НаКлиенте
Процедура ВидыНоменклатуры(Команда)
    
    // Формируем структуру стандартного отбора
    ОтборСписка = Новый Структура("ЛабораторныйПоказатель", Объект.Ссылка);
    
    // Помещаем отбор в параметры формы под предопределенным ключом "Отбор"
    ПараметрыФормы = Новый Структура("Отбор", ОтборСписка);
    
    // Открываем форму списка регистра с передачей параметров
    ОткрытьФорму("РегистрСведений.ЛабораторныеПоказателиВидовНоменклатур.ФормаСписка", ПараметрыФормы);
    
КонецПроцедуры

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

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

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

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


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

Вызывать эту процедуру можно, например, при открытии формы списка на сервере:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    Если Параметры.Свойство("ФильтрПоЛП") Тогда
        УстановитьОтборСписка(Список, "ЛабораторныйПоказатель", Параметры.ФильтрПоЛП);
    КонецЕсли;
    
КонецПроцедуры

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

Способ 3. Программный перехват события добавления (Для сложных случаев)

Рассмотрим ситуацию, когда динамический список построен по сложному запросу, использующему объединения (ОБЪЕДИНИТЬ) нескольких таблиц, из-за чего свойство ОсновнаяТаблица в настройках списка указать невозможно. Стандартный механизм автозаполнения в таких условиях бессилен.

В этом случае мы можем принудительно перехватить нажатие кнопки «Создать» на форме списка и передать нужные параметры заполнения вручную.

Проанализируем этот алгоритм шаг за шагом:

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

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

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

Способ 4. Ручная обработка переданных параметров в форме записи

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

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

Посмотрим на пример кода в форме списка (вызов события добавления):


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

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


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

Резюме

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

← На главную