Почему новые поля запроса не появляются в результате программного формирования отчета СКД?

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

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

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

Рассмотрим пример кода, который демонстрирует эту ситуацию:


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

В этом коде ошибка заключается в порядке действий. Мы сначала выполняем компоновку макета (КомпМакета.Выполнить()) на основе существующей СхемыКомпоновкиДанных и Настроек, а уже потом пытаемся изменить запрос в *сформированном макете* (МакетКомп.НаборыДанных.НаборДанных1.Запрос = ВернутьЗапрос(...)). К этому моменту макет уже "зафиксировал" структуру данных, которую он ожидает, и изменение запроса в нем не приведет к автоматическому обновлению этой структуры.

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

Пошаговое решение: Как правильно добавить новые поля в программно формируемый отчет СКД

Для успешного включения новых полей запроса в результат компоновки данных, мы должны последовательно выполнить следующие шаги:

  1. Обновить текст запроса в схеме компоновки данных.
  2. Зарегистрировать новые поля в самой схеме компоновки данных.
  3. Включить эти поля в настройки компоновки данных.
  4. Выполнить компоновку, используя обновленные схему и настройки.

Давайте разберем каждый шаг подробнее.

Шаг 1: Обновление текста запроса в схеме компоновки данных

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


// Предполагаем, что СхемаКомпоновки уже загружена или создана
// СхемаКомпоновки = ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных").ПолучитьСхему();

// Получаем набор данных, обычно это первый набор данных в коллекции
// Если у вас несколько наборов данных, убедитесь, что обращаетесь к правильному
Если СхемаКомпоновки.НаборыДанных.Количество() > 0 Тогда
    НаборДанныхЗапрос = СхемаКомпоновки.НаборыДанных[0]; // Предполагаем, что это НаборДанныхЗапросСхемыКомпоновкиДанных
    // Важно: изменить свойство Запрос у самого объекта схемы, а не у макета
    НаборДанныхЗапрос.Запрос = ВернутьЗапрос(ОтборПоОрг, ОтборПоКассе_ККМ, ОтборПоКассе_);
Иначе
    Сообщить("В схеме компоновки данных не найдено ни одного набора данных.");
    Возврат;
КонецЕсли;

Мы должны изменить свойство Запрос у объекта НаборДанныхЗапросСхемыКомпоновкиДанных, который находится в коллекции НаборыДанных нашей СхемыКомпоновкиДанных.

Шаг 2: Регистрация новых полей в схеме компоновки данных

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

Существует два основных способа сделать это:

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

НаборДанныхЗапрос.АвтоЗаполнениеДоступныхПолей = Истина;
// Этот шаг должен быть выполнен после изменения запроса,
// но до того, как схема будет использована для построения макета.
// Это заставит СКД обновить список доступных полей на основе нового запроса.

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

Ручное добавление полей (если нужна точная настройка)

Если нам требуется более тонкий контроль над полями, например, для определения их как ресурсов или установки определенных типов значений, мы можем добавить их вручную. Предположим, вы добавили в запрос поле "НовоеПолеСумма" и хотите сделать его ресурсом.


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

// Добавляем существующие поля, если они нужны, или используем АвтоЗаполнение для них

// Добавляем новое поле
НовоеПоле = НаборДанныхЗапрос.Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
НовоеПоле.Имя = "НовоеПолеСумма";
НовоеПоле.ПутьКДанным = "НовоеПолеСумма";
// Указываем тип значения, если он известен
НовоеПоле.ТипЗначения = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2));

// Если поле является ресурсом (как было упомянуто автором в сообщении 3)
// его также нужно добавить в коллекцию Ресурсов схемы.
// Имя ресурса должно совпадать с именем поля.
Ресурс = СхемаКомпоновки.Ресурсы.Добавить(Тип("РесурсСхемыКомпоновкиДанных"));
Ресурс.Имя = "НовоеПолеСумма";
Ресурс.Выражение = "Сумма(НовоеПолеСумма)"; // Пример агрегатной функции

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

Шаг 3: Включение полей в настройки компоновки данных

Даже если поля зарегистрированы в схеме, они не появятся в отчете или коллекции значений автоматически. Их необходимо явно включить в НастройкиКомпоновкиДанных. Это означает, что мы должны добавить их в "Выбранные поля" в структуре отчета (например, в детальных записях или группировках).

Предположим, мы хотим добавить "НовоеПолеСумма" в детальные записи отчета. Сначала нам нужно получить текущие настройки:


// Предполагаем, что Настройки уже получены (Настройки = СхемаКомпоновки.НастройкиПоУмолчанию;)
// или загружены из варианта отчета.

// Получаем элемент структуры отчета, например, ДетальныеЗаписи
// Если у вас сложная структура, нужно пройтись по ее элементам
ЭлементСтруктуры = Настройки.Структура.Найти("ДетальныеЗаписи"); // Пример: найти детальные записи

Если ЭлементСтруктуры <> Неопределено Тогда
    // Добавляем новое выбранное поле в коллекцию Выбор
    ВыбранноеПоле = ЭлементСтруктуры.Выбор.Элементы.Добавить(Тип("ВыбранноеПолеКомпоновкиДанных"));
    ВыбранноеПоле.Поле = Новый ПолеКомпоновкиДанных("НовоеПолеСумма");
    
    // Если требуется добавить все поля из схемы автоматически в выбранные поля
    // можно использовать АвтоВыбранноеПолеКомпоновкиДанных
    // ВыбранноеПоле = ЭлементСтруктуры.Выбор.Элементы.Добавить(Тип("АвтоВыбранноеПолеКомпоновкиДанных"));
    // Это аналог флажка "Автоматически заполнять" в настройках отчета
Иначе
    Сообщить("Элемент структуры 'ДетальныеЗаписи' не найден в настройках.");
КонецЕсли;

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

Шаг 4: Выполнение компоновки с обновленной схемой и настройками

Теперь, когда СхемаКомпоновкиДанных содержит обновленный запрос и зарегистрированные поля, а НастройкиКомпоновкиДанных включают эти поля в выбор, мы можем корректно выполнить компоновку:


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

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

После этих изменений ТаблицаДляОбработки должна содержать все добавленные поля.

Особые моменты и отладка

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

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

← На главную