Разработка отчетов в системе 1С:Предприятие 7.7 часто сталкивается с ограничениями платформы, которые в более современных версиях (например, 8.x) решаются одной командой. Одной из таких задач является вывод промежуточных итогов («Итого на странице» или «Перенос») в конце каждого печатного листа. В 1С 8.x для этого существует метод ПроверитьВывод(), однако в «семерке» разработчикам приходится прибегать к различным техническим ухищрениям. Рассмотрим подробнее основные способы решения этой задачи.
Проанализируем самый надежный, хотя и ресурсоемкий метод. Поскольку платформа 7.7 не умеет заранее предсказывать, поместится ли секция на текущий лист, мы можем создать «пробный» объект таблицы. Разберем этот процесс по шагам.
Суть заключается в использовании двух объектов типа Таблица. Первый объект — основной, который будет выведен на экран или принтер. Второй — вспомогательный (невидимый), на котором мы будем тренироваться.
Опции(), ПараметрыСтраницы().ВремТабл = СоздатьОбъект("Таблица"). Крайне важно, чтобы все настройки шрифтов, отступов и масштабирования у временной таблицы полностью совпадали с основной.КоличествоСтраниц().Посмотрим на пример реализации логики в коде:
// Создаем объекты
Таб = СоздатьОбъект("Таблица");
ВремТаб = СоздатьОбъект("Таблица");
// Обязательно копируем параметры страницы
ВремТаб.ПараметрыСтраницы(,,,,,);
ИтогоПоСтранице = 0;
ВыбратьСтроки();
Пока ПолучитьСтроку() = 1 Цикл
// Запоминаем текущее кол-во страниц
СтрДо = ВремТаб.КоличествоСтраниц();
// Пробный вывод секции строки
ВремТаб.ВывестиСекцию("Строка");
// Если после вывода строки количество страниц увеличилось
Если ВремТаб.КоличествоСтраниц() > СтрДо Тогда
// Сначала в основную таблицу выводим итог по старой странице
Таб.ВывестиСекцию("ИтогоПоСтранице");
Таб.НоваяСтраница();
// Очищаем временную таблицу для следующего листа (необязательно, но полезно для производительности)
// И сбрасываем счетчик суммы по странице
ИтогоПоСтранице = 0;
КонецЕсли;
// Выводим данные в основную таблицу
Таб.ВывестиСекцию("Строка");
ИтогоПоСтранице = ИтогоПоСтранице + Сумма;
КонецЦикла;
Выясним причину возможных «тормозов» при использовании этого метода. Каждое обращение к методу КоличествоСтраниц() заставляет систему пересчитывать геометрию всего документа, что на больших отчетах (более 100 листов) может приводить к заметным задержкам. Однако это единственный способ, учитывающий автоматический перенос строк по высоте.
Разберем альтернативный подход, который не требует создания второй таблицы. Метод ВысотаСекции() возвращает высоту указанной области в специальных единицах. Зная общую доступную высоту листа, мы можем математически вычислять момент перехода.
Для реализации этого метода нам необходимо экспериментальным путем определить «емкость» страницы. Выясним, сколько единиц высоты помещается на один лист А4 при заданных полях. Рассмотрим алгоритм:
МаксВысотаЛиста (например, 1000 единиц).ТекущаяВысота.ТекущаяВысота = ТекущаяВысота + Таб.ВысотаСекции("Строка").ТекущаяВысота и высоты секции подвала превышает МаксВысотаЛиста, выполняем перенос страницы.Проанализируем ситуацию с масштабированием: этот метод крайне чувствителен к настройке «По ширине листа». Если пользователь изменит масштаб печати или драйвер принтера будет иметь иные непечатные области, расчеты могут «поплыть». Поэтому данный метод рекомендуется использовать только при жестко заданных параметрах печати.
Как отмечается в сообщениях форума, во многих типовых конфигурациях (например, в «Бухгалтерии 7.7» для форм ТОРГ-12 или УПД) используется метод жесткой фиксации количества строк. Это самый простой и быстрый способ, хотя он не учитывает разную высоту строк (если в ячейках включен «перенос текста»).
Алгоритм работы прост:
СчетчикСтрок = 0;
СтрокНаСтранице = 25; // Определяется опытным путем
Пока ПолучитьСтроку() = 1 Цикл
Таб.ВывестиСекцию("Строка");
СчетчикСтрок = СчетчикСтрок + 1;
Если СчетчикСтрок >= СтрокНаСтранице Тогда
Таб.ВывестиСекцию("ПодвалСтраницы");
Таб.НоваяСтраница();
Таб.ВывестиСекцию("ЗаголовокТаблицы");
СчетчикСтрок = 0;
КонецЕсли;
КонецЦикла;
Для продвинутых разработчиков существует возможность использования внешней компоненты FormEx. Она расширяет возможности встроенного объекта Таблица, позволяя более точно управлять событиями при формировании печатных форм. С помощью неё можно минимизировать вычислительные затраты, характерные для метода с двумя таблицами, за счет более прямого доступа к атрибутам печатного листа.
При реализации итогов по страницам следует учитывать несколько критических моментов:
НижнийКолонтитул() в 7.7 позволяет выводить только фиксированные строки или простые шаблоны (номер страницы, дата). Он не может вычислять сумму по странице «на лету». Поэтому промежуточные итоги всегда выводятся через обычную секцию ВывестиСекцию() в теле отчета.Таб.Опции(0,0,0,0) и фиксированный масштаб Таб.ПараметрыСтраницы(,,,,,,100), если используете расчетные методы (Метод 2), чтобы избежать непредсказуемого поведения на разных компьютерах.Подведем итог: выбор метода зависит от сложности структуры отчета. Если высота строк всегда одинакова — используйте простой счетчик строк. Если текст в ячейках может переноситься — используйте эмуляцию через вспомогательную таблицу.