К статье
Практический материал

Отчеты и Аналитика · 11 мин

СКД в 1С: как передать таблицу значений как параметр

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

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

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

Ниже разобран полный рабочий цикл: создание набора данных «Объект» в схеме, описание полей, программная компоновка с передачей таблицы, типизация колонок, соединение с запросом и типичные ошибки, из-за которых отчёт выводится пустым или падает с ошибкой.

Почему таблицу значений нельзя передать обычным параметром

Параметры СКД — это скалярные значения, списки или ссылки, которые подставляются в текст запроса или в выражения отбора. Параметр типа «ТаблицаЗначений» в схеме компоновки не поддерживается как самостоятельный источник строк: СКД не умеет «разворачивать» параметр-таблицу в записи отчёта.

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

Создание набора данных «Объект» в схеме компоновки

Откройте схему компоновки данных (в отчёте или как отдельный макет) и на закладке «Наборы данных» добавьте набор типа «Добавить набор данных — Объект». В поле «Имя объекта, содержащего данные» укажите произвольное имя, например ТаблицаДанных — именно по этому ключу таблица будет передана из кода.

Далее обязательно опишите поля набора. Для каждой колонки таблицы значений добавьте поле с точным именем колонки, укажите тип и при необходимости заголовок. Имена должны совпадать посимвольно, с учётом регистра в некоторых случаях лучше не экспериментировать и задавать их идентично. Если поле не описано в схеме, оно недоступно в настройках отчёта, даже если колонка в таблице есть.

Для полей-ресурсов (суммы, количества) на закладке «Ресурсы» добавьте выражения агрегирования, например Сумма(СуммаПродажи). Для полей ссылочных типов полезно указать тип максимально точно — тогда СКД сможет строить отборы по реквизитам ссылки через точку.

Программное формирование отчёта с передачей таблицы

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

// 1. Готовим таблицу значений любым способом

ТЗ = СформироватьТаблицуДанных();

// 2. Загружаем схему и настройки

Схема = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");

Настройки = Схема.НастройкиПоУмолчанию;

// 3. Компоновщик макета

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;

МакетКомпоновки = КомпоновщикМакета.Выполнить(Схема, Настройки);

// 4. Внешние наборы данных

ВнешниеНаборы = Новый Структура;

ВнешниеНаборы.Вставить("ТаблицаДанных", ТЗ);

// 5. Процессор компоновки

Процессор = Новый ПроцессорКомпоновкиДанных;

Процессор.Инициализировать(МакетКомпоновки, ВнешниеНаборы);

// 6. Вывод результата

Результат = Новый ТабличныйДокумент;

ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент;

ПроцессорВывода.УстановитьДокумент(Результат);

ПроцессорВывода.Вывести(Процессор);

Обратите внимание на порядок: внешние наборы передаются вторым параметром метода Инициализировать, а не в компоновщик макета. Если передать таблицу в компоновщик — она будет проигнорирована, и отчёт сформируется пустым.

Порядок действий
  1. 1
    Создайте в схеме набор данных «Объект» и задайте имя объекта
  2. 2
    Опишите все поля набора с типами, добавьте ресурсы
  3. 3
    Сформируйте таблицу значений с колонками, совпадающими с полями
  4. 4
    Поместите таблицу в структуру с ключом-именем объекта
  5. 5
    Передайте структуру в Инициализировать процессора компоновки
  6. 6
    Выведите результат и проверьте, что строки и итоги заполнены

Типизация колонок таблицы значений

Нетипизированные колонки — самая частая причина проблем. Если колонка создана без описания типа (ТЗ.Колонки.Добавить("Сумма")), в ней могут оказаться значения разных типов, и СКД не сможет корректно сравнивать их или суммировать.

Всегда задавайте тип явно через ОписаниеТипов:

ОписаниеЧисло = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2));

ОписаниеСтрока = Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(150));

ОписаниеСсылка = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");

ТЗ.Колонки.Добавить("Номенклатура", ОписаниеСсылка);

ТЗ.Колонки.Добавить("Наименование", ОписаниеСтрока);

ТЗ.Колонки.Добавить("Сумма", ОписаниеЧисло);

Для составных типов перечислите допустимые типы через запятую, но помните: чем шире составной тип, тем медленнее работают отборы и сравнения в СКД. Если колонка по смыслу всегда ссылочная, не добавляйте в неё строковый тип «на всякий случай».

