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

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

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

Разберем специфику регистра сведений и все штатные способы передачи данных между формой списка регистра и вызывающей формой документа.

Особенности регистра сведений при выборе данных

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

Обратиться напрямую через точку к ресурсам или реквизитам выбранной строки через ключ нельзя. Чтобы получить нужные значения в вызывающей форме, мы можем пойти несколькими путями:

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

Способ 1. Штатный режим выбора и обработчик ОбработкаВыбора

Рассмотрим классический механизм платформы. Чтобы форма списка при двойном клике или нажатии клавиши Enter не пыталась открыть форму записи, а возвращала значение в документ, её нужно открыть с параметром РежимВыбора, указав форму документа в качестве владельца.

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


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

В модуле формы документа переопределим или создадим предопределенное клиентское событие ОбработкаВыбора:


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

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

Способ 2. Возврат произвольной структуры данных через ОповеститьОВыборе

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

В форме списка регистра добавим обработчик события Выбор для таблицы списка (динамического списка):


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

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


&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
    Если ТипЗнч(ВыбранноеЗначение) = Тип("Структура") И ВыбранноеЗначение.Свойство("Цена") Тогда
        Объект.Цена = ВыбранноеЗначение.Цена;
    КонецЕсли;
КонецПроцедуры

Способ 3. Передача через ОписаниеОповещения при открытии формы

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

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

Способ 4. Взаимодействие через глобальное оповещение (Оповестить)

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

В форме списка регистра отправляем оповещение:


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

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


&НаКлиенте
Процедура ОбработкаОповещения(ИмяОповещения, Параметр, Источник)
    Если ИмяОповещения = "ВыбранаЗаписьРегистраЦен" Тогда
        Объект.Цена = Параметр.Цена;
    КонецЕсли;
КонецПроцедуры

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

← На главную