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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Проанализируем доступные варианты решения этой задачи: от использования готовых механизмов Библиотеки стандартных подсистем (БСП) до написания собственного алгоритма обхода ячеек с учетом производительности клиентского приложения.

Способ 1. Вывод отчета через типовую форму печати БСП

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

Посмотрим на пример процедуры открытия такой формы из модуля формы внешнего отчета:


Процедура ПечатьДокументов(КоллекцияПечатныхФорм, Знач ОбъектыПечати = Неопределено, ВладелецФормы = Неопределено) Экспорт
    
    Если ОбъектыПечати = Неопределено Тогда
        ОбъектыПечати = Новый СписокЗначений;
    КонецЕсли;
    
    КлючУникальности = Строка(Новый УникальныйИдентификатор);
    
    ПараметрыОткрытия = Новый Структура("ИмяМенеджераПечати,ИменаМакетов,ПараметрКоманды,ПараметрыПечати");
    ПараметрыОткрытия.ПараметрКоманды = Новый Массив;
    ПараметрыОткрытия.ПараметрыПечати = Новый Структура;
    ПараметрыОткрытия.Вставить("КоллекцияПечатныхФорм", КоллекцияПечатныхФорм);
    ПараметрыОткрытия.Вставить("ОбъектыПечати", ОбъектыПечати);
    
    ОткрытьФорму("ОбщаяФорма.ПечатьДокументов", ПараметрыОткрытия, ВладелецФормы, КлючУникальности);
    
КонецПроцедуры

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

Способ 2. Использование готовых расчетных методов БСП

Если отчет обязательно должен отображаться на вашей собственной управляемой форме, писать математический алгоритм с нуля также не требуется. В базовой функциональности БСП предусмотрена готовая экспортная функция расчета показателей:

Функция ОбщегоНазначенияКлиентСервер.РасчетныеПоказателиЯчеек(ТабличныйДокумент, ВыделенныеОбласти, ПараметрыРасчета) (в зависимости от версии БСП может находиться в модуле ОбщегоНазначенияСлужебныйКлиентСервер) принимает табличный документ и коллекцию ВыделенныеОбласти. На выходе она возвращает структуру со значениями:

  1. Сумма — сумма всех числовых ячеек;
  2. Количество — общее количество выделенных ячеек;
  3. КоличествоЧисловых — число ячеек, содержащих корректные числа;
  4. КоличествоНеПустых — ячейки с заполненными значениями;
  5. Среднее, Минимум и Максимум.

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

Способ 3. Самостоятельная реализация через событие ПриАктивизацииОбласти

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

Для элемента формы с типом ПолеТабличногоДокумента необходимо назначить обработчик события ПриАктивизацииОбласти. Каждое изменение выделения ячеек будет вызывать этот обработчик, внутри которого мы обращаемся к коллекции Элементы.ТабличныйДокумент.ВыделенныеОбласти.

При ручной реализации обязательно нужно учитывать технические ограничения платформы:

  1. Зависание при выделении всей таблицы или колонок целиком. Если пользователь нажмет Ctrl + A или кликнет по заголовку строки/колонки, координаты области (свойства Низ и Право) могут вернуть максимальные пределы листа. Попытка обойти миллион пустых строк во вложенных циклах намертво подвесит клиент. Поэтому границы обхода необходимо принудительно ограничивать реальными габаритами документа: Мин(Область.Низ, Элементы.ТабличныйДокумент.ВысотаТаблицы) и Мин(Область.Право, Элементы.ТабличныйДокумент.ШиринаТаблицы). Если количество обрабатываемых ячеек превышает разумный порог (например, 10 000), расчет следует прерывать с предупреждением.
  2. Пересекающиеся области. При выделении нескольких блоков ячеек с зажатой клавишей Ctrl прямоугольные диапазоны могут перекрывать друг друга. Чтобы число не суммировалось повторно, координаты каждой ячейки (строку и колонку) необходимо регистрировать в объекте Соответствие.
  3. Чтение значений и форматирование текста. Если ячейка формировалась со свойством СодержитЗначение = Истина, число считывается напрямую из свойства Значение. Если ячейка содержит обычную строку, считывается свойство Текст. Строку необходимо предварительно очищать от неразрывных пробелов Символы.НПП и стандартных разделителей триад, после чего безопасно преобразовывать в число через блок Попытка ... Исключение или ОписаниеТипов("Число").

