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

Программист 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. Использование Консоли СКД: Специализированные инструменты, такие как Консоль запросов УФ (мод от Dr.Zombi), позволяют импортировать вашу схему, применять к ней различные настройки и, самое главное, просматривать итоговый запрос, генерируемый платформой. Это помогает выявить расхождения между тем, что вы ожидаете, и тем, что фактически отправляется в базу данных.
  2. Программный вывод запроса: Мы можем временно добавить код в процедуру, которая формирует отчет, чтобы получить текст запроса, сформированного компоновщиком макета. Для этого нам потребуется получить текст запроса из объекта МакетКомпоновки.

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

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

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

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

← На главную