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