В обычном приложении 1С табличное поле, связанное с динамическим списком (например, с реквизитом типа ДокументСписок или СправочникСписок), не обладает встроенным свойством автоматического подсчета итогов в подвале. В отличие от табличных частей или таблиц значений, динамический список считывает данные из базы данных порциями, по мере прокрутки. Из-за этого платформа "не знает" общую сумму всех документов в списке без выполнения дополнительного запроса.
Разберем подробно, как решить задачу вывода итога по колонке "Сумма" в подвал формы списка, как оптимизировать этот процесс для исключения зависаний системы, и какие альтернативные интерактивные методы можно предложить пользователям.
Наиболее очевидный способ, который часто выбирают начинающие разработчики, заключается в использовании события списка ПриПолученииДанных и объекта ПостроительОтчета. Рассмотрим пример такого кода:
Процедура ДокументСписокПриПолученииДанных(Элемент, ОформленияСтрок)
ПостроительОтчета = Новый ПостроительОтчета;
ПостроительОтчета.ИсточникДанных = Новый ОписаниеИсточникаДанных(ДокументСписок);
Таб = ПостроительОтчета.Результат.Выгрузить();
СуммаДокументов = Таб.Итог("СуммаДокумента");
КонецПроцедуры
В данном примере СуммаДокументов — это реквизит формы, расположенный под табличным полем списка документов.
Важное предупреждение: этот способ крайне не рекомендуется использовать на рабочих базах с большим объемом данных! Метод Выгрузить() заставляет систему полностью выкачивать все записи списка из базы данных на клиентский компьютер. При каждой прокрутке списка, изменении размеров окна или поиске это событие будет срабатывать заново, вызывая жуткие торможения интерфейса и перегружая сервер.
Чтобы избежать передачи всей таблицы документов на клиент, мы должны переложить задачу суммирования на сервер баз данных. Для этого мы получим текст запроса динамического списка (вместе со всеми наложенными пользователем отборами) через ПостроительЗапроса, а затем обернем его во вложенный запрос, который вернет нам ровно одно число — итоговую сумму.
Рассмотрим пример правильной реализации:
Построитель = Новый ПостроительЗапроса;
Построитель.ИсточникДанных = Новый ОписаниеИсточникаДанных(ДокументСписок);
// Получаем готовый запрос с учетом всех пользовательских настроек и отборов
ЗапросИтога = Построитель.ПолучитьЗапрос();
ЗапросИтога.Текст = "ВЫБРАТЬ СУММА(Вл.СуммаДокумента) КАК Всего ИЗ (" + ЗапросИтога.Текст + ") КАК Вл";
Выборка = ЗапросИтога.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
ИтоговаяСумма = Выборка.Всего;
КонецЕсли;
Этот метод работает в разы быстрее, так как сервер СУБД самостоятельно выполняет группировку и возвращает клиенту единственное числовое значение.
Даже оптимизированный запрос к базе данных может вызывать задержки, если в списке находятся сотни тысяч документов, а пользователь постоянно меняет отборы. Чтобы сделать работу максимально комфортной, применим следующие подходы:
СуммаДокумента), который заполняется в момент записи документа. Если реквизита в шапке нет и сумма каждый раз рассчитывается динамически по табличной части каждого документа, то любой групповой расчет по журналу будет выполняться крайне медленно.Если конфигурация находится на поддержке и вносить изменения в код нельзя, покажем бухгалтеру штатные интерактивные возможности платформы 1С для быстрого получения итогов:
Способ 1. Использование встроенного калькулятора (комбинация Ctrl + A + M+)
Способ 2. Вывод списка в табличный документ