В разработке на платформе 1С:Предприятие 8.х (особенно в режиме обычных форм) часто возникает задача интерактивного взаимодействия с пользователем через табличное поле. Одной из таких задач является автоматический расчет суммы выделенных числовых значений, как это реализовано в Excel. Однако при работе с ДокументСписок или стандартным табличным полем программисты сталкиваются с тем, что платформа не предоставляет прямой коллекции «выделенных ячеек». Вместо этого она оперирует выделенными строками, что создает трудности при попытке отследить повторный клик по ячейке для отмены ее выбора.
В этой статье мы подробно разберем, как правильно организовать алгоритм суммирования, как обрабатывать визуальное изменение состояния ячейки (переход из темно-синего цвета в белый с пунктиром) и какие методы 1С помогут сделать этот процесс эффективным.
Для начала проанализируем, что происходит на уровне платформы, когда пользователь взаимодействует с ячейками. В обычных формах у элемента ТабличноеПоле существует свойство РежимВыделения. Если оно установлено в значение Строка, то платформа выделяет всю строку целиком. Если же мы хотим работать с отдельными колонками, нам важно понимать следующее:
Ctrl) строка добавляется в коллекцию ВыделенныеСтроки, и ячейка окрашивается в стандартный цвет выделения (обычно темно-синий).Ctrl строка исключается из коллекции ВыделенныеСтроки. Визуально это выглядит так: синий фон исчезает, но вокруг ячейки остается пунктирная рамка, обозначающая, что ячейка остается «текущей» (активной).ПриАктивизацииЯчейки срабатывает при каждом перемещении фокуса, но его не всегда достаточно для отслеживания изменения состава выделенных строк, если фокус остается в одной и той же колонке.Самый надежный и простой в реализации способ — не пытаться «поймать» момент нажатия или отмены нажатия, а выполнять полный пересчет суммы по всем выделенным строкам при каждом срабатывании события ПриАктивизацииЯчейки. Поскольку платформа сама управляет составом коллекции ВыделенныеСтроки, нам достаточно просто прочитать актуальные данные.
Рассмотрим пример реализации. Предположим, наше табличное поле называется ДокументСписок, а сумма должна считаться для текущей активной колонки, если она является числовой.
Процедура ДокументСписокПриАктивизацииЯчейки(Элемент)
Перем СуммаВыделенных, ИмяТекущейКолонки, ТекущаяСтрокаСсылка;
СуммаВыделенных = 0;
// Определяем имя колонки, в которой находится пользователь
ИмяТекущейКолонки = Элемент.ТекущаяКолонка.Имя;
// Проверяем, входит ли колонка в список суммируемых (например, "СуммаДокумента" или "Всего")
Если ИмяТекущейКолонки = "СуммаДокумента" Или ИмяТекущейКолонки = "Оплачено" Тогда
// Обходим коллекцию строк, которые в данный момент выделены синим цветом
Для Каждого ТекущаяСтрокаСсылка Из Элемент.ВыделенныеСтроки Цикл
// Важный момент: работаем напрямую с данными объекта через ссылку,
// это гораздо быстрее, чем обращение к ОформлениеСтроки
СуммаВыделенных = СуммаВыделенных + ТекущаяСтрокаСсылка[ИмяТекущейКолонки];
КонецЦикла;
КонецЕсли;
// Выводим результат в надпись на форме или в кнопку панели инструментов
ЭлементыФормы.НадписьСумма.Заголовок = "Сумма: " + СуммаВыделенных;
КонецПроцедуры
Почему этот метод хорош? Он автоматически учитывает «отмену» выделения. Когда пользователь кликает по выделенной ячейке второй раз, строка пропадает из ВыделенныеСтроки, и при следующем выполнении цикла сумма уменьшится сама собой. Нам не нужно хранить промежуточные состояния.
Иногда возникают ситуации, когда требуется более сложная логика — например, если выделение строк и выделение ячеек должно работать независимо, или если мы имеем дело не с динамическим списком, а с табличной частью. В этом случае мы можем использовать объект Соответствие, чтобы хранить состояние каждой ячейки (нажата или нет).
Разберем, как реализовать этот механизм. В качестве ключа соответствия мы будем использовать комбинацию уникального идентификатора строки и имени колонки.
Шаг 1. Объявим переменную в модуле формы для хранения выделенных адресов.
Перем мВыделенныеЯчейки; // Тип: Соответствие
Шаг 2. В процедуре ПриОткрытии инициализируем ее.
Процедура ПриОткрытии()
мВыделенныеЯчейки = Новый Соответствие;
КонецПроцедуры
Шаг 3. Реализуем логику переключения в событии ПриАктивизацииЯчейки.
Процедура ДокументСписокПриАктивизацииЯчейки(Элемент)
Если Элемент.ТекущаяСтрока = Неопределено Тогда
Возврат;
КонецЕсли;
ИмяКолонки = Элемент.ТекущаяКолонка.Имя;
КлючЯчейки = Строка(Элемент.ТекущаяСтрока.Ссылка.УникальныйИдентификатор()) + "_" + ИмяКолонки;
// Проверяем, есть ли ячейка в нашем списке "активных"
Если мВыделенныеЯчейки.Получить(КлючЯчейки) = Неопределено Тогда
// Добавляем ячейку в список
мВыделенныеЯчейки.Вставить(КлючЯчейки, Элемент.ТекущаяСтрока[ИмяКолонки]);
Иначе
// Если уже была — удаляем (имитация снятия выделения)
мВыделенныеЯчейки.Удалить(КлючЯчейки);
КонецЕсли;
// Пересчитываем итоговую сумму по всему соответствию
Итог = 0;
Для Каждого Запись Из мВыделенныеЯчейки Цикл
Итог = Итог + Запись.Значение;
КонецЦикла;
ЭлементыФормы.ДействияФормы.Кнопки.Сумма.Текст = Формат(Итог, "ЧЦ=15; ЧДЦ=2");
КонецПроцедуры
Проанализируем ситуацию, когда в списке тысячи документов. Использование метода ОформлениеСтроки(Строка).Ячейки[ИмяТекущейКолонки].Текст, как это делал автор вопроса в Сообщении 5, является ресурсоемкой операцией. Метод ОформлениеСтроки заставляет платформу вычислять визуальные параметры, что значительно замедляет цикл при массовом выделении (например, через Ctrl+A).
Рекомендации для повышения скорости:
Строка.СуммаДокумента. Если Строка — это ссылка на документ, используйте обращение через точку, а лучше заранее получите данные в объект ТаблицаЗначений, если это возможно.ДокументСписок) оптимальнее всего использовать именно коллекцию ВыделенныеСтроки, так как она поддерживается платформой на уровне интерфейса.ПриВыводеСтроки, проверяя наличие ключа ячейки в вашем Соответствии.В Сообщении 5 упоминалось использование номера документа для идентификации ячейки. Выясним, почему это опасно: в 1С номера документов могут повторяться в разных периодах или иметь префиксы. Правильный подход — всегда использовать ссылку (объект Ссылка) или УникальныйИдентификатор(). Это гарантирует, что даже если у двух документов одинаковые номера, программа не перепутает их при расчете суммы.
Для решения задачи по отмене выделения ячейки и корректному пересчету суммы в обычных формах:
ПриАктивизацииЯчейки как основной триггер.ЭлементыФормы.ВашеПоле.ВыделенныеСтроки.Соответствие для хранения состояния каждой конкретной ячейки.Разработанные подходы позволят создать отзывчивый и точный интерфейс, который будет корректно реагировать на любые действия пользователя, включая сложные комбинации клавиш и повторные клики мышью.