Как реализовать расчет суммы в выделенных ячейках табличного поля и обработать отмену выделения

Программист 1С v8.3 (Обычные формы)
← На главную

В разработке на платформе 1С:Предприятие 8.х (особенно в режиме обычных форм) часто возникает задача интерактивного взаимодействия с пользователем через табличное поле. Одной из таких задач является автоматический расчет суммы выделенных числовых значений, как это реализовано в Excel. Однако при работе с ДокументСписок или стандартным табличным полем программисты сталкиваются с тем, что платформа не предоставляет прямой коллекции «выделенных ячеек». Вместо этого она оперирует выделенными строками, что создает трудности при попытке отследить повторный клик по ячейке для отмены ее выбора.

В этой статье мы подробно разберем, как правильно организовать алгоритм суммирования, как обрабатывать визуальное изменение состояния ячейки (переход из темно-синего цвета в белый с пунктиром) и какие методы 1С помогут сделать этот процесс эффективным.

Анализ стандартного поведения табличного поля

Для начала проанализируем, что происходит на уровне платформы, когда пользователь взаимодействует с ячейками. В обычных формах у элемента ТабличноеПоле существует свойство РежимВыделения. Если оно установлено в значение Строка, то платформа выделяет всю строку целиком. Если же мы хотим работать с отдельными колонками, нам важно понимать следующее:

  1. При первом нажатии на ячейку (особенно с зажатой клавишей Ctrl) строка добавляется в коллекцию ВыделенныеСтроки, и ячейка окрашивается в стандартный цвет выделения (обычно темно-синий).
  2. При повторном нажатии на ту же самую ячейку с Ctrl строка исключается из коллекции ВыделенныеСтроки. Визуально это выглядит так: синий фон исчезает, но вокруг ячейки остается пунктирная рамка, обозначающая, что ячейка остается «текущей» (активной).
  3. Событие ПриАктивизацииЯчейки срабатывает при каждом перемещении фокуса, но его не всегда достаточно для отслеживания изменения состава выделенных строк, если фокус остается в одной и той же колонке.

Способ 1. Полный пересчет по коллекции ВыделенныеСтроки (Рекомендуемый)

Самый надежный и простой в реализации способ — не пытаться «поймать» момент нажатия или отмены нажатия, а выполнять полный пересчет суммы по всем выделенным строкам при каждом срабатывании события ПриАктивизацииЯчейки. Поскольку платформа сама управляет составом коллекции ВыделенныеСтроки, нам достаточно просто прочитать актуальные данные.

Рассмотрим пример реализации. Предположим, наше табличное поле называется ДокументСписок, а сумма должна считаться для текущей активной колонки, если она является числовой.


Процедура ДокументСписокПриАктивизацииЯчейки(Элемент)
    
    Перем СуммаВыделенных, ИмяТекущейКолонки, ТекущаяСтрокаСсылка;
    
    СуммаВыделенных = 0;
    
    // Определяем имя колонки, в которой находится пользователь
    ИмяТекущейКолонки = Элемент.ТекущаяКолонка.Имя;
    
    // Проверяем, входит ли колонка в список суммируемых (например, "СуммаДокумента" или "Всего")
    Если ИмяТекущейКолонки = "СуммаДокумента" Или ИмяТекущейКолонки = "Оплачено" Тогда
        
        // Обходим коллекцию строк, которые в данный момент выделены синим цветом
        Для Каждого ТекущаяСтрокаСсылка Из Элемент.ВыделенныеСтроки Цикл
            
            // Важный момент: работаем напрямую с данными объекта через ссылку,
            // это гораздо быстрее, чем обращение к ОформлениеСтроки
            СуммаВыделенных = СуммаВыделенных + ТекущаяСтрокаСсылка[ИмяТекущейКолонки];
            
        КонецЦикла;
        
    КонецЕсли;
    
    // Выводим результат в надпись на форме или в кнопку панели инструментов
    ЭлементыФормы.НадписьСумма.Заголовок = "Сумма: " + СуммаВыделенных;
    
КонецПроцедуры

