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

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

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

В чем заключается ошибка при использовании метода ЗаполнитьЗначенияСвойств

Проанализируем типовую ситуацию: разработчик пытается программно обойти строки списка и перенести данные из таблицы значений или структуры с помощью метода ЗаполнитьЗначенияСвойств(), передавая в качестве приемника текущую строку или ссылку:

ЗаполнитьЗначенияСвойств(текЭлемент, стр);

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

  1. Неизменяемость ссылочного типа: Переменная текЭлемент в динамическом списке содержит значение типа СправочникСсылка. Ссылка в платформе 1С является неизменяемым объектом. Ее свойства доступны только для чтения. Чтобы изменить реквизиты объекта базы данных, необходимо получить объект методом ПолучитьОбъект(), изменить свойства и вызвать метод Записать(). Однако для простого визуального отображения данных запись объектов в базу данных не требуется и является грубой архитектурной ошибкой.
  2. Особенности динамического списка: Основным источником данных в стандартных формах списков управляемого приложения выступает ДинамическийСписок. Он считывает данные из базы порциями (страницами) и предназначен исключительно для отображения. Строка динамического списка не является строкой таблицы значений или объектом данных, к ней нельзя применить прямое присвоение значений колонок или метод ЗаполнитьЗначенияСвойств().

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

Самый простой и стандартный способ отобразить данные из регистра сведений в форме списка — настроить произвольный запрос динамического списка. Посмотрим, как это сделать правильно.

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


ВЫБРАТЬ
    СпрНоменклатура.Ссылка КАК Ссылка,
    СпрНоменклатура.ПометкаУдаления КАК ПометкаУдаления,
    СпрНоменклатура.Код КАК Код,
    СпрНоменклатура.Наименование КАК Наименование,
    ЦеныНоменклатурыСрезПоследних.Цена КАК Цена
ИЗ
    Справочник.Номенклатура КАК СпрНоменклатура
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, ) КАК ЦеныНоменклатурыСрезПоследних
        ПО СпрНоменклатура.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура

Если дату среза регистра необходимо менять динамически прямо на форме (например, при смене реквизита формы ПериодОтображения), передадим значение параметра программно:


&НаКлиенте
Процедура ПериодОтображенияПриИзменении(Элемент)
    УстановитьПараметрСписка();
КонецПроцедуры

&НаСервере
Процедура УстановитьПараметрСписка()
    Список.Параметры.УстановитьЗначениеПараметра("Период", ПериодОтображения);
КонецПроцедуры

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

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

Способ 2. Использование события ПриПолученииДанныхНаСервере

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

Разберем по шагам реализацию этого механизма:

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

Посмотрим на пример программного кода:


&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, УправляемыеФормы, Строки)
    
    МассивСсылок = Новый Массив;
    Для Каждого КлючСтроки Из Строки.ПолучитьКлючи() Цикл
        МассивСсылок.Добавить(КлючСтроки);
    КонецЦикла;
    
    Если МассивСсылок.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |   Цены.Номенклатура КАК Номенклатура,
        |   Цены.Цена КАК Цена
        |ИЗ
        |   РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&Период, Номенклатура В (&МассивСсылок)) КАК Цены";
    
    Запрос.УстановитьПараметр("Период", ТекущаяДатаСеанса());
    Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
    
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        ДанныеСтроки = Строки[Выборка.Номенклатура];
        Если ДанныеСтроки <> Неопределено Тогда
            ДанныеСтроки.Оформление["ЦенаИзРегистра"].УстановитьТекст(Строка(Выборка.Цена));
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

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

Способ 3. Использование реквизита ТаблицаЗначений вместо ДинамическогоСписка

Если для бизнес-логики принципиально необходимо использовать именно метод ЗаполнитьЗначенияСвойств(), произвольно менять значения в строках без их немедленной записи в базу данных, то динамический список для этой цели не подходит.

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


Для Каждого СтрФормы Из ТаблицаНаФорме Цикл
    НайденнаяСтрока = ТаблицаЦен.Найти(СтрФормы.Ссылка, "Ссылка");
    Если НайденнаяСтрока <> Неопределено Тогда
        ЗаполнитьЗначенияСвойств(СтрФормы, НайденнаяСтрока);
    КонецЕсли;
КонецЦикла;

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

← На главную