Как добавить отбор по дате во внешний отчет с внешним набором данных

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

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

В чем заключается основная сложность

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

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

Шаг 1. Настройка параметров в схеме компоновки

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

  1. Период — тип СтандартныйПериод. Именно его мы выведем пользователю на форму для удобного выбора (например, «Текущий месяц»).
  2. НачалоПериода — тип Дата. В поле «Выражение» укажем &Период.ДатаНачала. Ограничим его использование, установив галочку «Ограничение доступности».
  3. КонецПериода — тип Дата. В поле «Выражение» укажем &Период.ДатаОкончания. Также установим «Ограничение доступности».

Таким образом, пользователь взаимодействует с одним полем, а система автоматически заполняет две переменные даты, которые мы будем использовать в коде.

Шаг 2. Программное извлечение параметров

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

Проанализируем пример кода для получения дат из настроек:


// В начале процедуры всегда отключаем стандартную обработку
СтандартнаяОбработка = Ложь;

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

// Ищем параметр "Период" в настройках
ПараметрПериод = Настройки.ПараметрыДанных.Элементы.Найти("Период");

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

Шаг 3. Использование дат в запросе для внешнего набора данных

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |   Продажи.Ссылка КАК Документ,
    |   Продажи.Дата КАК Дата,
    |   Продажи.СуммаДокумента КАК Сумма
    |ИЗ
    |   Документ.РеализацияТоваровУслуг КАК Продажи
    |ГДЕ
    |   Продажи.Дата МЕЖДУ &Начало И &Конец";

Запрос.УстановитьПараметр("Начало", ДатаНачала);
Запрос.УстановитьПараметр("Конец", ДатаОкончания);

ТаблицаДляСКД = Запрос.Выполнить().Выгрузить();

Обратите внимание: если вы пропустите секцию ГДЕ в программном запросе, ваш отчет всегда будет выводить все данные, сколько бы фильтров вы ни ставили в настройках самого отчета на форме. Это и была главная ошибка в обсуждаемой теме форума.

Шаг 4. Инициализация процесса компоновки

Завершающим этапом является передача подготовленной таблицы в процессор компоновки. Разберем по шагам, как правильно инициализировать все объекты, чтобы внешние данные «подружились» с макетом.


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

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

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

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

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

Важные технические нюансы

Рассмотрим несколько моментов, которые часто упускают из виду:

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

← На главную