Как программно вывести две таблицы с разным количеством строк слева и справа в 1С

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

При формировании печатных форм или отчетов в 1С часто возникает задача вывести две таблицы «бок о бок» (по горизонтали), чтобы сравнить показатели. Например, слева необходимо отобразить статьи движения денежных средств (ДДС) и суммы по нашей организации, а справа — аналогичные данные по клиенту. При этом количество строк в левой и правой таблицах почти никогда не совпадает.

Если решать эту задачу «в лоб» — сначала вывести в цикле всю левую таблицу через метод Вывести(), а затем в отдельном цикле попытаться пристыковать правую таблицу через метод Присоединить() — результат окажется некорректным. Правая таблица начнется не с первой строки документа, а прикрепится к самой последней выведенной строке левой таблицы. Выясним, почему так происходит, и подробно разберем правильные способы решения этой задачи.

Почему стандартный последовательный вывод не работает?

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

Когда мы полностью выводим левую таблицу (например, из 10 строк), курсор вывода в табличном документе смещается на 10-ю строку. При вызове первого же метода Присоединить() для правой таблицы платформа присоединит её область именно к 10-й строке, уйдя вправо. В итоге правая таблица «уползет» далеко вниз, нарушив всю структуру отчета.

Рассмотрим два надежных и профессиональных способа обхода этого ограничения.

---

Способ 1. Синхронный вывод в одном цикле (по максимальному числу строк)

Этот алгоритм заключается в том, что мы объединяем вывод обеих таблиц в один общий цикл. Количество итераций этого цикла должно быть равно максимальному числу строк среди обеих таблиц. На каждой итерации мы проверяем, есть ли данные для левой и правой частей, и при необходимости выводим пустые «заглушки», чтобы сохранить структуру строк.

Разберем этот метод по шагам на практическом примере:


// Предположим, у нас есть две таблицы значений: ТаблицаЛево и ТаблицаПраво
МаксСтрок = Макс(ТаблицаЛево.Количество(), ТаблицаПраво.Количество());

ОблЛево = Макет.ПолучитьОбласть("ТелоТаблицы|ДляНас");
ОблПраво = Макет.ПолучитьОбласть("ТелоТаблицы|ДляКлиента");

// Нам также понадобятся пустые области (без параметров), чтобы не нарушать сетку,
// если одна из таблиц закончится раньше другой.
ОблЛевоПустая = Макет.ПолучитьОбласть("ТелоТаблицыПустая|ДляНас");
ОблПравоПустая = Макет.ПолучитьОбласть("ТелоТаблицыПустая|ДляКлиента");

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

Важный нюанс: обязательно создайте в макете области ТелоТаблицыПустая|ДляНас и ТелоТаблицыПустая|ДляКлиента. Они должны полностью повторять размеры (высоту строк и ширину колонок) основных рабочих областей, но не содержать параметров. Если просто пропускать вывод левой части, то метод Присоединить() для правой части выведет данные в первую (левую) колонку документа, и структура полностью сломается.

---

Способ 2. Объединение независимых табличных документов через ВставитьОбласть()

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

Этот способ избавляет от необходимости писать сложные условия в циклах и выводить пустые области-пустышки. Мы работаем с каждой таблицей так, как будто она одна на листе.

Рассмотрим подробнее реализацию этого метода:


// 1. Создаем временный документ для левой таблицы и заполняем его
ТабДокЛево = Новый ТабличныйДокумент;
ОблЛево = Макет.ПолучитьОбласть("ТелоТаблицы|ДляНас");

Для Каждого Стр Из ТаблицаЛево Цикл
    ОблЛево.Параметры.Заполнить(Стр);
    ТабДокЛево.Вывести(ОблЛево);
КонецЦикла;

// 2. Создаем временный документ для правой таблицы и заполняем его
ТабДокПраво = Новый ТабличныйДокумент;
ОблПраво = Макет.ПолучитьОбласть("ТелоТаблицы|ДляКлиента");

Для Каждого Стр Из ТаблицаПраво Цикл
    ОблПраво.Параметры.Заполнить(Стр);
    ТабДокПраво.Вывести(ОблПраво);
КонецЦикла;

// 3. Выводим левую таблицу в финальный документ
ТабличныйДокумент.Вывести(ТабДокЛево);

// 4. Вживляем правую таблицу в финальный документ со сдвигом вправо.
// Определяем область-приемник: первая строка, колонка сразу за левой таблицей.
КолонкаНачала = ТабДокЛево.ШиринаТаблицы + 1;
ОбластьПриемник = ТабличныйДокумент.Область(1, КолонкаНачала);

// Копируем всю заполненную область правой таблицы в результирующий документ
ТабличныйДокумент.ВставитьОбласть(ТабДокПраво.Область(), ОбластьПриемник);

Использование метода ВставитьОбласть() гарантирует, что правая таблица начнется ровно с первой строки и аккуратно расположится справа от левой таблицы, независимо от того, сколько строк в каждой из них.

---

Как решить проблему «разъезжания» колонок?

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

Чтобы избежать искажения внешнего вида ячеек, воспользуемся следующими рекомендациями:

  1. Метод СоздатьФорматСтрок(). Если вы используете Способ 2 (объединение документов), после вставки областей примените метод СоздатьФорматСтрок() к результирующему документу. Это заставит 1С рассчитывать ширину колонок индивидуально для каждой строки, не деформируя общую структуру.
  2. Принцип «мелкой сетки». При проектировании макета сделайте множество узких колонок (например, шириной 3–5 единиц). Ваши реальные колонки «Статья ДДС» и «Сумма» формируйте путем горизонтального объединения нескольких мелких ячеек макета. Это позволит гибко регулировать ширину левой и правой таблиц независимо друг от друга.

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

← На главную