При формировании печатных форм в системе 1С:Предприятие разработчики часто сталкиваются с эстетической и технической проблемой: необходимо объединить в один ТабличныйДокумент две части, которые имеют принципиально разную структуру колонок. Типичный пример — статический заголовок с фиксированным набором реквизитов и динамическая кросс-таблица, количество колонок в которой зависит от периода или набора данных.
Стандартная проблема заключается в том, что при использовании свойства АвтоМасштаб система рассчитывает коэффициент сжатия по самой широкой части документа. В результате более узкая часть (например, заголовок) визуально «сжимается» вместе с основной таблицей и перестает доходить до правого края листа, образуя некрасивый пустой отступ. Разберем, как добиться того, чтобы правые края обеих таблиц идеально совпадали при печати.
Прежде чем переходить к расчетам, нам необходимо разобраться, как 1С управляет сеткой колонок. По умолчанию, если вы просто выводите одну область за другой в ТабличныйДокумент, изменение ширины колонки №1 в первой строке автоматически изменит ширину колонки №1 во всем документе. Чтобы этого избежать, используется важнейший метод СоздатьФорматСтрок.
Проанализируем ситуацию: когда мы вызываем этот метод для конкретной области или строки, 1С «отвязывает» геометрию колонок этой строки от остального документа. Это позволяет нам задать для заголовка 3 широкие колонки, а для табличной части — 15 узких, и они не будут влиять друг на друга. Рассмотрим правильный порядок вывода:
// Выводим первую часть (например, заголовок)
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ТабДок.Вывести(ОбластьЗаголовок);
// Фиксируем формат строк для уже выведенной части
ТабДок.Область(1, , ТабДок.ВысотаТаблицы).СоздатьФорматСтрок();
// Выводим вторую часть (таблицу)
ОбластьДанные = Макет.ПолучитьОбласть("СтрокаТаблицы");
ТабДок.Вывести(ОбластьДанные);
// Снова фиксируем формат строк для новой части, чтобы она была независимой
ТабДок.Область(СтараяВысота + 1, , ТабДок.ВысотаТаблицы).СоздатьФорматСтрок();
Даже если мы разделили форматы строк, автоматическое выравнивание по правому краю не произойдет само собой. Нам нужно вычислить суммарную ширину «эталонной» области (той, которая шире или должна быть основной) и программно «растянуть» или «сжать» колонки второй области, чтобы их суммы совпали. Рассмотрим пошаговый алгоритм решения этой задачи.
Шаг 1: Определение эталонной ширины. Выясним, какая ширина в единицах 1С является целевой. Обычно это ширина заголовка, если он занимает всю ширину листа, или ширина максимально заполненной табличной части.
Шаг 2: Расчет текущей ширины изменяемой области. Суммируем ширину всех колонок области, которую нужно подогнать.
Шаг 3: Распределение разницы. Разберем пример кода, который пропорционально распределяет «недостающую» ширину между колонками таблицы, чтобы правый край совпал с заголовком:
// Предположим, ШиринаЗаголовка нам известна (например, 120 единиц)
ШиринаДокументаЦелевая = ШиринаКолонкиЗаголовка * КоличествоКолонокЗаголовка;
// Теперь работаем с колонками таблицы, которые мы уже вывели и занесли в массив
// МассивКолонокТаблицы содержит объекты типа ОбластьЯчеекТабличногоДокумента
КоличествоКолонокТаблицы = МассивКолонокТаблицы.Количество();
ТекущаяСуммарнаяШирина = 0;
// Сначала узнаем текущую ширину
Для Каждого ТекущаяКолонка Из МассивКолонокТаблицы Цикл
ТекущаяСуммарнаяШирина = ТекущаяСуммарнаяШирина + ТекущаяКолонка.ШиринаКолонки;
КонецЦикла;
// Вычисляем разницу и распределяем её
Разница = ШиринаДокументаЦелевая - ТекущаяСуммарнаяШирина;
Для Индекс = 0 По КоличествоКолонокТаблицы - 1 Цикл
ОсталосьКолонок = КоличествоКолонокТаблицы - Индекс;
// Добавочная ширина для текущей колонки
Добавка = Окр(Разница / ОсталосьКолонок, 2);
ТекущаяКолонка = МассивКолонокТаблицы[Индекс];
ТекущаяКолонка.ШиринаКолонки = ТекущаяКолонка.ШиринаКолонки + Добавка;
Разница = Разница - Добавка;
КонецЦикла;
В данном примере мы используем постепенное уменьшение остатка (переменная Разница), что позволяет избежать погрешностей округления, из-за которых правый край может не сойтись на доли миллиметра.
Проанализируем более простой, но не менее эффективный способ. Если нам не критично, чтобы все колонки таблицы были строго одинаковыми, мы можем добавить в макет (или создавать программно) одну дополнительную колонку в самом конце каждой области.
МаксШирина - ТекущаяШиринаБлока.Этот метод гарантирует, что визуально все строки будут заканчиваться в одной точке по горизонтали, при этом основное содержимое не будет искажаться из-за пересчета ширин.
Посмотрим на ситуацию со стороны свойств самого ТабличногоДокумента. Важно помнить, что если вы программно меняете ширину ячеек, делать это нужно после того, как область присоединена к результирующему документу. Выясним причину: при методе Присоединить() или Вывести() 1С может переопределять свойства ячеек, если не задан индивидуальный формат строк. Поэтому алгоритм всегда должен быть таким:
Вывод области -> СоздатьФорматСтрок -> Изменение ширины колонок.
Проанализируем технические ограничения, которые могут возникнуть при реализации данных методов:
АвтоМасштаб. При изменении ширины колонок размер шрифта остается прежним. Если вы сильно сужаете колонки, текст может перестать в них помещаться (появятся «решетки» или текст обрежется).Если задача требует, чтобы заголовок был, например, в портретной ориентации, а таблица под ним — в альбомной (или с разным уровнем сжатия АвтоМасштаб), стандартный ТабличныйДокумент не сможет этого сделать в рамках одного печатного задания. В таких исключительных случаях рассмотрим вариант с сохранением каждой части в отдельный временный PDF-файл и последующим их объединением внешними средствами. Однако для 99% задач описанные выше методы с СоздатьФорматСтрок и программным пересчетом ширины являются исчерпывающими.
Таким образом, комбинируя разделение форматов строк и точный расчет суммарной ширины, мы получаем полный контроль над геометрией печатной формы, обеспечивая профессиональный вид документов независимо от сложности их структуры.