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

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

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

Почему не работает прямая запись в ЭлементУправления?

Проанализируем механику работы табличного поля в обычных формах. Когда мы обращаемся к свойству ЭлементыФормы.ИмяТаблицы.Колонки.ИмяКолонки.ЭлементУправления.Значение, мы обращаемся к общему шаблону элемента управления для всей колонки целиком. В 1С обычных форм поле ввода (или другой элемент) не существует физически в каждой ячейке. Платформа динамически "подкладывает" один и тот же элемент управления в ту строку, которую пользователь сейчас редактирует.

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

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

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

Разберем пример кода для этого обработчика:


Процедура ТабличнаяЧастьПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
    
    // Рассчитываем значение на лету
    РезультатРасчета = ДанныеСтроки.Цена * ДанныеСтроки.Количество;
    
    // Устанавливаем текст в ячейку расчетной колонки
    ОформлениеСтроки.Ячейки.Итог.УстановитьТекст(Формат(РезультатРасчета, "ЧЦ=15; ЧДЦ=2"));
    
КонецПроцедуры

В данном случае мы используем объект ОформлениеСтроки, который содержит коллекцию Ячейки. Важно понимать: мы не меняем данные в базе, мы лишь управляем визуальным представлением конкретной строки. Метод УстановитьТекст() позволяет вывести строковое представление числа, которое останется видимым даже после выхода из режима редактирования.

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

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

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


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

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

Важный нюанс: Обновление данных при изменении

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


Процедура ТабличнаяЧастьКоличествоПриИзменении(Элемент)
    
    // Принудительно вызываем перерисовку текущей строки
    ЭлементыФормы.ТабличнаяЧасть.ОбновитьСтроки(ЭлементыФормы.ТабличнаяЧасть.ТекущаяСтрока);
    
КонецПроцедуры

Метод ОбновитьСтроки() сообщает системе, что визуальное состояние таблицы изменилось, и инициирует вызов обработчиков оформления. Без этого вызова пользователь увидит новый результат расчета только после того, как "дернет" таблицу мышкой или прокрутит список.

Ограничения расчетных колонок

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

  1. Отсутствие сортировки и фильтрации: Так как данные в колонке существуют только "нарисованными" в виде текста, встроенные механизмы 1С (кнопки сортировки по алфавиту/числу, автофильтр) работать не будут. Платформа не видит реальных значений за текстом ОформлениеСтроки.
  2. Поиск: Стандартный поиск (Ctrl+F) также не сможет найти данные в такой колонке.
  3. Сложность при печати: Если вы захотите вывести эту таблицу в печатную форму, вам придется дублировать алгоритм расчета в коде формирования табличного документа, так как из самой формы данные получить не удастся.

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

Таким образом, мы выяснили, что для простого визуального отображения расчетов лучше всего подходят события оформления строк. Мы научились правильно использовать УстановитьТекст() и поняли важность вызова ОбновитьСтроки() для поддержания актуальности данных в интерфейсе.

← На главную