При разработке печатных форм в системе 1С:Предприятие программисты часто сталкиваются с ограничением: ячейка табличного документа является атомарной сущностью. Это означает, что мы не можем просто «вставить» одну ячейку внутрь другой. Однако бизнес-задачи часто требуют отображения иерархических данных, например, когда в одной строке основного отчета (в одной из колонок) должен быть представлен список связанных подстрок. Рассмотрим подробнее, какими методами можно добиться эффекта «таблицы в ячейке», от простых приемов с текстом до сложных манипуляций с объектами макета.
Этот метод считается классическим и наиболее надежным для печатных форм. Вместо того чтобы пытаться расширить одну ячейку, мы разбиваем вывод на несколько строк макета. Разберем этот процесс по шагам.
Представим, что у нас есть три колонки: «Товар», «Склад» и «Серийные номера». Серийных номеров может быть много. Мы создаем в макете область строки, где для первой и второй колонки задаем границы только сверху и снизу (или объединяем их позже), а для третьей — стандартную сетку.
Проанализируем пример кода для реализации такого вывода:
// Получаем макет и области
Макет = ПолучитьМакет("Макет");
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ТабДок = Новый ТабличныйДокумент;
Для Каждого ТекущийТовар Из СписокТоваров Цикл
// Заполняем основные данные
ОбластьСтрока.Параметры.Товар = ТекущийТовар.Наименование;
ОбластьСтрока.Параметры.Склад = ТекущийТовар.Склад;
ПерваяСтрокаГруппы = ТабДок.ВысотаТаблицы + 1;
// Выводим вложенную «таблицу» (список серийных номеров)
Для Каждого Серия Из ТекущийТовар.СерийныеНомера Цикл
ОбластьСтрока.Параметры.СерийныйНомер = Серия.Номер;
ТабДок.Вывести(ОбластьСтрока);
// Очищаем параметры для следующих итераций внутри группы,
// чтобы визуально данные не дублировались, если мы не используем объединение
ОбластьСтрока.Параметры.Товар = "";
ОбластьСтрока.Параметры.Склад = "";
КонецЦикла;
ПоследняяСтрокаГруппы = ТабДок.ВысотаТаблицы;
// Программно объединяем ячейки первой и второй колонки для создания эффекта одной большой ячейки
Если ПоследняяСтрокаГруппы > ПерваяСтрокаГруппы Тогда
ОбластьДляОбъединения1 = ТабДок.Область(ПерваяСтрокаГруппы, 1, ПоследняяСтрокаГруппы, 1);
ОбластьДляОбъединения1.Объединить();
ОбластьДляОбъединения2 = ТабДок.Область(ПерваяСтрокаГруппы, 2, ПоследняяСтрокаГруппы, 2);
ОбластьДляОбъединения2.Объединить();
КонецЕсли;
КонецЦикла;
Использование метода Объединить() позволяет динамически связывать ячейки в левой части таблицы, пока в правой части выводятся детальные записи. Это создает безупречный визуальный вид вложенности.
Если структура вложенных данных достаточно проста (например, просто список строк без сложного форматирования колонок внутри), можно использовать метод формирования одной большой строки текста. Выясним причину популярности этого метода: он требует минимального количества кода и манипуляций с макетом.
Для реализации этого подхода в макете необходимо для целевой ячейки установить свойство «Размещение текста» в значение «Переносить». Рассмотрим, как программно подготовить данные:
ТекстДляЯчейки = "";
Для Каждого ЭлементСписка Из КоллекцияДанных Цикл
Если ЗначениеЗаполнено(ТекстДляЯчейки) Тогда
ТекстДляЯчейки = ТекстДляЯчейки + Символы.ПС; // Добавляем перевод строки
КонецЕсли;
ТекстДляЯчейки = ТекстДляЯчейки + ЭлементСписка.Наименование;
КонецЦикла;
Область.Параметры.МногострочноеПоле = ТекстДляЯчейки;
ТабДок.Вывести(Область);
Основная проблема этого метода, как было замечено в обсуждении, — отсутствие внутренних границ (линий) между строками. Посмотрим, как это можно обойти:
Courier New), это будет выглядеть вполне аккуратно.Рисунки табличного документа можно наложить прямые линии поверх ячейки, рассчитав их координаты.Это продвинутый способ, который позволяет вставить в ячейку (точнее, в область ячейки) полноценную независимую таблицу. В 1С:Предприятии существует возможность добавления рисунков с типом ТипРисункаТабличногоДокумента.Объект.
Разберем алгоритм реализации:
ТабличныйДокумент (назовем его «ВложеннаяТаблица»).Пример программной реализации:
// 1. Формируем внутреннюю таблицу
ВнутреннийТабДок = Новый ТабличныйДокумент;
ОбластьВнутренняя = МакетВложенный.ПолучитьОбласть("Данные");
// ... заполнение ВнутреннийТабДок в цикле ...
// 2. Вставляем её как рисунок в основной документ
Рисунок = ТабДок.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Объект);
Рисунок.Объект = ВнутреннийТабДок;
Рисунок.РазмернаяСтратегия = СтратегияРазмераРисункаТабличногоДокумента.АвтоРазмер;
// 3. Позиционируем рисунок над нужной ячейкой
НужнаяОбласть = ТабДок.Область(НомерСтроки, НомерКолонки);
Рисунок.Расположить(НужнаяОбласть);
Важный нюанс: Этот метод идеально подходит для экранных форм, но при печати вложенные объекты могут вести себя непредсказуемо (например, масштабироваться иначе, чем основная сетка). Поэтому всегда проверяйте результат методом ПроверитьВывод().
Если ваша печатная форма предназначена в первую очередь для отображения в интерфейсе (управляемые формы), можно воспользоваться свойством ячейки «Содержит HTML». Посмотрим на этот подход: мы можем сконструировать полноценную HTML-таблицу со всеми необходимыми стилями CSS и передать её в параметр ячейки.
Рассмотрим пример формирования строки:
СтрокаHTML = "<table style='width:100%; border-collapse: collapse;' border='1'>";
Для Каждого Стр Из Данные Цикл
СтрокаHTML = СтрокаHTML + "<tr><td>" + Стр.Значение + "</td></tr>";
КонецЦикла;
СтрокаHTML = СтрокаHTML + "</table>";
Область.Параметры.ЯчейкаHTML = СтрокаHTML;
Этот метод дает максимальную гибкость в оформлении внутренних границ и отступов, недоступную стандартным средствам макета 1С.
Проанализируем ситуацию, когда пользователю нужно именно визуальное сходство с таблицей. Если вы выбрали метод вывода строк в цикле (Метод 1), важно правильно управлять свойством ГраницаСверху, ГраницаСнизу и ГраницаСлева/Справа.
Совет: Чтобы избежать «толстых» линий при объединении ячеек, устанавливайте границы не для всей области сразу, а точечно. Например, для первой строки вложенного списка рисуйте верхнюю границу, а для всех последующих — только нижнюю. Это позволит сохранить единую толщину сетки по всему документу.
В заключение отметим, что выбор метода зависит от сложности структуры данных. Для простых списков достаточно переноса строк с разделителями (Метод 2), для классических отчетов с группировками лучше всего подходит программное объединение областей (Метод 1), а для сложной верстки — вложенные объекты или HTML.