Почему программно формируемый отчет СКД возвращает пустые данные, если схема загружена из временного хранилища?

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

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

Основные причины и пути решения

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

1. Проверка логики инициализации и жизненного цикла схемы СКД

Одной из частых причин пустого результата является некорректное использование временного хранилища или неправильная последовательность инициализации объектов СКД.

Давайте разберем типичный сценарий, описанный вами:

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

Здесь возникает несколько вопросов, которые мы должны проанализировать:

  1. Время жизни адреса временного хранилища: Адрес, полученный при вызове ПоместитьВоВременноеХранилище, имеет определенный жизненный цикл. Если вы помещаете данные во временное хранилище с привязкой к форме (используя УникальныйИдентификатор формы), данные будут храниться до закрытия этой формы. Однако, если между помещением и получением данных происходит длительный промежуток времени или несколько серверных вызовов, есть вероятность, что адрес мог "протухнуть" или данные могли быть удалены из кэша.
  2. "Чистая" схема: Когда вы извлекаете схему из временного хранилища с помощью ПолучитьИзВременногоХранилища(АдресСхемы), вы получаете "чистую" схему, которая была помещена изначально. Если вы инициализировали объект Компоновщик (который является реквизитом формы) с этим адресом, а затем отдельно получаете схему, убедитесь, что вы работаете с одним и тем же экземпляром схемы и настроек.
  3. Контекст инициализации: Рекомендуем инициализировать компоновщик настроек и получать схему ближе к моменту ее использования, особенно если вы не уверены в стабильности адреса временного хранилища или если контекст выполнения может меняться.

Что мы можем предпринять:

Рассмотрим пример правильной инициализации схемы и компоновщика настроек, которая обеспечивает актуальность данных:


// В процедуре, где непосредственно нужно сформировать отчет:
// 1. Получаем макет схемы
СхемаКомпоновкиДанных = РеквизитФормыВЗначение("Объект").ПолучитьМакет("ОтборыПрайса");

// 2. Инициализируем КомпоновщикНастроекКомпоновкиДанных
КомпоновщикНастроекДанных = Новый КомпоновщикНастроекКомпоновкиДанных;
КомпоновщикНастроекДанных.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновкиДанных));

// 3. Загружаем настройки. Можно загрузить настройки по умолчанию или ранее сохраненные.
// Например, если у вас есть сохраненные настройки в реквизите формы "Компоновщик"
// КомпоновщикНастроекДанных.ЗагрузитьНастройки(Компоновщик.ПолучитьНастройки());
// Или настройки по умолчанию из схемы
КомпоновщикНастроекДанных.ЗагрузитьНастройки(СхемаКомпоновкиДанных.НастройкиПоУмолчанию);

// 4. Получаем текущие настройки для установки параметров
Настройки = КомпоновщикНастроекДанных.ПолучитьНастройки();

// 5. Устанавливаем параметры данных
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Владелец", Владелец);
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Период", ДатаОкончанияДействия);
Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("ТипЦен", ТипЦен);

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

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

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

Обратите внимание, что мы получаем схему непосредственно перед использованием и инициализируем КомпоновщикНастроекДанных с ней. Это гарантирует, что мы работаем с актуальной схемой и корректно применяем к ней настройки.

2. Корректная работа с КомпоновщикомНастроекКомпоновкиДанных

Объект КомпоновщикНастроекКомпоновкиДанных играет ключевую роль в применении параметров, отборов, группировок и других настроек к схеме компоновки данных. Без правильной инициализации и загрузки настроек, даже корректная схема может давать пустой результат.

Разберем по шагам, как правильно использовать этот объект:

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

    Важный момент: Если реквизит формы типа КомпоновщикНастроекКомпоновкиДанных используется для хранения настроек, учтите, что он не сохраняется и не восстанавливается автоматически как реквизит формы. Для хранения и передачи настроек между серверными вызовами часто используют дополнительный реквизит произвольного типа или объект ХранилищеЗначения.

3. Детальная отладка и диагностика пустого результата

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

Давайте рассмотрим дополнительные шаги по отладке:

  1. Проверка наличия данных в источнике: Самая очевидная, но часто упускаемая причина — отсутствие данных в базе данных, которые соответствуют условиям запроса. Прежде чем углубляться в СКД, убедитесь, что при прямом запросе к базе данных (например, через консоль запросов) с аналогичными условиями, данные возвращаются.
  2. Анализ параметров и отборов:
    • Значения параметров: Проверьте в отладчике, какие значения фактически попадают в параметры (Владелец, ДатаОкончанияДействия, ТипЦен). Убедитесь, что они не пустые, имеют правильный тип и соответствуют ожидаемым данным.
    • Использование параметров: Удостоверьтесь, что параметры, которые вы устанавливаете, действительно используются в запросе схемы СКД и влияют на выборку. Иногда параметры используются только в вычисляемых полях или выражениях, а не в условиях "ГДЕ", что может приводить к неожиданным результатам.
    • Отборы: Если в схеме СКД есть отборы, проверьте, не слишком ли они строгие или не конфликтуют ли с параметрами, приводя к нулевому результату.
  3. Проверка источников данных в макете: В сообщении 1 упоминается "смущает, что в макете компоновки есть параметры, но нет источников данных...". Убедитесь, что ваша схема компоновки данных корректно описывает источники данных и наборы данных, а также, что они доступны для СКД. Если вы используете внешние наборы данных (например, ТаблицаЗначений), важно, чтобы имя набора данных в схеме СКД совпадало с ключом в структуре, передаваемой в ПроцессорКомпоновкиДанных.Инициализировать.
  4. "Стандартные настройки" и кэш: Иногда в пользовательском режиме система может подчитывать настройки из кэша по внутреннему идентификатору. Если вы вносили изменения в схему, попробуйте сделать "Стандартные настройки" в консоли СКД или убедитесь, что ваша программная инициализация не использует устаревшие кэшированные настройки.
  5. Проверка содержимого объектов в отладчике: Используйте точку останова перед выполнением ПроцессорКомпоновкиДанных.Инициализировать и проверьте содержимое ключевых объектов:
    • СхемаКомпоновкиДанных: Убедитесь, что это действительно ваша схема, а не пустой объект.
    • Настройки: Проверьте, что параметры данных установлены корректно и что отборы и группировки соответствуют вашим ожиданиям.
    • МакетКомпоновки: После выполнения КомпоновщикМакета.Выполнить, исследуйте объект МакетКомпоновки. Он содержит скомпонованный запрос и структуру отчета. Мы можем использовать специальные утилиты для просмотра его содержимого (например, в консоли отладчика или через дополнительные обработки).

4. Анализ сформированного запроса и макета СКД

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

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

    К сожалению, стандартными средствами 1С напрямую получить текст SQL-запроса из МакетКомпоновки, который будет выполнен, не всегда тривиально. Однако, мы можем получить описание запроса из СхемаКомпоновкиДанных или использовать отладочные инструменты, которые позволяют "разобрать" МакетКомпоновки.

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

  3. Проверка на заполненность результата: После выполнения компоновки, всегда проверяйте, содержит ли полученный объект РезультатЗапроса какие-либо данные.
    
    Если РезультатЗапроса.Количество() = 0 Тогда
        Сообщить("Отчет не содержит данных. Проверьте параметры и отборы.");
    КонецЕсли;
    

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

← К списку