При формировании печатных форм (ценников, этикеток, списков, бейджей или компактных реестров) часто возникает задача распределить информацию в две или более колонок на одном печатном листе. Типичный сценарий: заполнить левую половину листа сверху донизу, затем перейти на правую колонку того же листа, а после ее заполнения перейти на следующую страницу.
Однако в платформе 1С отсутствует встроенная верстка в виде «газетных колонок» с автоматическим перетеканием текста. Рассмотрим, как устроена механика формирования табличных документов, почему стандартный метод Присоединить() ведет себя неожиданным образом и как правильно реализовать вывод в две колонки.
Проанализируем распространенную ошибку: разработчик в цикле выводит всю левую колонку через ТабДок.Вывести(), а затем пытается добавить вторую колонку с помощью ТабДок.Присоединить(). В результате правая колонка выводится справа, но начинается не с первой строки документа, а с той строки, на которой завершился вывод левой колонки (то есть в самом низу).
Обратимся к синтаксису платформы. Метод Присоединить() помещает область в следующей колонке правее самой правой выведенной колонки, начиная со строки, с которой выводился предыдущий табличный документ. Таким образом, если левая колонка заняла 40 строк, попытка присоединить вторую область прикрепит ее начиная с 40-й строки, а не с 1-й.
Самый надежный и быстродействующий способ — формировать документ горизонтальными парами строк. Разберем по шагам, как организовать этот процесс:
ТабДок.Вывести(ОбластьЛево), затем сразу ТабДок.Присоединить(ОбластьПраво).ТабДок.ВывестиГоризонтальныйРазделительСтраниц().Посмотрим на пример программной реализации параллельного вывода фиксированного количества строк:
// Количество строк в одной колонке на странице
СтрокНаЛисте = 30;
ВсегоЭлементов = МассивДанных.Количество();
Индекс = 0;
Пока Индекс < ВсегоЭлементов Цикл
// Вычисляем границы порции для текущего листа
КоличествоНаЛист = Мин(СтрокНаЛисте * 2, ВсегоЭлементов - Индекс);
СтрокВКолонке = Окр(КоличествоНаЛист / 2, 0, РежимОкругления.ОкруглениеВверх);
Для НомерСтроки = 0 По СтрокВКолонке - 1 Цикл
ИндексЛевый = Индекс + НомерСтроки;
ИндексПравый = Индекс + СтрокВКолонке + НомерСтроки;
// Заполняем и выводим левую колонку
Если ИндексЛевый < ВсегоЭлементов Тогда
ОбластьЛевая.Параметры.Заполнить(МассивДанных[ИндексЛевый]);
ТабДок.Вывести(ОбластьЛевая);
КонецЕсли;
// Заполняем и присоединяем правую колонку
Если ИндексПравый < (Индекс + КоличествоНаЛист) И ИндексПравый < ВсегоЭлементов Тогда
ОбластьПравая.Параметры.Заполнить(МассивДанных[ИндексПравый]);
ТабДок.Присоединить(ОбластьПравая);
КонецЕсли;
КонецЦикла;
Индекс = Индекс + КоличествоНаЛист;
// Если данные еще остались, добавляем разделитель страниц
Если Индекс < ВсегоЭлементов Тогда
ТабДок.ВывестиГоризонтальныйРазделительСтраниц();
КонецЕсли;
КонецЦикла;
Если строки содержат многострочный текст и ячейки имеют переменную высоту (включено автораздвижение строк), мы не можем жестко зафиксировать количество строк на листе константой. В этом случае выясним высоту страницы программно:
ТабличныйДокумент с теми же параметрами печати (поля, ориентация, масштаб), что и основной.ТабДокВременный.ПроверитьВывод(МассивОбластей).Ложь, фиксируем, сколько строк поместилось по высоте листа.
МассивОбластей = Новый Массив;
МассивОбластей.Добавить(ОбластьСтроки);
// Проверка возможности размещения строки на текущем листе
Если Не ТабДокВременный.ПроверитьВывод(МассивОбластей) Тогда
// Достигнут конец страницы, выполняем перенос
КонецЕсли;
Если алгоритм построения макета требует сначала полностью сгенерировать левую часть таблицы, а затем перенести данные в правую половину, можно воспользоваться методом ВставитьОбласть():
ТабличныйДокумент.ТабДок.ВставитьОбласть(ОбластьИсточник, ОбластьПриемник, ТипСмещенияТабличногоДокумента.БезСмещения).Важное условие: размеры исходной области (ОбластьИсточник) и целевой области (ОбластьПриемник) по количеству строк и колонок должны строго совпадать, иначе платформа выдаст ошибку несовпадения выделенных блоков.
Присоединить() убедитесь, что высота ячеек в макете зафиксирована. Если левая ячейка растянется по высоте из-за длинного текста, а правая останется короткой, платформа автоматически растянет правую строку до высоты левой, сохраняя базовую линию.ПроверитьВывод() корректно работает только при наличии установленного принтера по умолчанию и графической подсистемы. На сервере 1С под управлением ОС Linux вызовы проверки печати рекомендуется оборачивать в блок Попытка ... Исключение во избежание сбоев формирования отчета.