В процессе разработки конфигураций на платформе 1С:Предприятие программисты часто сталкиваются с требованиями заказчиков сделать интерфейс «как в Excel». Одной из таких задач является объединение ячеек по вертикали, когда несколько строк должны иметь одну общую ячейку (например, для отображения общей суммы по группе клиентов). Рассмотрим подробно, как решается эта задача, и разберем, почему стандартная табличная часть ведет себя иначе, чем табличный документ.
Прежде всего, нам необходимо четко разграничить два объекта. Табличная часть (ТЧ) — это часть структуры данных объекта (документа, справочника). Она представляет собой набор записей в базе данных. В стандартном интерфейсе 1С ячейки в ТЧ объединять нельзя, так как каждая строка должна быть независимой единицей информации.
Табличный документ (ТабДок) — это средство вывода информации (отчеты, печатные формы). Здесь мы обладаем полной свободой оформления и можем объединять любые области. Проанализируем способы решения задачи в зависимости от того, где именно нужно отобразить данные.
Если ваша задача — вывести план продаж или отчет на печать (или в специальное поле на форме), мы используем метод Объединить(). Рассмотрим алгоритм, который автоматически сканирует колонку и объединяет ячейки с одинаковым текстом. Проанализируем следующий пример кода:
ОбъединениеНачало = 2; // Предположим, первая строка — это заголовок
ПоследняяСтрока = ТабДок.ВысотаТаблицы;
Для ТекущаяСтрока = 2 По ПоследняяСтрока Цикл
// Сравниваем текст текущей ячейки с текстом в предыдущей строке
ТекстТекущий = ТабДок.Область("R" + ТекущаяСтрока + "C1").Текст;
ТекстПредыдущий = ТабДок.Область("R" + (ТекущаяСтрока - 1) + "C1").Текст;
Если ТекстТекущий = ТекстПредыдущий Тогда
// Если значения совпадают, продолжаем цикл, пока не найдем конец группы
Продолжить;
Иначе
// Как только значение изменилось, объединяем пройденный диапазон
Если (ТекущаяСтрока - 1) > ОбъединениеНачало Тогда
ОбластьДляОбъединения = "R" + ОбъединениеНачало + "C1:R" + (ТекущаяСтрока - 1) + "C1";
ТабДок.Область(ОбластьДляОбъединения).Объединить();
КонецЕсли;
ОбъединениеНачало = ТекущаяСтрока;
КонецЕсли;
КонецЦикла;
Разберем по шагам, что происходит в этом коде. Мы обходим таблицу построчно. Как только программа встречает новое значение в колонке C1, она берет диапазон строк от ОбъединениеНачало до предыдущей строки и вызывает метод Объединить(). Это идеальный вариант для формирования сложных коммерческих планов и отчетов.
Если же объединение требуется именно в интерактивной Табличной части, где пользователь вводит данные, напрямую объединить ячейки не получится. Однако мы можем применить хитрость с Условным оформлением. Выясним, как создать иллюзию объединения:
Для реализации сложной иерархии, как в случае с планом продаж (Группа -> Сумма -> Список клиентов), лучше всего подходит объект ДеревоЗначений. Рассмотрим подробнее преимущества этого подхода:
В дереве значений мы создаем родительскую строку, в которой заполняем только колонку Сумма. Все строки с клиентами делаем подчиненными (дочерними) этой строке. При отображении на форме 1С автоматически добавит кнопки «развернуть/свернуть», и визуально это будет выглядеть гораздо профессиональнее, чем попытки объединения ячеек в плоской таблице.
Рано или поздно встает вопрос: как записать такие «объединенные» данные в Регистр сведений (РС)? Помните, что регистр — это плоская таблица. Рассмотрим два варианта записи:
Вариант А: Избыточное хранение. Мы записываем сумму в каждую строку. Например:
Строка 1: Клиент А, Группа «Новые», Сумма 10000.
Строка 2: Клиент Б, Группа «Новые», Сумма 10000.
При построении отчета мы просто сгруппируем данные по полю Сумма или будем использовать агрегатные функции типа МАКСИМУМ.
Вариант Б: Разделение сущностей. Это наиболее правильный с точки зрения архитектуры подход. Мы создаем два регистра или две табличные части:
Связь между ними осуществляется по КлючуСтроки или уникальному идентификатору. Это позволяет избежать дублирования сумм и исключает ошибки при случайном редактировании одной из строк группы.
Проанализировав ситуацию, можно сделать вывод: если вам нужно только отображение — используйте ТабличныйДокумент и метод Объединить(). Если нужно редактирование — используйте ДеревоЗначений. Для хранения в базе данных всегда приводите данные к «плоскому» виду, используя идентификаторы групп для последующей группировки в отчетах.