При динамическом формировании отчетов, печатных форм и макетов в 1С:Предприятии разработчики часто сталкиваются с необходимостью изменить границы ранее созданной именованной области табличного документа. Например, когда область была изначально задана для строк с 1 по 10, но в процессе вывода данных табличный документ увеличился, и область требуется «растянуть» до конца таблицы.
На первый взгляд задача кажется тривиальной, но простые интуитивные решения часто приводят к ошибкам или игнорируются платформой. В рамках этой статьи мы подробно разберем, почему стандартные подходы не работают, изучим внутренние механизмы платформы 1С и реализуем правильный, стабильный алгоритм изменения границ и имен областей ячеек.
Рассмотрим типичную ошибку начинающих разработчиков. Попытка напрямую изменить свойства, отвечающие за границы области ячеек, не увенчается успехом:
// Попытка изменить координаты напрямую (вызовет ошибку)
Область = ТабДок.Области["Документ_1"];
Область.Низ = ТабДок.ВысотаТаблицы; // Ошибка: Свойство доступно только для чтения!
В объекте ОбластьЯчеекТабличногоДокумента свойства, определяющие границы диапазона ячеек — Верх, Низ, Лево и Право — доступны строго только для чтения. Платформа 1С:Предприятие принципиально не позволяет изменять геометрические размеры уже существующего объекта области напрямую.
Вторая сложность заключается в уникальности имен. В рамках одного табличного документа имена областей должны быть строго уникальными. Если вы попытаетесь создать новую область с нужными координатами и присвоить ей уже существующее имя, платформа проигнорирует это действие:
// Этот код не изменит существующую область "Документ_1"
НоваяОбласть = ТабДок.Область(1, , ТабДок.ВысотаТаблицы, );
НоваяОбласть.Имя = "Документ_1"; // Платформа проигнорирует это присвоение, имя останется у старой области
При этом платформа не выдает ошибку выполнения, что часто путает разработчиков. Имя просто молча остается за старым диапазоном ячеек. Примечательно и то, что коллекция именованных областей табличного документа (доступная через свойство Области) не имеет метода Удалить(). Мы не можем просто удалить старую область из коллекции, чтобы освободить ее имя.
Чтобы обойти системные ограничения платформы и успешно переопределить границы области, нам необходимо выполнить три простых шага:
Имя пустую строку (""). При этом область физически теряет свое имя, удаляется из коллекции именованных областей, но сами ячейки и данные в табличном документе остаются нетронутыми.Проанализируем программный код, реализующий данный алгоритм:
// Выясним причину неработающего кода и исправим его по шагам
// Шаг 1: Получаем ссылку на старую область и "обнуляем" ее имя
СтараяОбласть = РезТаб.Области["Документ_1"];
СтараяОбласть.Имя = ""; // Имя "Документ_1" теперь свободно!
// Шаг 2: Создаем новую область ячеек с расширенными границами (от 1 строки до конца таблицы)
НовыеКоординатыВерх = 1;
НовыеКоординатыНиз = РезТаб.ВысотаТаблицы;
НоваяОбласть = РезТаб.Область(НовыеКоординатыВерх, , НовыеКоординатыНиз, );
// Шаг 3: Назначаем освобожденное имя новой области
НоваяОбласть.Имя = "Документ_1";
В процессе работы с табличными документами разработчики часто путают два ключевых метода: ПолучитьОбласть() и Область(). Понимание разницы между ними критически важно для корректной работы с метаданными макетов.
ТабличныйДокумент. Этот объект является изолированным фрагментом. Если вы попытаетесь изменить свойства областей внутри него, вы измените лишь локальную копию, но никак не повлияете на исходный документ.ОбластьЯчеекТабличногоДокумента, который является прямой ссылкой на диапазон ячеек внутри исходного табличного документа. Любые манипуляции со свойствами этого объекта (изменение шрифта, цвета, текста или имени) мгновенно отражаются на исходном документе.Рассмотрим пример ошибочного использования, с которым часто сталкиваются на практике:
// ОШИБОЧНЫЙ ПОДХОД:
ЛокальнаяКопия = РезТаб.ПолучитьОбласть("Документ_1"); // Возвращает новый ТабличныйДокумент
ЛокальнаяКопия.Области.Документ_1.Имя = "Документ_2"; // Изменения произойдут только внутри копии, исходный РезТаб не изменится!
// ПРАВИЛЬНЫЙ ПОДХОД:
СсылкаНаОбласть = РезТаб.Область("Документ_1"); // Возвращает прямую ссылку на ячейки исходного документа
СсылкаНаОбласть.Имя = "Документ_2"; // Имя успешно изменено в исходном документе РезТаб!
Иногда разработчики пытаются очистить имя области, используя метод табличного документа УдалитьОбласть(). Это грубая ошибка, которая может полностью разрушить верстку и структуру вашего отчета.
Метод УдалитьОбласть() предназначен не для удаления имени из коллекции, а для физического удаления ячеек с их последующим смещением вверх или влево. Применение этого метода приведет к тому, что строки или колонки внутри указанного диапазона будут безвозвратно удалены из структуры таблицы, нарушая вывод всех последующих секций макета. Для изменения имени или границ области используйте исключительно способ с присвоением имени пустой строки (Имя = "").
Для удобства использования в реальных проектах рекомендуется оформить данную логику в виде универсальной процедуры. Рассмотрим пример такой реализации, которую вы можете добавить в общий модуль своей конфигурации:
// Процедура переопределяет границы существующей именованной области
// или создает её, если она ранее не существовала.
//
// Параметры:
// ТабДок - ТабличныйДокумент - целевой табличный документ
// ИмяОбласти - Строка - имя изменяемой области
// НомерСтрокиВерх - Число - новая верхняя граница
// НомерКолонкиЛев - Число - новая левая граница
// НомерСтрокиНиз - Число - новая нижняя граница
// НомерКолонкиПрав- Число - новая правая граница
//
Процедура ПереопределитьГраницыОбласти(ТабДок, ИмяОбласти, НомерСтрокиВерх = Неопределено, НомерКолонкиЛев = Неопределено, НомерСтрокиНиз = Неопределено, НомерКолонкиПрав = Неопределено) Экспорт
// Проверяем, существует ли уже область с таким именем
НайденнаяОбласть = ТабДок.Области.Найти(ИмяОбласти);
Если НайденнаяОбласть <> Неопределено Тогда
// Освобождаем занятое имя
НайденнаяОбласть.Имя = "";
КонецЕсли;
// Создаем новую область по указанным координатам
НоваяОбласть = ТабДок.Область(НомерСтрокиВерх, НомерКолонкиЛев, НомерСтрокиНиз, НомерКолонкиПрав);
// Назначаем имя новой области
НоваяОбласть.Имя = ИмяОбласти;
КонецПроцедуры
Использование данной процедуры существенно упрощает код формирования сложных отчетов, делая его более читаемым и защищенным от ошибок работы с коллекциями областей табличного документа 1С. Для изучения архитектуры типовой печати можно использовать пример внешней печатной формы на актуальной БСП.