Как программно определить, объединены ли ячейки в табличном документе 1С

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

При работе с отчетами, печатными формами или динамическими таблицами в 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);

Если ОбъединенаССоседями Тогда
    // Это означает, что запрошенная область поглощена более крупным объединением
    // или пересекается с ним.
КонецЕсли;

Определение «главной» ячейки объединения при переборе

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

Проанализируем алгоритм «умного» обхода:

  1. Получаем область текущей ячейки цикла (R, C).
  2. Проверяем, совпадают ли Область.Верх с R и Область.Лево с C.
  3. Если совпадают — мы находимся в «голове» объединения. Можно считывать данные.
  4. Если не совпадают — мы находимся «внутри» или в «хвосте» объединения, которое уже было обработано ранее. Такую ячейку следует пропустить.

Пример реализации:


Для НомерСтроки = 1 По ТабДок.ВысотаТаблицы Цикл
    Для НомерКолонки = 1 По ТабДок.ШиринаТаблицы Цикл
        
        ТекОбласть = ТабДок.Область(НомерСтроки, НомерКолонки);
        
        // Проверяем, является ли текущая итерация началом области
        Если ТекОбласть.Верх = НомерСтроки И ТекОбласть.Лево = НомерКолонки Тогда
            // Обрабатываем данные ячейки (или объединения)
            Значение = ТекОбласть.Текст;
        Иначе
            // Пропускаем, так как эта ячейка — часть уже обработанного блока
            Продолжить;
        EndЕсли;
        
    КонецЦикла;
КонецЦикла;

Работа с «Полем табличного документа» на форме

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

Если вы работаете в обычных формах, вы обращаетесь к элементу формы напрямую, и он ведет себя как табличный документ. В управляемых формах элемент формы связан с реквизитом (обычно типа ТабличныйДокумент). Чтобы выполнить проверку объединения на сервере, вам необходимо передать этот реквизит в серверный контекст или выполнять действия непосредственно с данными, к которым привязано поле.

Важный нюанс: Если вы хотите проверить, объединены ли две конкретные ячейки (А и Б) между собой, логика будет следующей: нужно получить область для ячейки А и область для ячейки Б. Если их границы (Верх, Низ, Лево, Право) полностью идентичны, значит, это одна и та же объединенная область.

Оптимизация и производительность

Рассмотрим вопрос производительности. Прямое обращение к ТабДок.Область(R, C) внутри вложенных циклов для таблицы размером 10 000 строк может работать медленно. Если ваша задача — просто прочитать данные, старайтесь использовать выгрузку в РезультатЗапроса или анализировать только заполненные области. Однако для анализа визуального форматирования (границ, цветов и объединений) использование Область() является единственным штатным способом.

Для ускорения работы рекомендуется:

Таким образом, комбинируя проверку координат через Верх, Низ, Лево и Право, вы можете полностью контролировать логику обработки объединенных ячеек в любом табличном документе 1С.

← На главную