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