Посмотрим на практический пример функции расчета суммы для модуля формы:


&НаКлиенте
Процедура ТабличныйДокументПриАктивизацииОбласти(Элемент)
    
    СуммаВыделения = 0;
    УникальныеЯчейки = Новый Соответствие;
    
    МаксСтрока = Элемент.ВысотаТаблицы;
    МаксКолонка = Элемент.ШиринаТаблицы;
    
    Для Каждого Область Из Элемент.ВыделенныеОбласти Цикл
        
        Если ТипЗнч(Область) <> Тип("ОбластьЯчеекТабличногоДокумента") Тогда
            Продолжить;
        КонецЕсли;
        
        Верх = Область.Верх;
        Низ = Мин(Область.Низ, МаксСтрока);
        Лево = Область.Лево;
        Право = Мин(Область.Право, МаксКолонка);
        
        // Защита от зависания при чрезмерно большом выделении
        Если (Низ - Верх + 1) * (Право - Лево + 1) > 10000 Тогда
            СуммаВыделения = 0;
            Прервать;
        КонецЕсли;
        
        Для НомерСтроки = Верх По Низ Цикл
            Для НомерКолонки = Лево По Право Цикл
                
                ИндексЯчейки = Формат(НомерСтроки, "ЧГ=0") + "_" + Формат(НомерКолонки, "ЧГ=0");
                Если УникальныеЯчейки[ИндексЯчейки] <> Неопределено Тогда
                    Продолжить;
                КонецЕсли;
                
                УникальныеЯчейки.Вставить(ИндексЯчейки, Истина);
                ТекущаяЯчейка = Элемент.Область(НомерСтроки, НомерКолонки);
                
                Если ТекущаяЯчейка.СодержитЗначение И ТипЗнч(ТекущаяЯчейка.Значение) = Тип("Число") Тогда
                    СуммаВыделения = СуммаВыделения + ТекущаяЯчейка.Значение;
                Иначе
                    ТекстЧисла = СтрЗаменить(ТекущаяЯчейка.Текст, Символы.НПП, "");
                    ТекстЧисла = СтрЗаменить(ТекстЧисла, " ", "");
                    Попытка
                        ЧисловоеЗначение = Число(ТекстЧисла);
                        СуммаВыделения = СуммаВыделения + ЧисловоеЗначение;
                    Исключение
                        // Ячейка не содержит преобразуемого числа
                    КонецПопытки;
                КонецЕсли;
                
            КонецЦикла;
        КонецЦикла;
        
    КонецЦикла;
    
    // Выводим полученное значение в реквизит формы
    Элементы.ПолеНадписьСумма.Заголовок = "Сумма: " + Формат(СуммаВыделения, "ЧДЦ=2; ЧГ=3,0");
    
КонецПроцедуры

Для обеспечения максимальной отзывчивости интерфейса при протягивании рамки выделения мышью расчет можно вызывать не мгновенно, а с небольшой задержкой (0.1–0.2 секунды) через метод ПодключитьОбработчикОжидания(), отменяя предыдущий отложенный вызов.

Штатная альтернатива платформы без изменения конфигурации

Стоит отметить, что в платформе «1С:Предприятие» предусмотрен встроенный способ подсчета суммы чисел в табличном документе без написания кода:

  1. Пользователь открывает системный Калькулятор через главное меню платформы.
  2. В табличном документе выделяется произвольный диапазон числовых ячеек.
  3. При нажатии на калькуляторе кнопки добавления в память (M+ или клавиши M) сумма всех чисел из выделенных ячеек автоматически помещается в буфер калькулятора.

Этот прием позволяет быстро складывать данные отчетов в любой базе без необходимости дорабатывать формы программным кодом.

← На главную