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

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

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

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

Способ 1. Использование события «ПриПолученииДанных» (рекомендуемый)

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

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

Разберем алгоритм реализации:

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

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


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

Ограничения вычисляемых колонок

Рассмотрим важную особенность: по колонкам, которые заполняются программно через оформление строк, стандартная сортировка платформы и быстрый поиск работать не будут. Так как этих данных физически нет в объекте РегистрСведенийСписок, платформа не может применить к ним встроенные SQL-фильтры без дополнительной программной обработки формы.

Способ 2. Замена источника данных табличного поля на ТаблицуЗначений

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

Разберем по шагам, как это работает:

  1. Очищаем свойство Данные у табличного поля формы списка.
  2. Создаем в модуле формы процедуру обновления данных, выполняющую запрос с левым соединением к нужным справочникам.
  3. Выгружаем результат запроса в объект ТаблицаЗначений и присваиваем свойству ЭлементыФормы.ТабличноеПоле.Значение.
  4. Вызываем созданную процедуру при открытии формы и при изменении фильтров.

Посмотрим на пример реализации запроса:


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

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

Способ 3. Денормализация структуры регистра (архитектурное решение)

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

← На главную