Типичные ошибки
01
Колонки таблицы без типа — отборы и итоги работают некорректно или падают с ошибкой преобразования
02
Имя колонки не совпадает с именем поля в схеме — поле в отчёте пустое
03
Таблица передана в КомпоновщикМакета вместо ПроцессораКомпоновкиДанных — отчёт формируется без строк
04
Имя ключа в структуре внешних наборов отличается от имени объекта в схеме — ошибка «Внешний набор данных не найден»
05
Передача таблицы с миллионами строк без отбора — отчёт формируется долго и съедает память

Соединение таблицы значений с запросом

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

Здесь важно направление связи и обязательность. Если связь левая (все строки таблицы и подходящие строки запроса), контрагенты без данных в базе всё равно попадут в отчёт. Если сделать запрос источником, а таблицу приёмником, строки таблицы без совпадений в запросе потеряются.

Сравнение вариантов

Только набор «Объект»

Подходит, когда все данные уже собраны в таблицу. Простая схема, но нет доступа к данным базы без дополнительного кода.

Объект + связь с запросом

Таблица дополняется данными из базы. Гибко, но требует аккуратной настройки связей и контроля типов полей связи.

Поместить ТЗ в временную таблицу запроса

Через менеджер временных таблиц запроса СКД (сложнее в настройке, доступно не во всех сценариях). Даёт полноценное соединение в SQL, но требует передачи менеджера таблиц в процессор компоновки.

Отборы, параметры и ограничения

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

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

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

Контрольные точки

Как проверить результат

Строки в отчёте
Норма

Количество строк совпадает с количеством строк таблицы (без отборов)

Тревожный признак

Отчёт пустой или строк меньше — проверьте имя ключа и связи

Итоги по ресурсам
Норма

Суммы сходятся с контрольной суммой по таблице

Тревожный признак

Итоги нулевые — ресурс не описан или поле не числовое

Отбор по полю
Норма

Отбор отсекает строки корректно

Тревожный признак

Отбор не работает или ошибка — тип поля не совпадает с типом колонки

Поля из связанного запроса
Норма

Дополнительные данные подтянуты к строкам таблицы

Тревожный признак

Поля пустые — неверное направление связи или тип поля связи

Частые ошибки и их диагностика

Ошибка «Не найден внешний набор данных» означает, что имя ключа в структуре не совпадает с именем объекта в схеме. Проверьте оба значения посимвольно, включая отсутствие пробелов.

Пустой отчёт при корректной передаче чаще всего связан с настройками: в выбранном варианте отчёта нет группировки или поля, либо пользовательский отбор отсекает все строки. Для проверки сформируйте отчёт с НастройкиПоУмолчанию без отборов — если строки появились, проблема в настройках, а не в данных.

Ошибки преобразования типов при компоновке указывают на несоответствие типа поля в схеме и содержимого колонки. Особенно коварны значения Неопределено и NULL: перед передачей таблицы пройдитесь по строкам и замените их на значения по умолчанию для типа колонки.

FAQ

Можно ли передать в СКД дерево значений вместо таблицы?

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

Как передать несколько таблиц значений в одну схему?

Создайте несколько наборов данных «Объект» с разными именами и передайте структуру с несколькими ключами: ВнешниеНаборы.Вставить("Таблица1", ТЗ1); ВнешниеНаборы.Вставить("Таблица2", ТЗ2). Наборы можно связывать между собой стандартными связями СКД.

Почему отбор по строковому полю работает медленно?

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

Можно ли использовать внешний набор в отчёте на управляемых формах без программирования?

Частично. Если отчёт построен на СКД с набором «Объект», таблицу всё равно нужно передать программно — обычно в обработчике ПриКомпоновкеРезультата модуля объекта отчёта, где доступен процессор компоновки через параметры события. Полностью декларативно это не решается.

Что делать, если поле в отчёте пустое, хотя колонка заполнена?

Проверьте три вещи: совпадает ли имя колонки с именем поля в наборе данных, включено ли поле в выбранные поля текущего варианта настроек, и не отсекает ли отбор строки. Чаще всего причина — опечатка в имени поля или колонки.

Как отладить, какие данные реально ушли в СКД?

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

Итог

Что важно запомнить

Таблица значений передаётся в СКД как внешний набор данных «Объект»: поля описываются в схеме, колонки таблицы типизируются, а сама таблица передаётся в ПроцессорКомпоновкиДанных через структуру ВнешниеНаборыДанных. Имена объекта, полей и ключей должны совпадать, объём данных — контролироваться до передачи.