При разработке сложных отчетов и печатных форм в среде 1С часто возникает задача динамического формирования структуры документа. Одной из типичных проблем является определение точных координат ячейки (адреса в формате RxxCxx), в которую будет выведена область методом Присоединить() или Вывести(). Это необходимо для того, чтобы предварительно настроить параметры области или внести изменения в уже выведенную структуру. В данной статье мы подробно разберем несколько стратегий решения этой задачи, проанализируем механизмы работы табличного документа и научимся эффективно управлять его содержимым.
Проанализируем самый простой и интуитивно понятный способ — обращение к текущему состоянию табличного документа. Прежде чем вызвать метод вывода, мы можем узнать, сколько строк и колонок уже заполнено. Для этого используются свойства ВысотаТаблицы и ШиринаТаблицы.
Рассмотрим логику: если мы собираемся вызвать метод Вывести(), то новая область по умолчанию встанет в начало следующей строки. Следовательно, номер строки будет равен ТабДок.ВысотаТаблицы + 1. Если же мы используем метод Присоединить(), область добавится справа в ту же строку, и её начальная колонка будет соответствовать значению ТабДок.ШиринаТаблицы + 1.
Посмотрим на пример кода:
// Определяем координаты будущей вставки
НоваяСтрока = ТабДок.ВысотаТаблицы + 1;
НоваяКолонка = ТабДок.ШиринаТаблицы + 1;
// Теперь мы можем заранее получить область по этим координатам
БудущаяОбласть = ТабДок.Область(НоваяСтрока, НоваяКолонка, НоваяСтрока, НоваяКолонка);
// Установим параметры или формат
БудущаяОбласть.ЦветТекста = ЦветаСтиля.ОсобыйТекст;
Разберем важную особенность встроенного языка: методы Вывести() и Присоединить() возвращают объект типа ОбластьЯчеекТабличногоДокумента. Многие программисты забывают об этом, используя методы просто как процедуры. Однако этот возвращаемый объект содержит актуальные координаты области, которые она заняла в итоговом документе.
Выясним, как это работает на практике. Сразу после выполнения метода мы можем обратиться к свойствам Верх, Низ, Лево и Право полученного объекта. Это позволяет узнать точное местоположение и, при необходимости, изменить текст или параметры в этой области уже после вывода, что решает задачу автора темы.
// Присоединяем область и сохраняем ссылку на результат
ВыведеннаяОбласть = ТабДок.Присоединить(ОбластьМакета);
// Теперь нам известны точные координаты
НомерСтроки = ВыведеннаяОбласть.Верх;
НомерКолонки = ВыведеннаяОбласть.Лево;
// Мы можем изменить значение прямо в выведенной ячейке
ВыведеннаяОбласть.Текст = "Новое значение";
// Или обратиться к параметру, если он был задан в макете
ВыведеннаяОбласть.Параметры.Сумма = 1000;
Проанализируем более сложную ситуацию, упомянутую в обсуждении: когда нам нужно выводить данные в конкретную колонку, заголовок которой был сформирован динамически. Вместо того чтобы каждый раз искать координаты ячейки «на лету», мы применим профессиональный подход с предварительной индексацией.
Разберем по шагам реализацию этого метода:
Соответствие для хранения связи между именем (или заголовком) колонки и её номером.Присоединить(), будем записывать номер текущей колонки в наше соответствие.Рассмотрим пример реализации:
// 1. Подготовка структуры колонок
КолонкиОтчета = Новый Соответствие;
Для Каждого ТекКолонка Из СписокДинамическихКолонок Цикл
ОблШапки = Макет.ПолучитьОбласть("Шапка|ДинамическаяКолонка");
ОблШапки.Параметры.Заголовок = ТекКолонка.Имя;
ВыведеннаяОбласть = ТабДок.Присоединить(ОблШапки);
// Запоминаем индекс колонки
КолонкиОтчета.Вставить(ТекКолонка.Имя, ВыведеннаяОбласть.Лево);
КонецЦикла;
// 2. Вывод данных
Пока Выборка.Следующий() Цикл
ТабДок.Вывести(ОбластьСтрокаНачало); // Выводим начало строки
ТекущаяСтрока = ТабДок.ВысотаТаблицы;
Для Каждого ДанныеКолонки Из Выборка.ДопДанные Цикл
НомерКол = КолонкиОтчета.Получить(ДанныеКолонки.Ключ);
Если НомерКол <> Неопределено Тогда
// Обращаемся напрямую к ячейке по координатам
Ячейка = ТабДок.Область(ТекущаяСтрока, НомерКол);
Ячейка.Текст = ДанныеКолонки.Значение;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Посмотрим на альтернативное решение, предложенное в сообщении №4. В некоторых случаях логика компоновки настолько сложна, что проще «проиграть» вывод в невидимый (тестовый) табличный документ. Мы выводим область в тестовый документ, проверяем, куда она «встала», выполняем необходимые расчеты или проверки (например, ПроверитьВывод()), а затем повторяем действие в основном документе с уже известными параметрами.
Этот метод особенно полезен, когда нужно заранее знать, поместится ли область по ширине страницы или не произойдет ли нежелательного разрыва страницы по вертикали.
Проанализируем еще одну возможность. Если в макете задать имена не только областям (строкам/колонкам), но и конкретным ячейкам, то после вывода всей строки (например, методом Вывести()) вы можете обращаться к вложенным ячейкам по их именам. Это избавляет от необходимости вычислять RxxCxx вручную.
Пример обращения к именованной ячейке внутри выведенной области:
// Выводим строку целиком
ОбластьСтрока = ТабДок.Вывести(Макет.ПолучитьОбласть("Строка"));
// Обращаемся к ячейке "СуммаИтого", которая находится внутри этой области
// При этом неважно, в какой именно колонке она находится физически
ОбластьСтрока.Область("СуммаИтого").Текст = "Заполнено по имени";
Подводя итог нашему анализу, можно выделить следующие рекомендации по работе с координатами в ТабличномДокументе:
Вывести() и Присоединить(). Это самый быстрый и надежный способ получить доступ к только что созданной области.НайтиТекст() в цикле значительно замедлит формирование отчета.Текст, Значение и Параметр доступны для записи в любой момент.ШиринаТаблицы и ВысотаТаблицы для контроля границ документа, но учитывайте, что эти свойства возвращают границы уже заполненных ячеек.Рассмотренные подходы позволяют гибко управлять формированием печатных форм любой сложности, минимизируя ошибки ручного вычисления координат и делая код более читаемым и поддерживаемым.