Как реализовать вложенную таблицу внутри строки печатной формы 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке печатных форм в 1С часто возникает задача вывода данных со сложной структурой. Классический пример — основная таблица, в одной из строк которой должна располагаться другая таблица с произвольным количеством строк. Это создает определенные трудности, так как стандартный метод Вывести() просто добавляет новые строки одну за другой, что визуально разрывает ячейки основной строки, находящиеся слева или справа от вложенной таблицы.

В этой статье мы подробно разберем, как решить эту задачу, сохранив целостность макета и обеспечив корректное отображение границ. Мы проанализируем несколько подходов: от классического объединения ячеек до программного управления границами и использования временных документов.

Метод 1: Программное объединение ячеек (базовый подход)

Этот метод был признан наиболее эффективным в обсуждении. Суть заключается в том, что мы разбиваем вывод основной строки на несколько этапов и фиксируем номера строк, чтобы потом объединить "разорванные" ячейки. Рассмотрим алгоритм по шагам.

Для начала нам необходимо подготовить макет, разделив его на три ключевые области:

  1. ОбластьСтрокаОсновная — стандартная строка для данных без детализации.
  2. ОбластьЗаголовокВложенный — шапка для таблицы, которая будет внутри строки.
  3. ОбластьСтрокаВложенная — строка, которая будет тиражироваться во вложенной таблице.

Проанализируем процесс вывода в коде. Основная идея — запомнить номер строки начала вывода вложенных данных и номер строки окончания.


// Определяем переменные
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("МойМакет");

ОбластьДанные = Макет.ПолучитьОбласть("СтрокаОсновная");
ОбластьШапкаВложенная = Макет.ПолучитьОбласть("ЗаголовокВложенный");
ОбластьСтрокаВложенная = Макет.ПолучитьОбласть("СтрокаВложенная");

Для Каждого СтрокаИзДанных Из СписокДанных Цикл
    
    Если СтрокаИзДанных.ЕстьВложеннаяТаблица Тогда
        // 1. Запоминаем номер первой строки блока
        НомерНачала = ТабДок.ВысотаТаблицы + 1;
        
        // 2. Выводим шапку вложенной таблицы
        ЗаполнитьЗначенияСвойств(ОбластьШапкаВложенная.Параметры, СтрокаИзДанных);
        ТабДок.Вывести(ОбластьШапкаВложенная);
        
        // 3. Выводим строки вложенной таблицы в цикле
        Для Каждого СтрокаВнутренняя Из СтрокаИзДанных.ВнутренниеДанные Цикл
            ЗаполнитьЗначенияСвойств(ОбластьСтрокаВложенная.Параметры, СтрокаВнутренняя);
            ТабДок.Вывести(ОбластьСтрокаВложенная);
        КонецЦикла;
        
        // 4. Запоминаем номер последней строки блока
        НомерКонца = ТабДок.ВысотаТаблицы;
        
        // 5. Объединяем ячейки, которые должны быть общими для всего блока
        // Предположим, это колонки 1, 2 и 5
        ТабДок.Область(НомерНачала, 1, НомерКонца, 1).Объединить();
        ТабДок.Область(НомерНачала, 2, НомерКонца, 2).Объединить();
        ТабДок.Область(НомерНачала, 5, НомерКонца, 5).Объединить();
        
    Иначе
        // Обычный вывод без вложенности
        ЗаполнитьЗначенияСвойств(ОбластьДанные.Параметры, СтрокаИзДанных);
        ТабДок.Вывести(ОбластьДанные);
    КонецЕсли;
    
КонецЦикла;

Этот метод позволяет "растянуть" ячейки основной строки на всю высоту вложенной таблицы. Важный нюанс: метод Объединить() требует точного указания координат ячеек, поэтому использование ТабДок.ВысотаТаблицы является самым надежным способом определения границ.

Метод 2: Программное управление границами (решение проблемы "лишних линий")

