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

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

При разработке отчетов и печатных форм в системе 1С:Предприятие программисты часто сталкиваются с необходимостью вывода данных, структура которых заранее неизвестна. Например, когда количество колонок в таблице зависит от результатов запроса или выбора пользователя. В таких случаях стандартное использование заранее нарисованного макета с фиксированными именованными областями становится неудобным или невозможным. Рассмотрим, как правильно подойти к решению этой задачи, отказавшись от устаревших методов адресации и научившись управлять табличным документом напрямую.

Различие между макетом и табличным документом

Для начала проанализируем фундаментальную разницу между объектами Макет и ТабличныйДокумент. Многие начинающие разработчики путают эти понятия. Макет — это шаблон, заготовка, в которой мы рисуем структуру будущего документа. ТабличныйДокумент — это сам результат, то, что видит пользователь на экране или получает на принтер.

Когда мы вызываем метод Макет.ПолучитьОбласть(), мы копируем «кусок» шаблона в память, чтобы затем вставить его в итоговый документ. Однако, если наша цель — создать таблицу полностью динамически, мы можем вообще не создавать макет в дереве метаданных, а работать напрямую с объектом ТабличныйДокумент, программно задавая текст, границы и шрифты для каждой ячейки.

Отказ от адресации R1C1 в пользу числовых индексов

Использование строк вида "R1C1:R2C2" для получения областей считается «магическими строками» и атавизмом. Это неудобно по нескольким причинам: необходимость постоянно «склеивать» строки в цикле, риск опечатки и низкая производительность, так как платформе требуется парсить строку для вычисления координат.

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

ТабДок.Область(НомерНачальнойСтроки, НомерНачальнойКолонки, НомерКонечнойСтроки, НомерКонечнойКолонки)

Такой подход позволяет легко использовать счетчики циклов. Проанализируем пример вывода шапки таблицы на основе колонок таблицы значений ТзРез:


// Создаем новый документ, если его нет на форме
ТабДок = Новый ТабличныйДокумент;

ИндексКолонки = 1;
Для Каждого Колонка Из ТзРез.Колонки Цикл
    // Обращаемся напрямую к ячейке по координатам (строка 1, текущая колонка)
    ТекущаяЯчейка = ТабДок.Область(1, ИндексКолонки);
    ТекущаяЯчейка.Текст = Колонка.Имя;
    
    // Сразу задаем оформление
    ТекущаяЯчейка.Рамка = Новый СистемнаяЛиния(ЛинияСоединенияТабличногоДокумента.Сплошная, 1);
    ТекущаяЯчейка.Шрифт = Новый Шрифт(ТекущаяЯчейка.Шрифт, , , Истина); // Жирный
    
    ИндексКолонки = ИндексКолонки + 1;
КонецЦикла;

Методы Вывести() и Присоединить(): как наращивать таблицу

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

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

Посмотрим на пример правильного комбинирования этих методов при выводе данных из таблицы значений:


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

Заполнение параметров и работа без них

Разберем ситуацию, когда в табличном документе нет заранее определенных параметров. Если вы работаете с областью, полученной из макета, где свойство Заполнение установлено в значение Параметр, то использование Область.Параметры.ИмяПараметра = Значение обязательно.

Однако, если вы строите документ динамически через метод Область(р1, к1, р2, к2), вам не нужны параметры. Вы напрямую меняете свойство Текст. Это значительно упрощает код, так как вам не нужно следить за именами параметров в макете. Проанализируем, как можно быстро заполнить область данными:


// Прямое заполнение текста без использования механизма параметров макета
ОбластьДанных = ТабДок.Область(НомерСтроки, НомерКолонки);
ОбластьДанных.Текст = Строка(ЗначениеИзЗапроса);
ОбластьДанных.ГоризонтальноеПоложение = ГоризонтальноеПоложение.Центр;

Программное форматирование «на лету»

При полном отказе от макета нам необходимо программно описывать внешний вид ячеек. Это требует больше строк кода, но дает абсолютную гибкость. Рассмотрим основные свойства, которые понадобятся для оформления динамического отчета:

Пример создания рамки для ячейки:


Сетка = Новый Линия(ТипЛинииТабличногоДокумента.Сплошная, 1);
Ячейка = ТабДок.Область(5, 5);
Ячейка.Обвести(Сетка, Сетка, Сетка, Сетка); // Лево, Верх, Право, Низ

Использование построителя или СКД как альтернатива

Если ваша задача — просто вывести результат произвольного запроса в красивую таблицу, стоит рассмотреть использование Системы компоновки данных (СКД) или Построителя отчета.

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

Таким образом, мы рассмотрели основные инструменты для динамической работы с таблицами. Помните: использование числовых индексов вместо R1C1 и грамотное сочетание Вывести/Присоединить — это ключ к созданию быстрых и надежных отчетов в 1С.

← На главную