При работе с отчетами, печатными формами или динамическими таблицами в 1С:Предприятии программисты часто сталкиваются с необходимостью программного анализа структуры ТабличныйДокумент. Одной из типовых задач является определение того, входит ли конкретная ячейка в состав объединения. Это критично при обходе ячеек в цикле, чтобы избежать повторной обработки данных или корректно считать значения. В данной статье мы разберем механизмы работы с областями и приведем конкретные примеры кода для решения этой задачи.
Для начала проанализируем, как платформа 1С обрабатывает запросы к ячейкам. Основным инструментом здесь выступает метод Область(). Важно понимать ключевую особенность: если вы обращаетесь к ячейке по адресу (строка, колонка), которая является частью объединенной области, система всегда возвращает объект ОбластьТабличногоДокумента, соответствующий всему объединению целиком.
Рассмотрим ситуацию: ячейки с (2, 2) по (4, 4) объединены. Если мы вызовем ТабДок.Область(2, 2), мы получим объект с границами 2-4. Если мы вызовем ТабДок.Область(3, 3), мы получим тот же самый объект с теми же самыми границами (Верх=2, Низ=4, Лево=2, Право=4).
Самый быстрый способ узнать, является ли ячейка «одиночной» или она входит в блок — это сравнить ее координаты с границами полученного объекта области. Если координаты «Верх» равны «Низ», а «Лево» равно «Право», значит, ячейка не объединена с соседями.
Разберем программный пример для проверки конкретной ячейки с координатами R (строка) и C (колонка):
// Пусть ТабДок — наш табличный документ, а R и C — индексы ячейки
ТекущаяЯчейка = ТабДок.Область(R, C);
// Если границы области шире, чем одна ячейка, значит она объединена
ЭтоОбъединение = НЕ (ТекущаяЯчейка.Верх = ТекущаяЯчейка.Низ
И ТекущаяЯчейка.Лево = ТекущаяЯчейка.Право);
Если ЭтоОбъединение Тогда
Сообщить("Ячейка (" + R + "," + C + ") входит в состав объединения!");
КонецЕсли;
Иногда задача стоит иначе: мы выбрали диапазон ячеек и хотим знать, не является ли этот диапазон частью еще более крупного объединения. Рассмотрим код, который позволяет это выяснить:
// Задаем границы интересующей нас области
x1 = 5; y1 = 3; // Верх, Лево
x2 = 7; y2 = 3; // Низ, Право
Область = ТабДок.Область(x1, y1, x2, y2);
// Проверяем, совпадают ли границы полученного объекта с запрошенными
ОбъединенаССоседями = НЕ (Область.Верх = x1 И Область.Лево = y1
И Область.Низ = x2 И Область.Право = y2);
Если ОбъединенаССоседями Тогда
// Это означает, что запрошенная область поглощена более крупным объединением
// или пересекается с ним.
КонецЕсли;
При обходе таблицы в цикле (например, по строкам) нам часто нужно обрабатывать объединенную область только один раз — когда мы «натыкаемся» на ее начало (левый верхний угол). Если мы будем обрабатывать каждую ячейку внутри объединения, мы получим дублирование данных.
Проанализируем алгоритм «умного» обхода:
(R, C).Область.Верх с R и Область.Лево с C.Пример реализации:
Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
Для НомерКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
ТекОбласть = ТабДок.Область(НомерСтроки, НомерКолонки);
// Проверяем, является ли текущая итерация началом области
Если ТекОбласть.Верх = НомерСтроки И ТекОбласть.Лево = НомерКолонки Тогда
// Обрабатываем данные ячейки (или объединения)
Значение = ТекОбласть.Текст;
Иначе
// Пропускаем, так как эта ячейка — часть уже обработанного блока
Продолжить;
EndЕсли;
КонецЦикла;
КонецЦикла;
Выясним причину путаницы, которая часто возникает у начинающих разработчиков. В 1С существует объект ТабличныйДокумент (прикладной тип данных) и элемент формы Поле табличного документа (визуальный элемент).
Если вы работаете в обычных формах, вы обращаетесь к элементу формы напрямую, и он ведет себя как табличный документ. В управляемых формах элемент формы связан с реквизитом (обычно типа ТабличныйДокумент). Чтобы выполнить проверку объединения на сервере, вам необходимо передать этот реквизит в серверный контекст или выполнять действия непосредственно с данными, к которым привязано поле.
Важный нюанс: Если вы хотите проверить, объединены ли две конкретные ячейки (А и Б) между собой, логика будет следующей: нужно получить область для ячейки А и область для ячейки Б. Если их границы (Верх, Низ, Лево, Право) полностью идентичны, значит, это одна и та же объединенная область.
Рассмотрим вопрос производительности. Прямое обращение к ТабДок.Область(R, C) внутри вложенных циклов для таблицы размером 10 000 строк может работать медленно. Если ваша задача — просто прочитать данные, старайтесь использовать выгрузку в РезультатЗапроса или анализировать только заполненные области. Однако для анализа визуального форматирования (границ, цветов и объединений) использование Область() является единственным штатным способом.
Для ускорения работы рекомендуется:
Текст или Расшифровка внутри блоков, которые вы решили пропустить по условию Иначе Продолжить.Таким образом, комбинируя проверку координат через Верх, Низ, Лево и Право, вы можете полностью контролировать логику обработки объединенных ячеек в любом табличном документе 1С.