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