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

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

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

Метод 1: Постобработка Табличного документа

Самый гибкий способ — это пройтись по уже сформированному табличному документу и программно объединить нужные области. Разберем алгоритм, который находит одинаковые значения в ключевой колонке (например, "Контрагент"), объединяет их, а в других колонках собирает данные в одну строку.

Рассмотрим пример процедуры, которая принимает сформированный ТабДок, номер ключевой колонки и массив колонок, данные в которых нужно соединить через запятую:


&НаСервереБезКонтекста
Процедура ОбъединитьЯчейкиВКолонке(ТабДок, НомерКолонки, КолонкиОбъединить, ПерваяСтрока = 1)
    
    ТекущийТекст = Неопределено;
    НачалоОбласти = ПерваяСтрока;
    КоличествоСтрок = ТабДок.ВысотаТаблицы;
    
    Для НомерСтроки = ПерваяСтрока По КоличествоСтрок Цикл
        
        ТекстЯчейки = ТабДок.Область(НомерСтроки, НомерКолонки).Текст;
        
        // Проверяем, изменилось ли значение в ключевой колонке
        Если ТекущийТекст <> ТекстЯчейки Тогда
            
            // Если накопилось несколько одинаковых строк, объединяем их
            Если НомерСтроки - НачалоОбласти > 1 Тогда
                
                // Объединяем ключевую колонку
                ТабДок.Область(НачалоОбласти, НомерКолонки, НомерСтроки - 1, НомерКолонки).Объединить();
                
                // Обрабатываем зависимые колонки (собираем текст через запятую)
                Для Каждого Колонка Из КолонкиОбъединить Цикл
                    МассивЗначений = Новый Массив;
                    
                    Для Стр = НачалоОбласти По НомерСтроки - 1 Цикл
                        ЗначениеТекста = ТабДок.Область(Стр, Колонка).Текст;
                        Если ЗначениеТекста <> "" Тогда
                            МассивЗначений.Добавить(ЗначениеТекста);
                        КонецЕсли;
                    КонецЦикла;
                    
                    ОбластьДляОбъединения = ТабДок.Область(НачалоОбласти, Колонка, НомерСтроки - 1, Колонка);
                    ОбластьДляОбъединения.Объединить();
                    ОбластьДляОбъединения.Текст = СтрСоединить(МассивЗначений, ", ");
                    
                    // Настраиваем внешний вид
                    ОбластьДляОбъединения.ВертикальноеПоложение = ВертикальноеПоложение.Центр;
                    ОбластьДляОбъединения.РазмещениеТекста = РазмещениеТекста.Переносить;
                КонецЦикла;
                
            КонецЕсли;
            
            НачалоОбласти = НомерСтроки;
            ТекущийТекст = ТекстЯчейки;
            
        КонецЕсли;
    КонецЦикла;

    // Не забываем обработать последний блок строк
    Если НомерСтроки - НачалоОбласти > 1 Тогда
        ТабДок.Область(НачалоОбласти, НомерКолонки, НомерСтроки - 1, НомерКолонки).Объединить();
        // ... (аналогичный код обработки зависимых колонок)
    КонецЕсли;
    
    ТабДок.АвтоВысотаСтрок = Истина;
    
КонецПроцедуры

Важные нюансы при программном объединении:

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

Метод 2: Подготовка данных в Запросе

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

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


ВЫБРАТЬ
    РеестрПлатежей.Контрагент КАК Контрагент,
    СУММА(РеестрПлатежей.Сумма) КАК Сумма,
    ПРЕДСТАВЛЕНИЕ(РеестрПлатежей.Документ) КАК ДокументСтрокой
ПОМЕСТИТЬ ВТ_Данные
ИЗ
    РегистрНакопления.РеестрПлатежей КАК РеестрПлатежей
СГРУППИРОВАТЬ ПО
    РеестрПлатежей.Контрагент,
    РеестрПлатежей.Документ
;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
    ВТ_Данные.Контрагент,
    СУММА(ВТ_Данные.Сумма) КАК ОбщаяСумма
ИЗ
    ВТ_Данные КАК ВТ_Данные
СГРУППИРОВАТЬ ПО
    ВТ_Данные.Контрагент

Хотя стандартный SQL в 1С не поддерживает функцию типа STRING_AGG напрямую, мы можем использовать итоги в запросе (ИТОГИ ПО Контрагенту). При обходе результата запроса мы будем выводить секцию контрагента один раз, а затем внутри цикла обходить детальные записи, собирая строку с документами вручную перед выводом в макет.

Метод 3: Использование Системы компоновки данных (СКД)

Если отчет строится на СКД, задачу по объединению и перечислению через запятую можно решить без единой строчки кода в модуле. Выясним, как это сделать:

  1. Функция СоединитьСтроки: В ресурсах СКД выберите поле, которое нужно перечислить. В выражении укажите: СоединитьСтроки(Массив(ВычислитьВыражениеСГруппировкойМассив("НомерДокумента")), ", ").
  2. Настройки группировки: Добавьте группировку по Контрагенту. В выбранные поля этой группировки добавьте созданный ресурс.
  3. Расположение группировок: В настройках отчета (вкладка "Другие настройки") установите параметр "Расположение группировок" в значение "Вместе". Это заставит СКД объединять ячейки с одинаковыми значениями в левых колонках.

Этот метод является наиболее "правильным" с точки зрения архитектуры 1С, так как он сохраняет расшифровку и корректно работает с фоновым формированием отчетов.

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

Рассмотрим ситуацию, когда в отчете более 10 000 строк. Построчный перебор и вызов метода Область() для каждой ячейки может занять значительное время. Чтобы ускорить процесс, проанализируем следующие рекомендации:

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

← На главную