При работе с Системой компоновки данных (СКД) программисты часто сталкиваются с задачей компактного вывода данных. Типичный пример: нужно вывести «Артикул» и «Наименование» номенклатуры в одной ячейке, не создавая при этом лишних колонок и не выводя саму ссылку на «Номенклатуру» (владельца реквизитов). Однако стандартные настройки СКД часто ведут себя непредсказуемо: либо принудительно выводят владельца, либо добавляют странные запятые в начале строки. В этой статье мы подробно разберем, почему это происходит, и рассмотрим несколько надежных способов решения проблемы.
Разберем ситуацию: в СКД у нас есть поле Номенклатура, и мы хотим вывести его реквизиты Номенклатура.Артикул и Номенклатура.Код. В настройках варианта отчета на вкладке «Дополнительные настройки» есть параметр «Расположение реквизитов». Мы можем установить его в значение «Вместе», надеясь, что поля объединятся.
Проанализируем причину неудач: если вы просто добавляете Артикул и Код в выбранные поля как отдельные элементы, СКД воспринимает их как независимые поля, а не как реквизиты в контексте группировки. В результате настройка расположения игнорируется. Если же использовать режим «Вместе с владельцем», то в ячейку всегда будет попадать представление самой Номенклатуры. Если владелец пуст или не выбран, система может оставить зарезервированное место под него, что и приводит к появлению «дурацкой запятой» в начале строки.
Это самый простой и эффективный метод, не требующий написания кода. Рассмотрим его по шагам:
Номенклатура.Артикул и Номенклатура.Наименование).Этот метод заставляет СКД рассматривать содержимое группы как единый блок данных в одной колонке. При этом нам не нужно добавлять в выбранные поля само поле-владелец.
Если нам нужно полное управление форматированием (например, мы хотим, чтобы артикул был в скобках или через тире), лучше всего использовать пользовательские поля. Выясним, как это сделать:
На вкладке Настройки перейдем на вложенную вкладку Пользовательские поля. Создадим новое поле типа «Поле-выражение». В выражении детальных записей мы можем прописать логику объединения строк. Важно помнить о типах данных: если реквизит не является строкой, его нужно преобразовать функцией Строка() или Представление().
Пример выражения:
Представление(Номенклатура.Артикул) + " — " + Представление(Номенклатура.Наименование)
Такой подход полностью исключает появление системных запятых, так как мы сами определяем разделитель. Рассмотрим преимущество: если один из реквизитов не заполнен, мы можем обработать это условием ВЫБОР КОГДА, чтобы разделитель не висел в пустоте.
Для тех случаев, когда визуальная составляющая критически важна, мы можем воспользоваться механизмом макетов. Проанализируем ситуацию: нам нужно расположить данные в одной ячейке, но, возможно, в две строки или с разным шрифтом.
[Артикул] / [Наименование].Этот способ является «тяжелой артиллерией», так как он жестко фиксирует оформление, но зато дает 100% гарантию отсутствия лишних символов от движка СКД.
Иногда требуется заставить штатный механизм «Вместе с владельцем» работать без отображения самого владельца. Разберем этот лайфхак:
Контрагент) и его реквизиты в выбранные поля.0.1.В результате СКД выведет «пустое» представление владельца, а следом за ним — реквизиты. Это может помочь избавиться от запятой, если правильно скомбинировать настройки.
Если настройки варианта не помогают, мы всегда можем вмешаться в процесс вывода отчета программно. Рассмотрим пример кода, который перехватывает вывод в табличный документ и позволяет объединять ячейки или корректировать текст заголовков «на лету».
ПроцессорКомпановки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпановки.Инициализировать(МакетКомпановки, , ДанныеРасшифровки, Ложь);
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
ПроцессорВывода.УстановитьДокумент(ЭлементыФормы.Результат);
ПроцессорВывода.НачатьВывод();
Пока Истина Цикл
ЭлементРезультата = ПроцессорКомпановки.Следующий();
Если ЭлементРезультата = Неопределено Тогда
Прервать;
КонецЕсли;
// Здесь можно проанализировать ЭлементРезультата перед выводом
ПроцессорВывода.ВывестиЭлемент(ЭлементРезультата);
КонецЦикла;
ПроцессорВывода.ЗакончитьВывод();
В сообщениях форума также предлагался вариант постобработки уже готового ТабличногоДокумента. Мы можем обойти ячейки циклом и программно объединить те, в которых заголовки дублируются, или удалить лишние символы из строк.
Функция ОбъединятьЯчейки(ТабДок, ИндСтр, ИндКол)
Ячейка = ТабДок.Область(ИндСтр, ИндКол);
ЯчейкаСлед = ТабДок.Область(ИндСтр, ИндКол + 1);
Если ПустаяСтрока(Ячейка.Текст) Тогда
Возврат Ложь;
ИначеЕсли Ячейка.Текст = ЯчейкаСлед.Текст Тогда
Возврат Истина;
Иначе
Возврат Ложь;
КонецЕсли;
КонецФункции
Посмотрим на современный подход: в последних версиях платформы 8.3 в выражениях СКД стала доступна функция СоединитьСтроки(). Хотя она предназначена для агрегации данных по группировке, её можно использовать в вычисляемых полях для объединения массивов значений с четко заданным разделителем. Это самый чистый способ с точки зрения синтаксиса платформы, позволяющий избежать ручной конкатенации строк и проверки на NULL.
Резюме: Чтобы избавиться от «запятой в начале» и красиво сгруппировать реквизиты, лучше всего использовать группировку в выбранных полях с режимом «Вместе» или создавать пользовательские поля-выражения. Программная обработка — это крайний вариант, когда стандартные возможности оформления не позволяют добиться идеального визуального результата.