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