При работе с классом ТабличноеПоле и компонентой 1CPP в 1С 7.7 часто возникает задача добавления расчетных колонок (например, остатка долга по документу) и вывода общей суммы этих значений в подвал (footer) таблицы. Рассмотрим, как правильно реализовать эту логику, избежать проблем с производительностью и вовремя обновлять данные в подвале.
Выясним, почему стандартная попытка посчитать итоги прямо в процедуре ЭкранПриВыводеСтроки приводит к ошибкам и зависаниям интерфейса:
ПриВыводеСтроки срабатывает исключительно для тех строк, которые видны пользователю на экране в данный момент. Попытка суммировать значения при отрисовке строк посчитает только видимую область, а при скроллинге данные исказятся.Регистр.ДолгОтгрузки.Остаток(...) внутри события отрисовки ячейки выполняется при каждом пересчете экрана. Это приводит к задержкам и «зависанию» журнала при прокрутке.ТипРегиона = 2) и подвала (ТипРегиона = 4) отрисовываются при инициализации формы. При прокрутке основного списка (ТипРегиона = 3) подвал повторно не вызывается автоматически, поэтому его нужно обновлять программно.Для понимания логики вывода строк приведем значения типов регионов элемента ТабличноеПоле:
0 — регион не задан;1 — заголовок;2 — шапка;3 — строки (основная область данных);4 — подвал (footer).Разберем по шагам корректный алгоритм вычисления и отображения итоговой суммы:
ИтоговыйДолг).ЭкранПриВыводеСтроки при обработке ТипРегиона = 4 значение из переменной устанавливается в ячейку подвала.Рассмотрим пример добавления колонки и настройки вывода подвала в модуле формы:
// Переменная модуля для хранения итогового значения
Перем ИтоговыйДолг;
Процедура ПриОткрытии()
// Добавление колонки данных и колонки отображения
Данные.ДобавитьКолонкуДанных("Долг", "Долг", "''", "Число", 15, 2);
Данные.НоваяКолонка("Долг", 1);
ИтоговыйДолг = 0;
КонецПроцедуры
Процедура ЭкранПриВыводеСтроки(ТабличноеПоле, ОформлениеСтроки, ДанныеСтроки, ТипРегиона)
Если ТипРегиона = 3 Тогда
// Отрисовка основной строки
ТекДок = ДанныеСтроки.Получить("ТекущийДокумент");
ОформлениеЯчейки = ОформлениеСтроки.Ячейки.Получить("Долг");
// Примечание: Для высокой скорости рекомендуем получать Долг в SQL-запросе поставщика
ОформлениеЯчейки.УстановитьТекст(Регистр.ДолгОтгрузки.Остаток(ТекДок, "Долг"));
ИначеЕсли ТипРегиона = 4 Тогда
// Отрисовка подвала (footer)
ОформлениеЯчейки = ОформлениеСтроки.Ячейки.Получить("Долг");
ОформлениеЯчейки.УстановитьТекст(Строка(ИтоговыйДолг));
КонецЕсли;
КонецПроцедуры
Поскольку подвал не перерисовывается при обычной прокрутке списка, необходимо отлавливать моменты изменения данных (установка фильтра, сброс отбора, обновление журнала) и вызывать пересчет суммы с последующим обновлением подвала.
Для принудительного обновления визуального состояния подвала используем следующий метод:
Процедура ОбновитьИтогиПодвала()
// 1. Выполняем полный расчет суммы по всему набору данных
// Например, с помощью запроса или обхода выборки
ИтоговыйДолг = РассчитатьОбщуюСуммуДолга();
// 2. Принудительно обновляем отображение строк подвала
ТабличноеПоле.Подвал.ОбновитьСтроки();
КонецПроцедуры
Если для подвала используется отдельный поставщик данных, обновить его строки можно через обращение к источнику:
ПоставщикДанных.ТабличноеПоле.Подвал.ОбновитьСтроки();
Проанализируем наиболее производительный вариант: если ПоставщикДанных работает на базе прямого SQL-запроса (ODBC), вычисление долга по каждому документу и подсчет общей суммы лучше всего вынести на сторону СУБД.
В этом случае колонка «Долг» соединяется с виртуальной таблицей остатков регистра прямо в SQL-запросе. Это полностью исключит задержки при прокрутке журнала, а итоговая сумма будет получаться за один агрегатный запрос с помощью функции SUM().