Как добавить произвольную колонку в журнал документов на обычных формах 1С

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

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

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

Анализ проблемы: ПриВыводеСтроки против ПриПолученииДанных

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

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

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

Решение 1: Оптимальный метод через ПриПолученииДанных

Рассмотрим пошаговый алгоритм реализации вывода данных с помощью одного запроса. Допустим, нам нужно вывести «Контрагента» в журнал, где этого поля нет в метаданных.

Шаг 1. Создание колонки. Вы можете добавить колонку (Графу) в конфигураторе в объект «Журнал документов», либо добавить колонку программно в самом табличном поле на форме. Важно: свойство Данные у этой колонки должно оставаться пустым.

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


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

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

Этот подход гарантирует высокую скорость работы даже при больших объемах данных, так как количество запросов к базе минимизировано.

Решение 2: Использование ПриВыводеСтроки

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

Разберем типичную ошибку. Многие пытаются записать данные напрямую в ДанныеСтроки, но система выдает ошибку "Поле объекта не обнаружено" или "Реквизит не доступен для записи". Это происходит потому, что ДанныеСтроки отражают состояние данных в базе, а не визуальное представление.

Правильный способ — работа через коллекцию Ячейки объекта ОформлениеСтроки:


Процедура ЖурналДокументовСписокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    
    // Правильная установка значения через ОформлениеСтроки
    ОформлениеСтроки.Ячейки.Контрагент.УстановитьТекст(ДанныеСтроки.Ссылка.Контрагент);
    
    // Можно также менять цвет фона или шрифт
    Если ДанныеСтроки.Проведен Тогда
        ОформлениеСтроки.Ячейки.Контрагент.ЦветТекста = ЦветаСтиля.ЦветДистанционнойРаботы;
    КонецЕсли;

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

Важные ограничения и особенности

При использовании программного вывода колонок следует учитывать несколько критически важных моментов:

  1. Отбор и сортировка. По колонкам, заполненным в событиях ПриПолученииДанных или ПриВыводеСтроки, невозможно осуществлять стандартную сортировку или поиск. Платформа не видит этих данных в физической таблице базы данных. Если пользователю жизненно необходима сортировка по этому полю, его придется добавлять как реальную «Графу» в метаданные журнала и заполнять при записи документов.
  2. Кэширование. Если вы используете тяжелые запросы, рекомендуется создать в модуле формы переменную типа Соответствие для кэширования результатов. При повторном вызове события для тех же строк данные можно будет брать из памяти, а не из базы.
  3. Программное добавление колонок. Выясним, как добавить колонку, не заходя в конфигуратор. Это делается в процедуре ПриОткрытии формы:

НоваяКолонка = ЭлементыФормы.ЖурналДокументовСписок.Колонки.Вставить(0, "ВиртуальнаяКолонка");
НоваяКолонка.Имя = "СтатусДокумента";
НоваяКолонка.ТекстШапки = "Статус";
НоваяКолонка.Ширина = 15;

После этого к ячейке с именем "СтатусДокумента" можно обращаться в обработчиках оформления строк, как мы рассматривали выше.

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

← На главную