Как программно объединить ячейки по нескольким колонкам в 1С 7.7?

Программист 1С v7.7
← На главную

При формировании сложных печатных форм в 1С:Предприятии 7.7 часто возникает задача визуального объединения повторяющихся значений в колонках. Типичный пример — отчет по складам и работающим на них кладовщикам. Если один и тот же кладовщик перемещается между складами, стандартный алгоритм простого сравнения «предыдущее значение равно текущему» начинает давать сбои, объединяя данные там, где это логически неверно. В этой статье мы разберем, как правильно реализовать алгоритм объединения ячеек по нескольким полям и какие технические нюансы платформы 7.7 при этом важно учитывать.

Анализ проблемы: почему не работает простой цикл

Рассмотрим ситуацию, которую описал автор темы. У нас есть структура: Склад | Кладовщик | Товар. Нам нужно объединить ячейки в первых двух колонках. Основная сложность заключается в том, что «Кладовщик» является подчиненной группировкой по отношению к «Складу». Если мы будем проверять только колонку с именем кладовщика, то программа может ошибочно объединить ячейку «Иван Петров» со склада №1 и такую же ячейку со склада №2, если они идут в таблице друг за другом.

Для решения этой задачи нам необходимо учитывать иерархию. Ячейки во второй колонке могут быть объединены только в том случае, если:

  1. Текущее значение во второй колонке совпадает с предыдущим.
  2. И при этом значения в первой колонке (родительской группе) для этих строк также идентичны.

Алгоритм объединения по двум полям через «Составной ключ»

Проанализируем наиболее надежный способ реализации такого объединения. Чтобы не запутаться в сложных условиях Если ... И ... Тогда, мы можем использовать метод составного ключа. Разберем его по шагам.

Вместо того чтобы сравнивать каждое поле по отдельности, мы создадим строковую переменную, которая будет включать в себя значения всех ключевых колонок. Посмотрим на пример кода, который реализует эту логику:


// Предположим, Таб - это сформированная таблица
// Выборка - источник данных (например, ТаблицаЗначений)
ОбъединениеНачало = 2; // Начальная строка данных
Для СчетчикСтрок = 2 По Выборка.КоличествоСтрок() Цикл
    
    // Формируем ключи для текущей и предыдущей строки
    // Колонка 1 - Склад, Колонка 2 - Кладовщик
    КлючТекущий = Таб.Область("R"+СчетчикСтрок+"C1").Текст + "|" + Таб.Область("R"+СчетчикСтрок+"C2").Текст;
    КлючПредыдущий = Таб.Область("R"+Строка(СчетчикСтрок-1)+"C1").Текст + "|" + Таб.Область("R"+Строка(СчетчикСтрок-1)+"C2").Текст;
    
    Если КлючТекущий = КлючПредыдущий Тогда
        // Если ключи совпали, продолжаем цикл, пока не найдем конец блока
        Продолжить;
    Иначе
        // Ключ изменился - выполняем объединение накопленного блока
        Если (СчетчикСтрок - 1) > ОбъединениеНачало Тогда
            // Объединяем колонку Склад (C1)
            Таб.Область("R"+ОбъединениеНачало+"C1:R"+(СчетчикСтрок-1)+"C1").Объединить();
            // Объединяем колонку Кладовщик (C2)
            Таб.Область("R"+ОбъединениеНачало+"C2:R"+(СчетчикСтрок-1)+"C2").Объединить();
        КонецЕсли;
        ОбъединениеНачало = СчетчикСтрок;
    КонецЕсли;
КонецЦикла;

// Не забываем обработать последний блок после завершения цикла
Если (Выборка.КоличествоСтрок()) > ОбъединениеНачало Тогда
    Таб.Область("R"+ОбъединениеНачало+"C1:R"+Выборка.КоличествоСтрок()+"C1").Объединить();
    Таб.Область("R"+ОбъединениеНачало+"C2:R"+Выборка.КоличествоСтрок()+"C2").Объединить();
КонецЕсли;

Оптимизация производительности: работа с данными напрямую

Выясним важный момент: использование метода Область().Текст в цикле по тысячам строк может существенно замедлить формирование отчета. 1С 7.7 вынуждена при каждой итерации обращаться к графическому объекту таблицы. Чтобы ускорить процесс, рекомендуется сначала вычислить все координаты объединения, используя данные из ТаблицыЗначений или ВыборкиЗапроса, и только потом применять метод Объединить().

Рассмотрим рекомендации по оптимизации:

  1. Минимизация обращений: Сначала сформируйте таблицу полностью, а затем пройдите по ней один раз для объединения.
  2. Пакетная обработка: Если вы знаете структуру данных заранее, лучше объединять ячейки сразу после вывода группы строк, относящихся к одному кладовщику.
  3. Использование переменных: Вместо постоянного вызова Таб.Область(), сохраняйте ссылку на область в переменную, если планируете выполнять с ней несколько действий (например, объединение и форматирование).

Технические ограничения и визуальное оформление

При использовании метода Объединить() в 1С 7.7 важно помнить о нескольких особенностях:

Потеря данных: При объединении нескольких ячеек, в которых уже есть текст, платформа оставит только значение из самой верхней левой ячейки. Все остальные данные в объединяемом диапазоне будут удалены. Поэтому убедитесь, что вы выводите текст только в первую строку группы.

Вертикальное выравнивание: После объединения текст по умолчанию будет прижат к верхнему краю ячейки. Чтобы отчет выглядел профессионально, желательно установить центрирование. Проанализируем пример кода:


Обл = Таб.Область(НачСтр, Кол, КонСтр, Кол);
Обл.Объединить();
Обл.ВертикальноеВыравнивание(3); // 3 - Центр
Обл.Рамка(3,3,3,3); // Восстановление границ после объединения

Сетка и границы: Программное объединение часто «разрывает» границы ячеек, установленные в шаблоне. После вызова Объединить() рекомендуется принудительно устанавливать рамки для всей области методом Рамка(), как показано в примере выше.

Альтернативный метод: использование секций таблицы

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

В шаблоне таблицы создаются две секции для строки данных:

  1. Секция_С_Данными: содержит заполненные ячейки «Склад» и «Кладовщик» с границами.
  2. Секция_Пустая: на месте склада и кладовщика — пустые ячейки, но с правильно настроенными боковыми границами, имитирующими объединение.

При выводе каждой новой строки мы проверяем, изменился ли склад или кладовщик. Если значение то же самое — выводим Секция_Пустая, если значение новое — выводим Секция_С_Данными. Это позволяет получить визуально идентичный результат без использования тяжелых методов манипуляции областями, хотя и требует более аккуратной настройки сетки в самом шаблоне .mxl.

Выбор конкретного метода зависит от сложности вашего отчета и объема данных. Для небольших печатных форм (до 500 строк) программное объединение методом Объединить() с использованием составного ключа является наиболее гибким и понятным решением.

← На главную