При разработке учетных механизмов в платформе 1С:Предприятие 8.3 нередко возникает задача заполнения реквизитов документа на основании данных регистра сведений. В отличие от справочников или документов, регистр сведений является нессылочным объектом метаданных. В стандартной конфигурации у него нет предопределенной формы выбора (доступны только форма списка, форма записи и форма набора записей), а строки регистра не имеют уникальной ссылки. Разберем по шагам, как правильно создать форму выбора на базе формы списка регистра сведений, открыть ее из документа и корректно передать выбранные значения на управляемых формах.
Прежде чем приступать к написанию кода, проанализируем ключевые особенности регистров сведений:
СрезПоследних.ОткрытьФорму()) должны выполняться строго в клиентском контексте директивы &НаКлиенте. Метод создания ключа записи СоздатьКлючЗаписи() выполняется на сервере. Несоблюдение контекста приводит к ошибке компиляции «Процедура или функция с указанным именем не определена».Рассмотрим наиболее гибкий и современный способ для управляемых форм, не требующий вызова модальных окон и совместимый с режимом работы без модальности.
Шаг 1. Настройка формы списка регистра сведений
Создадим форму списка регистра сведений (например, с именем ФормаВыбора). Если требуется выбирать только актуальные записи, в свойствах основного реквизита Список (динамический список) включим флаг Произвольный запрос и укажем запрос к виртуальной таблице РегистрСведений.ПериодическийРасход.СрезПоследних.
В модуле формы списка регистра переопределим стандартную обработку выбора в таблице формы:
&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
// Получаем текущие данные выбранной строки динамического списка
ТекущиеДанные = Элементы.Список.ТекущиеДанные;
Если ТекущиеДанные <> Неопределено Тогда
// Оповещаем владельца формы о выборе конкретных данных
ОповеститьОВыборе(ТекущиеДанные);
КонецЕсли;
КонецПроцедуры
Шаг 2. Вызов формы из документа и обработка результата
В модуле формы документа организуем открытие формы списка в режиме выбора через клиентскую процедуру и настроим обработку возвращаемых данных через ОписаниеОповещения:
&НаКлиенте
Процедура ПодобратьИзРегистра(Команда)
// Создаем описание процедуры, которая выполнится после закрытия формы выбора
Оповещение = Новый ОписаниеОповещения("ПослеВыбораЗаписиРегистра", ЭтотОбъект);
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("РежимВыбора", Истина);
ПараметрыОткрытия.Вставить("ЗакрыватьПриВыборе", Истина);
// Открываем форму списка регистра сведений
ОткрытьФорму("РегистрСведений.ПериодическийРасход.Форма.ФормаВыбора",
ПараметрыОткрытия,
ЭтотОбъект,
,
,
,
Оповещение);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораЗаписиРегистра(РезультатВыбора, ДополнительныеПараметры) Экспорт
// Проверяем, что пользователь действительно выбрал строку, а не просто закрыл форму
Если РезультатВыбора <> Неопределено Тогда
// Заполняем реквизиты документа полученными значениями
Объект.КошелекОтправления = РезультатВыбора.Кошелек;
Объект.Получатель = РезультатВыбора.Получатель;
Объект.Сумма = РезультатВыбора.Сумма;
КонецЕсли;
КонецПроцедуры
Разберем альтернативный вариант, когда форма возвращает стандартный идентификатор строки регистра — РегистрСведенийКлючЗаписи. Этот подход используется, если форма списка работает в стандартном режиме выбора и возвращает только ключевые поля (период и измерения).
В этом случае в форме документа принимается ключ записи, после чего выполняется серверный вызов для считывания ресурсов записи:
&НаКлиенте
Процедура ПослеВыбораКлючаЗаписи(РезультатВыбора, ДополнительныеПараметры) Экспорт
Если РезультатВыбора <> Неопределено Тогда
// РезультатВыбора имеет тип РегистрСведенийКлючЗаписи
ЗаполнитьДокументПоКлючуНаСервере(РезультатВыбора);
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ЗаполнитьДокументПоКлючуНаСервере(КлючЗаписи)
// Считываем запись через набор записей с отбором по измерениям
Набор = РегистрыСведений.ПериодическийРасход.СоздатьНаборЗаписей();
Набор.Отбор.Период.Установить(КлючЗаписи.Период);
Набор.Отбор.Кошелек.Установить(КлючЗаписи.Кошелек);
Набор.Отбор.Получатель.Установить(КлючЗаписи.Получатель);
Набор.Прочитать();
Если Набор.Количество() > 0 Тогда
Запись = Набор[0];
Объект.Сумма = Запись.Сумма;
Объект.Получатель = Запись.Получатель;
Объект.КошелекОтправления = Запись.Кошелек;
КонецЕсли;
КонецПроцедуры
ОткрытьФорму() вызывается в процедуре с директивой &НаСервере. Вызов отображения окон интерфейса должен производиться исключительно на клиенте (&НаКлиенте).ПолучитьФорму() и ПолучитьФормуСписка() не применяются в управляемом интерфейсе. Вместо них всегда используется глобальный метод ОткрытьФорму().СоздатьКлючЗаписи() ожидает структуру, имена ключей которой в точности совпадают с именами измерений и периода регистра сведений. Ошибки в именах свойств структуры приводят к созданию некорректного ключа.