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

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

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

Давайте подробно разберем, как правильно создать такую колонку, программно её заполнить и при этом не «повесить» систему из-за проблем с производительностью.

Шаг 1. Настройка колонки в конфигураторе

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

  1. Кликнем правой кнопкой мыши по табличному полю и выберем Вставить колонку.
  2. В свойствах новой колонки зададим ей понятное имя, например, КолонкаКод.
  3. Важно: свойство «Данные» (Data) оставляем пустым! Колонка не должна быть привязана к физическим данным базы.
  4. В свойстве «Элемент управления» укажем Поле ввода.

Шаг 2. Заполнение колонки: почему событие ПриВыводеСтрок — плохая идея

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


Процедура ТабличноеПолеПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    ОформлениеСтроки.Ячейки.КолонкаКод.УстановитьТекст(ДанныеСтроки.Регистратор.Код);
КонецПроцедуры

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

Событие ПриВыводеСтрок срабатывает для каждой отдельной видимой строки при любой перерисовке экрана (скроллинг, клик, выделение строки). Обращаясь через точку к реквизиту ссылки (ДанныеСтроки.Регистратор.Код), мы заставляем платформу неявно выполнять микро-запрос к базе данных. Если на экране помещается 50 строк, платформа сделает 50 отдельных запросов к базе. Возникает классическая проблема «N+1 запроса», из-за которой список начнет катастрофически тормозить.

Шаг 3. Оптимальное решение: используем ПриПолученииДанных

Чтобы избежать тормозов, воспользуемся событием ПриПолученииДанных. Это событие вызывается один раз для целой «пачки» строк, которые готовятся к выводу на экран. Проанализируем алгоритм действий:

  1. Обходим коллекцию строк, которые сейчас выводятся на экран, и собираем все ссылки на регистраторы в массив.
  2. Выполняем один единственный запрос к базе данных, передав в него наш массив ссылок.
  3. Результат запроса помещаем в объект Соответствие для мгновенного поиска.
  4. Снова обходим строки и устанавливаем текст и цвет ячеек из подготовленного соответствия.

Посмотрим на пример правильного и оптимизированного кода:


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

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

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

Дополнительные возможности оформления

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

Альтернативный архитектурный подход: добавление измерения

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

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

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

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

← На главную