Как в СКД внешней обработки вывести список сотрудников через запятую без изменения конфигурации?

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

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

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

Ограничения вызова функций в выражениях СКД

Проанализируем архитектурное ограничение платформы 1С:Предприятие:

  1. В вычисляемых полях, выражениях ресурсов и пользовательских полях СКД нельзя вызывать процедуры и функции из модуля формы, модуля объекта внешней обработки или внешнего отчета.
  2. Язык выражений СКД позволяет вызывать только экспортные функции общих модулей конфигурации, для которых установлены соответствующие флаги доступности (сервер/клиент), по схеме ИмяОбщегоМодуля.ИмяФункции().
  3. Если конфигурация типовая и находится на замке (без возможности редактирования), добавить собственный общий модуль нельзя.

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

Решение 1: Получение строк через запрос и функция СоединитьСтроки в ресурсах

Наиболее эффективный и правильный способ с точки зрения производительности — выбрать всех сотрудников и сформировать их краткое ФИО сразу в запросе СКД, а конкатенацию возложить на вкладку «Ресурсы».

Рассмотрим, как правильно составить запрос набора данных. Обратим внимание на частые ошибки при получении срезов последних и формировании инициалов:

  1. Вместо конструкции ВЫРАЗИТЬ(Имя КАК СТРОКА(1)) для получения первой буквы имени и отчества надежнее использовать функцию ПОДСТРОКА().
  2. Параметры периода и условий следует передавать внутрь параметров виртуальных таблиц СрезПоследних(&Дата, ...), а не фильтровать результат в секции ГДЕ, чтобы запрос не сканировал лишние данные.
  3. Следует избегать неявного декартова произведения таблиц через запятую в секции ИЗ, используя явные соединения ЛЕВОЕ СОЕДИНЕНИЕ.

Посмотрим на пример корректного текста запроса набора данных СКД:


ВЫБРАТЬ
    Работники.ДолжностьПодразделения КАК ДолжностьПодразделения,
    ФИО.Фамилия + " " + ПОДСТРОКА(ФИО.Имя, 1, 1) + "." + ПОДСТРОКА(ФИО.Отчество, 1, 1) + "." КАК СотрудникКратко
ИЗ
    РегистрСведений.РаботникиОрганизаций.СрезПоследних(&Дата, ) КАК Работники
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ФИОФизЛиц.СрезПоследних(&Дата, ) КАК ФИО
        ПО Работники.Сотрудник.Физлицо = ФИО.ФизЛицо
ГДЕ
    (Работники.Сотрудник.ДатаУвольнения > &Дата
        ИЛИ Работники.Сотрудник.ДатаУвольнения = ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0))

Теперь разберем по шагам настройку СКД для объединения строк:

  1. Переходим на вкладку «Ресурсы» схемы компоновки данных.
  2. Добавляем поле СотрудникКратко в список ресурсов.
  3. В колонке «Выражение» указываем встроенную функцию СКД СоединитьСтроки:

СоединитьСтроки(СотрудникКратко, ", ")

Функция СоединитьСтроки принимает параметры: выражение, разделитель строк и разделитель колонок. Платформа автоматически выполнит обход всех детальных записей в рамках группировки (например, по подразделению или должности) и сформирует единую строку с разделителем без завершающей лишней запятой.

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


СоединитьСтроки(ВычислитьВыражениеСГруппировкойМассив("СотрудникКратко", "СотрудникКратко"), ", ")

Решение 2: Использование связей наборов данных

Если основной запрос отчета уже сложный или строится по другой таблице, можно разделить получение данных на два отдельных набора данных типа «Запрос»:

  1. НаборДанных1 (Основной) — выбирает список подразделений, должностей и другие базовые поля.
  2. НаборДанных2 (Сотрудники) — выбирает сотрудников с их кратким ФИО с условием по должности: ГДЕ Работники.ДолжностьПодразделения = &ДолжностьПодразделения.

Далее переходим на вкладку «Связи наборов данных»:

  1. Указываем Источник связи: НаборДанных1, Приемник связи: НаборДанных2.
  2. В поле Условие связи связываем поле должности основного набора.
  3. В колонке Параметры передаем значение в параметр второго набора данных: ДолжностьПодразделения.
  4. На вкладке «Ресурсы» настраиваем агрегацию для поля подчиненного набора данных через СоединитьСтроки(СотрудникКратко, ", ").

Решение 3: Программная подготовка данных через Набор данных «Объект»

Если логика склейки строк требует нестандартного алгоритма на встроенном языке 1С, который невозможно реализовать средствами языка запросов и функций СКД, можно использовать внешний набор данных типа «Объект».

Разберем реализацию в модуле объекта внешнего отчета через событие ПриКомпоновкеРезультата:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь;
    
    // 1. Формируем таблицу значений произвольным запросом и кодом 1С
    ТаблицаДанных = Новый ТаблицаЗначений;
    ТаблицаДанных.Колонки.Добавить("ДолжностьПодразделения");
    ТаблицаДанных.Колонки.Добавить("СписокСотрудников", Новый ОписаниеТипов("Строка"));
    
    // Заполняем ТаблицаДанных нужной информацией программно...
    
    // 2. Передаем подготовленную таблицу во внешний набор данных СКД
    ВнешниеНаборыДанных = Новый Структура;
    ВнешниеНаборыДанных.Вставить("ТаблицаСотрудников", ТаблицаДанных);
    
    // 3. Выполняем компоновку
    СхемаКомпоновкиДанных = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
    МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);
    
    ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
    ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, ВнешниеНаборыДанных, ДанныеРасшифровки);
    
    ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;
    ПроцессорВывода.УстановитьДокумент(ДокументРезультат);
    ПроцессорВывода.Вывести(ПроцессорКомпоновки);
    
КонецПроцедуры

В самой схеме СКД в этом случае создается набор данных типа «Объект» с именем источника ТаблицаСотрудников, и поля выводятся стандартным образом без необходимости вызова серверных функций конфигурации.

← На главную