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

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

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

Анализ проблемы: почему настройки «ломаются»

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

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

Шаг 1. Правильная передача данных через Временное хранилище

Выясним причину проблем с доступностью данных. Временное хранилище (ВХ) имеет ограниченный жизненный цикл. Если поместить данные в ВХ в одной форме и передать адрес в другую, нужно гарантировать, что данные не «протухнут». Рассмотрим правильный код помещения данных из обработки:


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

ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("АдресДанных", АдресДанных);
ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);

ОткрытьФорму("Отчет.МойОтчетНаТЗ.Форма.ФормаОтчета", ПараметрыФормы);

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

Шаг 2. Реализация обработчика ПриКомпоновкеДанных

Проанализируем ситуацию в модуле объекта отчета. Нам нужно перехватить процесс компоновки, подставить внешнюю ТЗ и при этом сохранить пользовательские настройки. Главная ошибка здесь — программное создание нового компоновщика или загрузка настроек по умолчанию, которая затирает изменения пользователя.

Рассмотрим эталонную реализацию в модуле объекта:


Процедура ПриКомпоновкеДанных(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    СтандартнаяОбработка = Ложь; // Отключаем штатный механизм
    
    // Получаем ТЗ из хранилища по адресу, сохраненному в реквизите объекта
    Если ЭтоАдресВременногоХранилища(АдресДанных) Тогда
        ВнешняяТЗ = ПолучитьИзВременногоХранилища(АдресДанных);
    Иначе
        Возврат; // Данных нет, выходить
    КонецЕсли;

    // Инициализируем схему и внешние наборы данных
    СхемаКД = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    ВнешниеНаборыДанных = Новый Структура;
    ВнешниеНаборыДанных.Вставить("ТЗ_Данные", ВнешняяТЗ);

    // ВАЖНО: Используем настройки из КомпоновщикаНастроек объекта, 
    // которые уже содержат пользовательские правки из формы
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();

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

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

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

Шаг 3. Решение проблемы «красных крестиков» и структуры

Если группировки все равно помечаются как некорректные, проверим следующие моменты:

  1. Совпадение имен полей: Имена колонок в вашей ТЗ должны в точности (включая регистр) совпадать с именами полей в наборе данных Объект в схеме СКД.
  2. Типы данных: Если в СКД для поля указан конкретный тип (например, СправочникСсылка.Номенклатура), а в ТЗ в этой колонке попадается Неопределено или другой тип, СКД может исключить поле из доступных.
  3. Настройки формы: Чтобы пользователь мог менять структуру в упрощенной форме настроек, в СКД на закладке «Настройки» необходимо зайти в «Состав пользовательских настроек» и проставить флаги для группировок, отборов и выбранных полей.

Шаг 4. Использование стандартной формы отчета

Как выяснилось в ходе обсуждения, наиболее стабильный вариант — отказ от собственной формы отчета в пользу стандартной. Стандартная форма (особенно в конфигурациях ERP, КА, УТ 11) умеет корректно работать с вариантами и настройками. Чтобы передать адрес ТЗ в стандартную форму, можно использовать параметры СКД.

Разберем этот алгоритм:

  1. В СКД создаем параметр АдресДанных (тип Строка, скрытый).
  2. При открытии отчета передаем этот параметр в структуру Параметры.
  3. В ПриКомпоновкеДанных считываем значение параметра из КомпоновщикНастроек.Настройки.ПараметрыДанных.

Пример открытия стандартной формы с передачей параметра:


ПараметрыОтчета = Новый Структура;
ПараметрыОтчета.Вставить("СформироватьПриОткрытии", Истина);
// Настройки параметров СКД передаются через ключ "Отбор" или "Параметры" в зависимости от версии БСП
ПараметрыДанных = Новый Структура("АдресДанных", НужныйАдрес);
ПараметрыОтчета.Вставить("ПараметрыДанных", ПараметрыДанных);

ОткрытьФорму("Отчет.МойОтчет.ФормаОбъекта", ПараметрыОтчета);

Посмотрим на результат: использование стандартной формы позволяет избежать проблем с «изолированными» сессиями и дает пользователю полный доступ к кнопке «Настройка» и «Изменить вариант», где структура будет отображаться корректно, так как SettingsComposer (Компоновщик настроек) будет инициализирован платформой в контексте актуальной схемы.

Дополнительный совет: Менеджер временных таблиц

Проанализируем еще один продвинутый способ. Если ТЗ большая или требуется ее соединение с другими таблицами БД в рамках СКД, можно использовать МенеджерВременныхТаблиц (МВТ). Вы можете выгрузить вашу ТЗ в МВТ запросом, а затем передать этот МВТ в процессор компоновки. В самой СКД при этом будет использоваться обычный Набор данных - запрос, который обращается к временной таблице. Это «обманет» систему настроек: СКД будет считать, что данные берутся из БД, и все механизмы группировок будут работать максимально прозрачно для пользователя.

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

← На главную