В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача предоставить пользователю возможность видеть итог (например, сумму документов или количество товара) по произвольно выбранным строкам в списке. При этом критически важно выполнять такие расчеты на стороне клиента, чтобы не создавать лишнюю нагрузку на сервер приложений и базу данных, особенно если в системе одновременно работают десятки или сотни пользователей через веб-клиент или медленные каналы связи.
В данной статье мы подробно разберем, как реализовать механизм подсчета суммы выделенных строк, проанализируем различные способы отслеживания событий выделения и рассмотрим технические нюансы, включая настройки динамического списка и кэширование данных.
Если ваша таблица на форме является Динамическим списком, то самый простой и эффективный способ получить данные выделенных строк на клиенте — это использование метода ДанныеСтроки(). Этот метод позволяет обратиться к полям строки, которые уже загружены в память клиента.
Рассмотрим алгоритм реализации. Сначала нам необходимо получить массив идентификаторов выделенных строк, а затем в цикле обойти их и просуммировать значения нужной колонки (аналогично тому, как реализуется флажок в динамическом списке). Пример кода для обработчика:
&НаКлиенте
Процедура ПересчитатьСуммуВыделенных()
Перем Сумма;
Сумма = 0;
// Получаем массив идентификаторов выделенных строк
ВыделенныеСтроки = Элементы.Список.ВыделенныеСтроки;
Для Каждого ИдентификаторСтроки Из ВыделенныеСтроки Цикл
// Получаем данные конкретной строки на клиенте
Данные = Элементы.Список.ДанныеСтроки(ИдентификаторСтроки);
// Проверяем, что данные доступны (могут быть не загружены в кэш)
Если Данные <> Неопределено Тогда
Сумма = Сумма + Данные.СуммаДокумента;
КонецЕсли;
КонецЦикла;
// Выводим результат в реквизит формы, отображаемый в подвале или декорации
ИтогПоВыделенным = Сумма;
КонецПроцедуры
Важное условие: Для того чтобы метод ДанныеСтроки() «видел» поле суммы, эта колонка обязательно должна присутствовать в элементах формы (в дереве элементов внутри таблицы). Если вам не нужно показывать эту колонку пользователю, установите ей свойство Видимость = Ложь, но не удаляйте её из состава элементов, иначе данные не будут доступны на клиенте.
Если же на форме отображается не динамический список, а обычная таблица (например, объектная таблица значений или табличная часть), подход немного меняется. Вместо метода динамического списка мы используем метод НайтиПоИдентификатору() самой коллекции данных формы.
Проанализируем пример для таблицы с именем Товары:
&НаКлиенте
Процедура РассчитатьИтогТаблицы()
МассивИдентификаторов = Элементы.Товары.ВыделенныеСтроки;
РезультатСумма = 0;
Для Каждого ТекущийID Из МассивИдентификаторов Цикл
// Поиск строки в источнике данных по ID
СтрокаДанных = Объект.Товары.НайтиПоИдентификатору(ТекущийID);
Если СтрокаДанных <> Неопределено Тогда
РезультатСумма = РезультатСумма + СтрокаДанных.Сумма;
КонецЕсли;
КонецЦикла;
ЭтаФорма.НадписьИтого = РезультатСумма;
КонецПроцедуры
Одной из главных сложностей является определение момента, когда нужно запускать пересчет. Стандартные события формы ведут себя по-разному в зависимости от действий пользователя:
Разберем реализацию через обработчик ожидания, который гарантированно «поймает» выделение всех строк через Ctrl+A:
&НаКлиенте
Перем мКоличествоВыделенных; // Глобальная переменная модуля клиента
&НаКлиенте
Процедура ПриОткрытии(Отказ)
мКоличествоВыделенных = 0;
// Запускаем таймер с интервалом 0.5 сек
ПодключитьОбработчикОжидания("КонтрольВыделения", 0.5);
КонецПроцедуры
&НаКлиенте
Процедура КонтрольВыделения()
ТекВыделено = Элементы.Список.ВыделенныеСтроки.Количество();
// Если количество изменилось — пересчитываем
Если ТекВыделено <> мКоличествоВыделенных Тогда
ПересчитатьСуммуВыделенных(); // Вызов нашей функции расчета
мКоличествоВыделенных = ТекВыделено;
КонецЕсли;
КонецПроцедуры
При реализации данного функционала следует учитывать несколько критических моментов, которые могут повлиять на корректность работы программы:
1. Кэширование данных: Метод ДанныеСтроки() работает только с теми данными, которые физически переданы с сервера на клиент. Динамический список подгружает данные порциями (обычно по 20–50 строк). Если пользователь выделит 1000 строк и прокрутит список вниз, часть данных в начале списка может быть вытеснена из кэша. В этом случае ДанныеСтроки() вернет Неопределено. Если для вашей задачи критична 100% точность на огромных выборках, расчет придется переносить на сервер, передавая туда массив ссылок.
2. Иерархические списки: Если в вашем списке включено отображение групп (иерархия), помните, что в массив ВыделенныеСтроки попадают и идентификаторы групп. У групп, как правило, нет реквизита «Сумма», поэтому при обходе массива обязательно делайте проверку на тип данных или наличие свойства, чтобы избежать ошибок выполнения.
3. Свойство ПутьКДаннымПодвала: Чтобы результат расчета выглядел эстетично, используйте стандартные возможности платформы. У колонки таблицы в свойствах есть поле ПутьКДаннымПодвала. Если вы укажете там имя реквизита формы (например, ИтогПоВыделенным), значение будет отображаться в нижней части таблицы в соответствующей колонке, что является стандартным поведением для продуктов на базе 1С.
4. Обновление интерфейса: Изменение заголовков или видимости элементов формы внутри событий активации строки может приводить к «дребезгу» интерфейса или повторному вызову событий. Старайтесь минимизировать количество визуальных изменений во время быстрых действий пользователя (например, при быстром пролистывании списка стрелками клавиатуры).
Таким образом, комбинируя использование метода ДанныеСтроки() и обработчика ожидания, можно создать отзывчивый и производительный интерфейс, который позволит пользователям мгновенно получать итоговые данные по выделенным объектам без лишних обращений к базе данных.