Как программно добавить колонку в табличное поле и заполнить её значениями в 1С

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

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

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

Шаг 1. Программное добавление виртуальной колонки

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

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

Разберем пример кода для добавления колонки:


Процедура ПриОткрытии()
    
    // Добавляем новую колонку в табличное поле "ДокументСписок"
    НоваяКолонка = ЭлементыФормы.ДокументСписок.Колонки.Добавить("ИмяВашейКолонки", "Статус оплаты");
    
    // Настраиваем внешний вид и ширину
    НоваяКолонка.Ширина = 15;
    НоваяКолонка.Доступность = Истина;
    
КонецПроцедуры

После выполнения этого кода на форме появится пустая колонка с заголовком "Статус оплаты". Теперь наша задача — заполнить её данными для каждой отображаемой строки.

Шаг 2. Заполнение через «ПриВыводеСтроки» (Простой способ и его опасности)

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

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


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

Почему этот способ является «миной замедленного действия»?

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

Шаг 3. Правильная реализация через «ПриПолученииДанных»

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

Разберем по шагам алгоритм правильной работы с этим событием:

  1. Сбор ссылок: Мы обходим переданную коллекцию строк и собираем уникальные ссылки отображаемых документов в массив. Параллельно формируем соответствие, где ключом будет ссылка на объект, а значением — оформление строки.
  2. Пакетный запрос: Мы делаем один-единственный запрос к базе данных, передавая туда весь массив собранных ссылок через оператор В (&МассивСсылок).
  3. Быстрое заполнение: Обходим результат запроса и моментально заполняем ячейки, используя ранее созданное соответствие строк. Никаких дополнительных обращений к серверу больше не происходит.

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


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

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

Важные ограничения виртуальных колонок

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

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

Как эта задача решается на управляемых формах (1С 8.3)

Если вы планируете переводить конфигурацию на современные управляемые формы (интерфейс "Такси"), то концепция работы со списками кардинально меняется:

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

← На главную