Часто после объединения ячеек или просто при выводе нескольких областей подряд между ними остаются горизонтальные линии, которые визуально дробят основную строку. Чтобы создать эффект единого пространства, мы можем программно отключать границы.

Разберем, как использовать объект Линия. Мы можем создать невидимую линию и применить ее к нижней границе каждой строки вложенной таблицы, кроме последней.


ЛинияПустая = Новый Линия(ТипЛинииТабличногоДокумента.Нет);
ЛинияСплошная = Новый Линия(ТипЛинииТабличногоДокумента.Сплошная, 1);

ВсегоСтрок = СтрокаИзДанных.ВнутренниеДанные.Количество();
Счетчик = 0;

Для Каждого СтрокаВнутренняя Из СтрокаИзДанных.ВнутренниеДанные Цикл
    Счетчик = Счетчик + 1;
    Область = Макет.ПолучитьОбласть("СтрокаВложенная");
    ЗаполнитьЗначенияСвойств(Область.Параметры, СтрокаВнутренняя);
    
    // Если это не последняя строка вложенной таблицы, убираем нижнюю границу
    Если Счетчик < ВсегоСтрок Тогда
        Область.Область().ГраницаСнизу = ЛинияПустая;
    Иначе
        Область.Область().ГраницаСнизу = ЛинияСплошная;
    КонецЕсли;
    
    ТабДок.Вывести(Область);
КонецЦикла;

Такой подход позволяет избежать использования тяжелого метода Объединить(), что положительно сказывается на производительности при формировании очень больших отчетов.

Метод 3: Использование временного табличного документа (Оптимизация)

Рассмотрим ситуацию, когда вложенная таблица очень сложная. Вместо того чтобы выводить всё сразу в основной документ, мы можем подготовить "блок" во временном документе, а затем перенести его целиком. Это ускоряет работу, так как операции с маленьким документом в оперативной памяти выполняются быстрее.

Выясним преимущества этого метода:


ВременныйТабДок = Новый ТабличныйДокумент;
// Формируем вложенную структуру во ВременныйТабДок так же, как в методе 1
// ... (заполнение данными и объединение)

// Теперь выводим весь временный документ в основной
ТабДок.Вывести(ВременныйТабДок);

Метод 4: Метод "Скрытых колонок"

Если количество колонок во вложенной таблице фиксировано и их немного (например, не более 5), можно заранее предусмотреть их в основном макете. Если для текущей строки вложенные данные отсутствуют, мы просто скрываем эти колонки или выводим пустую область.

Проанализируем ситуацию: в макете создаются колонки "Дополнительно 1", "Дополнительно 2". В коде мы управляем свойством Видимость:


ОбластьКолонки = ТабДок.Область(, НомерКолонкиДеталей);
ОбластьКолонки.Видимость = Ложь; // Скрываем, если данных нет

Рекомендации по автоматической высоте строк

При динамическом объединении ячеек (как в методе 1) 1С иногда некорректно рассчитывает высоту строки, особенно если включен перенос текста. Чтобы текст не обрезался, рекомендуем после завершения формирования всего документа или конкретного блока использовать метод АвтоВысотаСтроки.

Рассмотрим пример команды: ТабДок.Область(1, 1, ТабДок.ВысотаТаблицы, ТабДок.ШиринаТаблицы).АвтоВысотаСтроки = Истина;

Заключение

Мы разобрали основные способы создания "таблицы в таблице" в печатных формах 1С. Наиболее гибким и проверенным является Метод 1 с программным объединением ячеек через вычисление координат ВысотаТаблицы. Если же вы стремитесь к максимальной производительности и чистоте визуального стиля, обратите внимание на Метод 2 (управление границами) и использование временных табличных документов.

Выбор конкретного решения зависит от сложности вашего макета и объема выводимых данных. Главное — всегда сохранять структуру макета в Областях, что позволит легко вносить изменения в дизайн без переписывания логики формирования отчета.

← На главную