При формировании сложных печатных форм в 1С:Предприятии 7.7 часто возникает задача визуального объединения повторяющихся значений в колонках. Типичный пример — отчет по складам и работающим на них кладовщикам. Если один и тот же кладовщик перемещается между складами, стандартный алгоритм простого сравнения «предыдущее значение равно текущему» начинает давать сбои, объединяя данные там, где это логически неверно. В этой статье мы разберем, как правильно реализовать алгоритм объединения ячеек по нескольким полям и какие технические нюансы платформы 7.7 при этом важно учитывать.
Рассмотрим ситуацию, которую описал автор темы. У нас есть структура: Склад | Кладовщик | Товар. Нам нужно объединить ячейки в первых двух колонках. Основная сложность заключается в том, что «Кладовщик» является подчиненной группировкой по отношению к «Складу». Если мы будем проверять только колонку с именем кладовщика, то программа может ошибочно объединить ячейку «Иван Петров» со склада №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С 7.7 важно помнить о нескольких особенностях:
Потеря данных: При объединении нескольких ячеек, в которых уже есть текст, платформа оставит только значение из самой верхней левой ячейки. Все остальные данные в объединяемом диапазоне будут удалены. Поэтому убедитесь, что вы выводите текст только в первую строку группы.
Вертикальное выравнивание: После объединения текст по умолчанию будет прижат к верхнему краю ячейки. Чтобы отчет выглядел профессионально, желательно установить центрирование. Проанализируем пример кода:
Обл = Таб.Область(НачСтр, Кол, КонСтр, Кол);
Обл.Объединить();
Обл.ВертикальноеВыравнивание(3); // 3 - Центр
Обл.Рамка(3,3,3,3); // Восстановление границ после объединения
Сетка и границы: Программное объединение часто «разрывает» границы ячеек, установленные в шаблоне. После вызова Объединить() рекомендуется принудительно устанавливать рамки для всей области методом Рамка(), как показано в примере выше.
Профессиональные разработчики часто стараются избегать метода Объединить(), так как он ресурсозатратен. Вместо этого используется метод вывода разных секций. Разберем этот подход подробнее:
В шаблоне таблицы создаются две секции для строки данных:
При выводе каждой новой строки мы проверяем, изменился ли склад или кладовщик. Если значение то же самое — выводим Секция_Пустая, если значение новое — выводим Секция_С_Данными. Это позволяет получить визуально идентичный результат без использования тяжелых методов манипуляции областями, хотя и требует более аккуратной настройки сетки в самом шаблоне .mxl.
Выбор конкретного метода зависит от сложности вашего отчета и объема данных. Для небольших печатных форм (до 500 строк) программное объединение методом Объединить() с использованием составного ключа является наиболее гибким и понятным решением.