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

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

В процессе сопровождения и развития конфигураций на платформе «1С:Предприятие 8.3» (особенно таких крупных типовых решений, как УТ 11, КА 2 или ERP) часто возникает задача расширения функционала стандартных форм списков. Например, пользователям бывает необходимо быстро узнать, на какую общую сумму проведено документов в текущем списке с учетом установленных фильтров (организация, период, контрагент) или по ручной выборке строк.

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

---

Вариант 1. Использование встроенных возможностей платформы (без программирования)

Прежде чем приступать к написанию программного кода, рассмотрим инструменты платформы, которые уже доступны пользователям «из коробки» и не требуют доработки системы.

Метод 1. Использование встроенного калькулятора и буфера памяти (M+)

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

  1. Откройте нужную форму списка документов (например, заявки на оплату) и настройте стандартные отборы.
  2. Установите курсор (выделите ячейку) в колонке Сумма. Это принципиальный момент — суммирование всегда происходит по активной колонке табличного поля.
  3. Выделите строки, по которым нужно подвести итог. Для выделения всех строк используйте стандартную комбинацию клавиш Ctrl + A, для выборочного выделения удерживайте клавишу Ctrl.
  4. Нажмите кнопку M+ (или кнопку вызова калькулятора) на панели инструментов или через главное меню: «Сервис и настройки» -> «Калькулятор».
  5. В поле памяти калькулятора отобразится итоговая сумма всех выделенных документов.

Метод 2. Использование команды «Вывести список»

Еще один быстрый способ подсчета, аналогичный работе в Excel:

  1. В форме списка нажмите меню Еще -> Вывести список.
  2. В появившемся окне оставьте флажок только напротив колонки Сумма (и других необходимых вам реквизитов) и нажмите «ОК».
  3. Программа сформирует табличный документ. Выделите мышкой ячейки с суммами — в правом нижнем углу экрана платформы автоматически отобразится их сумма (штатный механизм автосуммы).

---

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

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

Разберем, как это работает. В БСП существует встроенный механизм, который сканирует зарегистрированные внешние обработки. Если внешняя обработка содержит в процедуре СведенияОВнешнейОбработке() указание на использование в качестве заполнения объекта или отчета для определенного типа документов, БСП автоматически выведет команду вызова этой обработки в меню «Еще» или в специальное подменю («Отчеты», «Заполнение») формы списка.

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

---

Вариант 3. Разработка через расширение конфигурации

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

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

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

Правильный путь: программное изменение формы в расширении

Чтобы избежать проблем с обновлениями, мы заимствуем не саму форму списка, а общий модуль конфигурации, отвечающий за переопределение интерфейса, или используем перехватчик события создания формы. В типовой линейке решений (УТ, КА, ERP) для этого отлично подходит общий модуль МодификацияКонфигурацииПереопределяемый.

Разберем по шагам реализацию этого метода.

Шаг 1. Создание расширения и заимствование модуля

Создадим новое расширение конфигурации. Заимствуем в него общий модуль МодификацияКонфигурацииПереопределяемый. В этом модуле найдем процедуру ПриСозданииНаСервере и добавим к ней аннотацию &После.

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


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

Шаг 2. Использование параметризуемой общей команды в расширении

Для того чтобы не писать сложные перехватчики клиентских событий формы списка, можно использовать механизм Общих команд в расширении. Это наиболее элегантный и простой способ добавления кнопки в формы списков:

  1. В созданном расширении добавьте новый объект метаданных: Общая команда.
  2. В свойствах созданной команды укажите свойство Тип параметра команды. Выберите тип ссылки нужного вам документа (например, ДокументСсылка.ЗаявкаНаРасходДенежныхСредств).
  3. Установите свойство Режим использования параметра в значение Множественный. Это позволит команде работать со списком выделенных строк.
  4. В поле Группа выберите, где должна отображаться команда на форме (например, Панель тестирования или командная панель формы). Платформа автоматически разместит эту кнопку на форме списка указанного документа!

Теперь опишем алгоритм выполнения этой общей команды в ее модуле:


&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
    
    // ПараметрКоманды содержит массив ссылок на выделенные в списке документы
    Если ПараметрКоманды.Количество() = 0 Тогда
        ПоказатьПредупреждение(, "Не выделено ни одного документа!");
        Возврат;
    КонецЕсли;
    
    // Передаем массив выделенных документов на сервер для быстрого расчета суммы
    ИтоговаяСумма = ПолучитьСуммуДокументовНаСервере(ПараметрКоманды);
    
    // Выводим результат пользователю
    ШаблонТекста = "Общая сумма выделенных документов (%1 шт.) составляет: %2 руб.";
    ТекстСообщения = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонТекста, ПараметрКоманды.Количество(), ИтоговаяСумма);
    ПоказатьПредупреждение(, ТекстСообщения);
    
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьСуммуДокументовНаСервере(МассивДокументов)
    
    // Выполняем один быстрый запрос к СУБД для подсчета суммы по массиву ссылок
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |	ЕСТЬNULL(СУММА(Заявка.СуммаДокумента), 0) КАК ИтоговаяСумма
        |ИЗ
        |	Документ.ЗаявкаНаРасходДенежныхСредств КАК Заявка
        |ГДЕ
        |	Заявка.Ссылка В(&МассивДокументов)";
        
    Запрос.УстановитьПараметр("МассивДокументов", МассивДокументов);
    
    Выборка = Запрос.Выполнить().Выбрать();
    Если Выборка.Следующий() Тогда
        Возврат Выборка.ИтоговаяСумма;
    КонецЕсли;
    
    Возврат 0;
    
КонецФункции

---

Вариант 4. Расчет суммы всего списка с учетом текущих отборов пользователя

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

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

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


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

Этот код позволяет мгновенно получать точные итоговые показатели по любым выборкам, независимо от количества документов в базе данных, используя всю мощь СУБД для агрегатных расчетов.

---

Резюме и рекомендации

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

← На главную