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

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

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

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

В чем сложность в обычных формах?

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

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

Основное решение: Использование события ПриПолученииДанных

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

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

Событие ПриПолученииДанных работает иначе. Оно вызывается один раз для всей порции строк, которые выводятся на экран (обычно это 20-30 строк). Это позволяет нам получить ссылки всех отображаемых элементов, выполнить один пакетный запрос к регистру сведений и быстро распределить полученные значения по ячейкам.

Пошаговый алгоритм реализации

Шаг 1. Добавим на форму в табличное поле списка справочника новую колонку. Зададим ей уникальное имя (например, ИмяКолонки). Свойство Данные оставляем пустым.

Шаг 2. Создадим обработчик события ПриПолученииДанных для табличного поля списка справочника и напишем следующий код:


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

КонецПроцедуры

Альтернативные варианты оптимизации

Рассмотрим ситуации, когда стандартный подход может быть скорректирован ради оптимизации работы интерфейса:

  1. Вывод информации вне таблицы. Если регистр сведений содержит сложную структуру данных и даже пакетный запрос к нему выполняется медленно, имеет смысл отказаться от вывода колонки. Вместо этого можно использовать обработчик события ПриАктивизацииСтроки. При выборе конкретной строки пользователем выполняется один легкий запрос по текущей ссылке, а результат выводится в отдельное текстовое поле (декоративную надпись), расположенное внизу формы списка.
  2. Кэширование при открытии формы. Если регистр сведений содержит небольшой и редко меняющийся объем данных, мы можем прочитать его целиком один раз при событии ПриОткрытии формы и сохранить в переменную модуля (например, в Соответствие). Тогда в обработчике ПриПолученииДанных мы будем мгновенно сопоставлять данные из оперативной памяти без единого обращения к СУБД.

Особенности перехода на управляемые формы

Если в будущем планируется перевод решения на управляемые формы, полезно знать следующие нюансы работы с динамическими списками:

← На главную