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