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