При разработке сложных документов в 1С часто возникает задача вывести сводную информацию по нескольким табличным частям в удобном для пользователя виде. Например, когда в документе есть таблицы Приход, Расход и ПрочиеПриходы, бухгалтеру или менеджеру важно видеть итоговый результат (сальдо) прямо в шапке или подвале формы, не складывая цифры в уме. В этой статье мы подробно разберем, как реализовать автоматический пересчет таких итогов и отобразить их с помощью текстовой декорации или поля надписи.
Прежде чем приступать к написанию кода, проанализируем, каким образом лучше отобразить итоговую строку. У нас есть два основных варианта: использование элемента формы типа Декорация-надпись или использование Реквизита формы с видом Поле надписи.
Разберем, почему второй вариант (Реквизит формы) часто предпочтительнее:
Поле надписи, и визуально оно не будет отличаться от обычной текстовой декорации.Для начала создадим реквизит формы (не путать с реквизитом объекта!) с именем ТекстИтога и типом Строка (длина неограничена). Перетащим его на форму в нужное место и в свойствах установим Вид — Поле надписи.
Наиболее простой и надежный способ получить итог по колонке табличной части — использовать встроенный метод Итог(). Однако стоит помнить, что этот метод доступен только на сервере. Рассмотрим структуру процедуры, которая будет собирать данные из всех табличных частей.
Проанализируем пример кода для модуля формы:
&НаСервере
Процедура РассчитатьИтогиНаСервере()
// Получаем итоги по каждой табличной части
// Предполагаем, что в ТЧ есть числовая колонка "Сумма"
ИтогПриход = Объект.Приход.Итог("Сумма");
ИтогРасход = Объект.Расход.Итог("Сумма");
ИтогПрочие = Объект.ПрочиеПриходы.Итог("Сумма");
// Вычисляем общий результат по формуле
ОбщийРезультат = ИтогПриход + ИтогПрочие - ИтогРасход;
// Формируем красивую строку для пользователя
// Используем функцию Формат для разделения разрядов и фиксации копеек
СтрокаПрихода = Формат(ИтогПриход, "ЧДЦ=2; ЧГ=3,0");
СтрокаРасхода = Формат(ИтогРасход, "ЧДЦ=2; ЧГ=3,0");
СтрокаИтога = Формат(ОбщийРезультат, "ЧДЦ=2; ЧГ=3,0");
// Присваиваем результат реквизиту формы
ТекстИтога = "Приход: " + СтрокаПрихода + " | Расход: " + СтрокаРасхода + " | ИТОГО: " + СтрокаИтога;
КонецПроцедуры
В данном коде мы используем объект Объект, который обращается к данным документа. Метод Итог("Сумма") быстро суммирует все строки таблицы по указанному полю. Обратите внимание на использование функции Формат(): параметр ЧГ=3,0 позволяет группировать тысячи, что делает числа (например, 1 000 000.00 вместо 1000000) гораздо более читаемыми.
Теперь выясним, в какие моменты должен происходить пересчет. Если мы напишем код только в ПриСозданииНаСервере, то при изменении чисел в таблице пользователем итог останется старым. Чтобы цифры "ожили", нам нужно подключить обработчики событий.
Рассмотрим основные точки вызова:
Таблица есть событие ПриИзменении. Оно срабатывает при добавлении, удалении или окончании редактирования любой строки.Пример подключения обработчика для таблицы:
&НаКлиенте
Процедура ПриходПриИзменении(Элемент)
// Вызываем серверный метод для пересчета
РассчитатьИтогиНаСервере();
КонецПроцедуры
&НаКлиенте
Процедура РасходПриИзменении(Элемент)
РассчитатьИтогиНаСервере();
КонецПроцедуры
Важный нюанс: если табличные части содержат сотни строк, частые серверные вызовы могут привести к "подтормаживанию" интерфейса. В таких случаях рассмотрим оптимизацию.
Если мы хотим избежать постоянных серверных вызовов при каждом изменении строки, мы можем реализовать обход коллекции ДанныеФормыКоллекция прямо на клиенте. Хотя у этой коллекции нет метода Итог(), мы можем использовать цикл.
Разберем пример клиентского расчета:
&НаКлиенте
Функция ПолучитьИтогТЧНаКлиенте(ИмяТЧ)
Результат = 0;
Для Каждого СтрокаТЧ Из Объект[ИмяТЧ] Цикл
Результат = Результат + СтрокаТЧ.Сумма;
КонецЦикла;
Возврат Результат;
КонецФункции
&НаКлиенте
Процедура ПересчитатьНаКлиенте()
СуммаП = ПолучитьИтогТЧНаКлиенте("Приход");
СуммаР = ПолучитьИтогТЧНаКлиенте("Расход");
// Обновляем реквизит формы напрямую
Общий = СуммаП - СуммаР;
ТекстИтога = "Итог: " + Формат(Общий, "ЧДЦ=2");
КонецПроцедуры
Такой подход работает мгновенно, так как данные уже находятся в памяти клиента. Однако помните, что если в таблице есть скрытые строки или сложные правила видимости данных, серверный Итог() будет надежнее.
Чтобы сделать интерфейс профессиональным, проанализируем ситуацию, когда итог должен менять цвет. Например, если расход превышает приход, сумма должна становиться красной. Для этого используется объект ФорматированнаяСтрока.
Рассмотрим, как это реализовать:
&НаСервере
Процедура ОбновитьКрасивыйИтог()
Итог = Объект.Приход.Итог("Сумма") - Объект.Расход.Итог("Сумма");
ЦветТекста = ?(Итог < 0, WebЦвета.Красный, WebЦвета.Зеленый);
ШрифтТекста = Новый Шрифт(,,Истина); // Жирный шрифт
// Создаем форматированную строку
ТекстДляВывода = Новый ФорматированнаяСтрока("ИТОГОВЫЙ БАЛАНС: ", , , , );
ЗначениеСуммы = Новый ФорматированнаяСтрока(Формат(Итог, "ЧДЦ=2"), ШрифтТекста, ЦветТекста);
// Соединяем части
Элементы.ТекстИтога.Заголовок = Новый ФорматированнаяСтрока(ТекстДляВывода, ЗначениеСуммы);
КонецПроцедуры
Обратите внимание: для работы с ФорматированнаяСтрока у элемента формы должен быть установлен вид Декорация-надпись, так как обычные реквизиты типа Строка не хранят информацию о цвете отдельных слов.
Проанализировав все способы, составим оптимальный алгоритм действий для программиста:
Декорацию-надпись с именем ДекорацияИтог.ОбновитьИтоги() в модуле формы с директивой &НаСервере.Объект.ТЧ.Итог("Поле").Элементы.ДекорацияИтог.Заголовок.ПриИзменении для каждой из ваших табличных частей (на клиенте), внутри которых вызывайте вашу серверную процедуру пересчета.ПриОткрытии или ПриЧтенииНаСервере, чтобы пользователь увидел цифры сразу при входе в документ.Используя эти методы, вы создадите отзывчивый и понятный интерфейс, который минимизирует ошибки ручного счета и сделает работу в программе 1С более комфортной.