При формировании сложных печатных форм в 1С программисты часто сталкиваются с задачей, когда основной документ (шапка, табличная часть и подвал) уже выведен, но требуется добавить дополнительный блок (например, примечание, штамп или боковую панель) справа, причем начать этот вывод нужно не с текущей позиции «курсора», а с самого верха или от определенной строки. Стандартный метод Присоединить() не всегда ведет себя предсказуемо, особенно если области имеют разную высоту.
В этой статье мы подробно разберем, почему возникает смещение при выводе областей, как работает внутренний механизм позиционирования в ТабличныйДокумент и как правильно использовать метод ВставитьОбласть, чтобы избежать распространенных ошибок.
Прежде всего, проанализируем ситуацию. В 1С методы Вывести() и Присоединить() управляют невидимым указателем (курсором) вывода. Когда мы вызываем Вывести(), платформа добавляет область вниз и переносит курсор на следующую строку после выведенного блока. Когда мы вызываем Присоединить(), платформа пытается пристыковать область справа от последнего выведенного блока в тех же строках.
Основная сложность возникает, когда мы пытаемся «присоединить» область после того, как основной документ уже сформирован. В этом случае «последней выведенной областью» считается «Подвал». Следовательно, метод Присоединить() начнет вывод вашего «Примечание» именно на уровне подвала, а не шапки.
Если же мы попробуем вывести «Шапку», а затем сразу «Присоединить» к ней «Примечание», то возникнет другая проблема: последующий вызов Вывести() для строк основной таблицы начнется не под шапкой, а под самым нижним краем присоединенного «Примечания». Если примечание длинное, в таблице образуется огромная пустая дыра.
Рассмотрим наиболее гибкий и профессиональный способ — метод ВставитьОбласть(). В отличие от стандартного вывода, этот метод позволяет буквально «наложить» одну область на другую в произвольные координаты документа. Это решает проблему привязки к «курсору» вывода.
Однако при использовании этого метода часто возникает ошибка: «Выделение не соответствует вставляемому блоку». Выясним причину этой ошибки. Она возникает, если вы пытаетесь вставить область в заранее определенный диапазон, который по размеру (количеству строк или колонок) отличается от исходного блока в макете. Также ошибку могут вызывать объединенные ячейки.
Чтобы избежать ошибок, рекомендуем указывать в качестве целевого диапазона не всю область, а только одну верхнюю левую ячейку. Посмотрим на пример кода:
// Получаем нужные области из макета
ОбластьМакетаПримечание = Макет.ПолучитьОбласть("Примечание");
// Определяем координату, с которой должно начинаться примечание.
// Например, мы хотим вставить его в 1-ю строку, 5-ю колонку.
ЦелеваяЯчейка = ТабДок.Область(1, 5);
// Вставляем область. 1С сама расширит документ вправо и вниз.
ТабДок.ВставитьОбласть(ОбластьМакетаПримечание, ЦелеваяЯчейка);
Важный нюанс: метод ВставитьОбласть имеет третий параметр ТипСмещения. Если вы хотите, чтобы при вставке существующие ячейки не раздвигались (не уезжали вправо или вниз), убедитесь, что вы правильно выбрали параметры смещения. Обычно при вставке в пустую правую часть документа проблем не возникает.
Рассмотрим ситуацию, когда примечание должно выводиться динамически вместе со строками основной части. В этом случае мы можем применить алгоритм из сообщения №3 форума — построчный вывод. Это требует более сложной логики в цикле, но гарантирует идеальное выравнивание.
Суть метода заключается в том, что мы не выводим примечание целиком, а выводим его по одной строке, присоединяя к каждой строке основной таблицы. Проанализируем пример реализации:
// Предположим, у нас есть массив строк данных
Для Каждого СтрокаДанных Из СписокСтрок Цикл
// Выводим основную строку данных
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ОбластьСтрока.Параметры.Заполнить(СтрокаДанных);
ТабДок.Вывести(ОбластьСтрока);
// Сразу же присоединяем соответствующую строку примечания
// (Если примечание длиннее, нужно предусмотреть проверку границ)
ОбластьПримСтрока = Макет.ПолучитьОбласть("Примечание|СтрокаПрим");
ТабДок.Присоединить(ОбластьПримСтрока);
КонецЦикла;
Этот способ хорош тем, что подвал документа всегда будет начинаться строго под самым длинным блоком (либо под основной таблицей, либо под примечанием), не создавая лишних пустот.
Иногда «Примечание» — это не строго табличные данные, а некий текстовый блок, который должен располагаться сбоку, как штамп. В 1С ТабличныйДокумент позволяет использовать объекты типа Рисунок. Рисунки не привязаны к сетке ячеек так жестко, как области, и «парят» над документом.
Посмотрим, как программно добавить такое примечание:
Рисунок в табличном документе.ТипРисункаТабличногоДокумента.Текст.Расположить) или через абсолютные координаты.Такой подход гарантирует, что никакие манипуляции с основным текстом (добавление строк, изменение высоты) не «сломают» верстку вашего примечания, так как оно позиционируется независимо.
Выясним причины, по которым метод ВставитьОбласть может продолжать выдавать ошибку, даже если координаты указаны верно:
R1C1:R1C2), то при вставке в целевой области не должно быть пересекающихся старых объединений.ВставитьОбласть ширина колонок в целевом документе может не совпасть с макетом. Возможно, после вставки потребуется вызвать метод АвтоМаксимальнаяШирина() или вручную задать ШиринаКолонки.ПолучитьОбласть(). Если область пустая, метод вставки может вести себя некорректно.Подводя итог, можно сказать: для простого добавления блока сбоку лучше всего подходит ВставитьОбласть() с указанием одной ячейки-ориентира. Для сложных отчетов, где высота примечания должна синхронизироваться с данными, используйте построчный вывод через Присоединить() в цикле.