Почему этот метод хорош? Он автоматически учитывает «отмену» выделения. Когда пользователь кликает по выделенной ячейке второй раз, строка пропадает из ВыделенныеСтроки, и при следующем выполнении цикла сумма уменьшится сама собой. Нам не нужно хранить промежуточные состояния.

Способ 2. Использование соответствия (Selection Tracker) для сложных случаев

Иногда возникают ситуации, когда требуется более сложная логика — например, если выделение строк и выделение ячеек должно работать независимо, или если мы имеем дело не с динамическим списком, а с табличной частью. В этом случае мы можем использовать объект Соответствие, чтобы хранить состояние каждой ячейки (нажата или нет).

Разберем, как реализовать этот механизм. В качестве ключа соответствия мы будем использовать комбинацию уникального идентификатора строки и имени колонки.

Шаг 1. Объявим переменную в модуле формы для хранения выделенных адресов.

Перем мВыделенныеЯчейки; // Тип: Соответствие

Шаг 2. В процедуре ПриОткрытии инициализируем ее.


Процедура ПриОткрытии()
    мВыделенныеЯчейки = Новый Соответствие;
КонецПроцедуры

Шаг 3. Реализуем логику переключения в событии ПриАктивизацииЯчейки.


Процедура ДокументСписокПриАктивизацииЯчейки(Элемент)
    
    Если Элемент.ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    ИмяКолонки = Элемент.ТекущаяКолонка.Имя;
    КлючЯчейки = Строка(Элемент.ТекущаяСтрока.Ссылка.УникальныйИдентификатор()) + "_" + ИмяКолонки;
    
    // Проверяем, есть ли ячейка в нашем списке "активных"
    Если мВыделенныеЯчейки.Получить(КлючЯчейки) = Неопределено Тогда
        // Добавляем ячейку в список
        мВыделенныеЯчейки.Вставить(КлючЯчейки, Элемент.ТекущаяСтрока[ИмяКолонки]);
    Иначе
        // Если уже была — удаляем (имитация снятия выделения)
        мВыделенныеЯчейки.Удалить(КлючЯчейки);
    КонецЕсли;
    
    // Пересчитываем итоговую сумму по всему соответствию
    Итог = 0;
    Для Каждого Запись Из мВыделенныеЯчейки Цикл
        Итог = Итог + Запись.Значение;
    КонецЦикла;
    
    ЭлементыФормы.ДействияФормы.Кнопки.Сумма.Текст = Формат(Итог, "ЧЦ=15; ЧДЦ=2");
    
КонецПроцедуры

Тонкости производительности и оптимизации

Проанализируем ситуацию, когда в списке тысячи документов. Использование метода ОформлениеСтроки(Строка).Ячейки[ИмяТекущейКолонки].Текст, как это делал автор вопроса в Сообщении 5, является ресурсоемкой операцией. Метод ОформлениеСтроки заставляет платформу вычислять визуальные параметры, что значительно замедляет цикл при массовом выделении (например, через Ctrl+A).

Рекомендации для повышения скорости:

Почему идентификация по номеру документа — плохая идея?

В Сообщении 5 упоминалось использование номера документа для идентификации ячейки. Выясним, почему это опасно: в 1С номера документов могут повторяться в разных периодах или иметь префиксы. Правильный подход — всегда использовать ссылку (объект Ссылка) или УникальныйИдентификатор(). Это гарантирует, что даже если у двух документов одинаковые номера, программа не перепутает их при расчете суммы.

Резюме

Для решения задачи по отмене выделения ячейки и корректному пересчету суммы в обычных формах:

  1. Используйте событие ПриАктивизацииЯчейки как основной триггер.
  2. Опирайтесь на системную коллекцию ЭлементыФормы.ВашеПоле.ВыделенныеСтроки.
  3. Для получения значений используйте обращение к реквизитам объекта через ссылку, а не через визуальное оформление ячейки.
  4. Если штатного механизма выделения строк недостаточно, внедряйте объект Соответствие для хранения состояния каждой конкретной ячейки.

Разработанные подходы позволят создать отзывчивый и точный интерфейс, который будет корректно реагировать на любые действия пользователя, включая сложные комбинации клавиш и повторные клики мышью.

← На главную