Как реализовать выбор записи из регистра сведений для заполнения реквизитов документа в 1С 8.3

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

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

Анализ архитектурных ограничений регистра сведений

Прежде чем приступать к написанию кода, проанализируем ключевые особенности регистров сведений:

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

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

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

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

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

В модуле формы списка регистра переопределим стандартную обработку выбора в таблице формы:


&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
    СтандартнаяОбработка = Ложь;
    
    // Получаем текущие данные выбранной строки динамического списка
    ТекущиеДанные = Элементы.Список.ТекущиеДанные;
    
    Если ТекущиеДанные <> Неопределено Тогда
        // Оповещаем владельца формы о выборе конкретных данных
        ОповеститьОВыборе(ТекущиеДанные);
    КонецЕсли;
КонецПроцедуры

Шаг 2. Вызов формы из документа и обработка результата

В модуле формы документа организуем открытие формы списка в режиме выбора через клиентскую процедуру и настроим обработку возвращаемых данных через ОписаниеОповещения:


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

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

Способ 2. Получение данных через «Ключ записи»

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

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


&НаКлиенте
Процедура ПослеВыбораКлючаЗаписи(РезультатВыбора, ДополнительныеПараметры) Экспорт
    Если РезультатВыбора <> Неопределено Тогда
        // РезультатВыбора имеет тип РегистрСведенийКлючЗаписи
        ЗаполнитьДокументПоКлючуНаСервере(РезультатВыбора);
    КонецЕсли;
КонецПроцедуры

&НаСервере
Процедура ЗаполнитьДокументПоКлючуНаСервере(КлючЗаписи)
    
    // Считываем запись через набор записей с отбором по измерениям
    Набор = РегистрыСведений.ПериодическийРасход.СоздатьНаборЗаписей();
    
    Набор.Отбор.Период.Установить(КлючЗаписи.Период);
    Набор.Отбор.Кошелек.Установить(КлючЗаписи.Кошелек);
    Набор.Отбор.Получатель.Установить(КлючЗаписи.Получатель);
    
    Набор.Прочитать();
    
    Если Набор.Количество() > 0 Тогда
        Запись = Набор[0];
        Объект.Сумма = Запись.Сумма;
        Объект.Получатель = Запись.Получатель;
        Объект.КошелекОтправления = Запись.Кошелек;
    КонецЕсли;
    
КонецПроцедуры

Частые ошибки при разработке и методы их решения

  1. Ошибка «Процедура или функция с указанным именем не определена (ОткрытьФорму)»: Метод ОткрытьФорму() вызывается в процедуре с директивой &НаСервере. Вызов отображения окон интерфейса должен производиться исключительно на клиенте (&НаКлиенте).
  2. Использование устаревших методов обычного приложения: Вызовы ПолучитьФорму() и ПолучитьФормуСписка() не применяются в управляемом интерфейсе. Вместо них всегда используется глобальный метод ОткрытьФорму().
  3. Несоответствие типов при создании ключа записи: Конструктор СоздатьКлючЗаписи() ожидает структуру, имена ключей которой в точности совпадают с именами измерений и периода регистра сведений. Ошибки в именах свойств структуры приводят к созданию некорректного ключа.
← На главную