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

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет
← На главную

При работе с классическими конфигурациями 1С (такими как УТ 10.3, УПП 1.3 или КА 1.1) разработчики часто сталкиваются с необходимостью вывести в список документов дополнительные данные, которых нет в реквизитах самого документа. Например, это может быть общая сумма связанных перемещений, статус оплаты из регистра или любая другая вычисляемая величина. В отличие от управляемых форм, где динамические списки позволяют легко добавлять поля через произвольный запрос, обычные формы требуют иного подхода. Разберем подробно, как реализовать эту задачу эффективно и правильно.

Постановка задачи и выбор метода решения

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

Метод 1: Событие ПриВыводеСтроки (Простой, но медленный)

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

Рассмотрим пример кода, который может привести к серьезным проблемам с производительностью:


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

Почему это плохо? Если на экране отображается 20 строк, 1С выполнит 20 отдельных обращений к базе данных при каждой прокрутке списка или обновлении формы. Это вызовет ощутимые «тормоза» интерфейса. Выясним причину: каждое обращение ДанныеСтроки.Ссылка.ИмяТабличнойЧасти заставляет платформу считывать объект из базы целиком.

Метод 2: Событие ПриПолученииДанных (Оптимальный)

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

Разберем алгоритм работы по шагам:

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

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


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

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

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

Программное добавление колонки

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

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


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

Важно помнить: такая колонка является виртуальной. Она существует только в памяти интерфейса.

Ограничения: Сортировка и Отборы

Рассмотрим критически важный нюанс использования произвольных колонок в обычных формах. Поскольку данные в нашей колонке «СуммаДокументов» рассчитываются «на лету» в коде, платформа 1С не может выполнять по ним стандартную сортировку или устанавливать отборы через меню «Установить фильтр».

Почему так происходит? Сортировка списка на обычных формах выполняется на уровне СУБД (SQL запросом к таблице). Так как физически поля «СуммаДокументов» в таблице базы данных нет, сервер не знает, как упорядочить по нему записи. Если пользователю жизненно необходима сортировка по вычисляемому полю, у вас есть два пути:

Визуальное оформление

Используя объект ОформлениеСтроки, мы можем не только выводить текст, но и делать список более информативным. Проанализируем дополнительные возможности:

Изменение цвета текста: Если сумма отрицательная, выделим её красным цветом.


Ячейка = Оформление.Ячейки.СуммаДокументов;
Ячейка.УстановитьТекст(Строка(ТекСумма));
Если ТекСумма < 0 Тогда
    Ячейка.ЦветТекста = ЦветаСтиля.ЦветОтрицательногоЧисла;
КонецЕсли;

Вывод картинки: Можно добавить колонку без текста, которая будет показывать иконку статуса (например, «Оплачено» или «Просрочено»).


Оформление.Ячейки.Статус.ОтображатьКартинку = Истина;
Оформление.Ячейки.Статус.ИндексКартинки = 1; // Индекс из коллекции картинок

Резюме

При работе с обычными формами в 1С всегда отдавайте предпочтение событию ПриПолученииДанных. Это золотой стандарт разработки, обеспечивающий высокую скорость работы интерфейса даже при больших объемах данных. Помните о проверке ДанныеСтроки <> Неопределено, чтобы избежать ошибок при открытии пустых списков или создании новых документов. Хотя обычные формы уступают управляемым в гибкости настройки списков, грамотное использование объектной модели оформления строк позволяет решать практически любые бизнес-задачи.

← На главную