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