gifts2017

Выполнить пакетный запрос ПостроителемОтчета?

Опубликовал Сергей (MoneG2) в раздел Программирование - Практика программирования

Выполнить пакетный запрос ПостроителемОтчета? Может каждый, но у вас не было времени :)

 

Не секрет, что ПостроительОтчета "не переваривает" пакетные запросы, однако можно поместить во временную таблицу результат некого (одного) запроса. "Ну и что?" - скажете Вы, - "Как потом такую ВТ прочитать и использовать??".
Тем не менее, всё предельно просто, если воспользоваться внешним по отношению в ПостроителюОтчета МенеджеромВременныхТаблиц, например, по такой схеме:

1)

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

Функция ВыполнитьПакетВПостроителе(МенеджерВТ)

       Построитель.Текст = 
       "ВЫБРАТЬ
       //..
       |ПОМЕСТИТЬ ВТ1
       |ИЗ
       //
       |
       |{ГДЕ
       |   Условие1 ,
       //....
       |   ОтборN
       | }
       |"
;

       Запрос = Построитель.ПолучитьЗапрос();
       Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
       Запрос.Текст = Запрос.Текст
+
       "
       |;
       |ВЫБРАТЬ

       //...
       |ИЗ ВТ1 КАК ВТ1
       //...
       |;
       |УНИЧТОЖИТЬ ВТ1;
       |"
;

       Возврат Запрос.Выполнить();

КонецФункции

Заметим, что ";" (точка с запятой), необходимая для первой ВТ, стоит не в текст  ПостроителяОтчета, а в тексте доработанного запроса. Это связано с тем, что  ПостроительОтчета, хоть и помещает результат во временную таблицу, но в тексте  своего запроса окончание (";") "съедает".

2) Если перед вызовом функции ВыполнитьПакетВПостроителе() настройки (Отбор,  ПараметрыДанных) были установлены, то простенький тестовый примерчик порадует  своей работоспособностью.
А что если решение задачи "требует" использования разных выборок данных в  различных разрезах, представлениях и т.п., причем желательно с использованием  однажды установленных пользователем настроек?
Очевидно, расширить схему:

Функция ВыполнитьПакетВПостроителе(МенеджерВТ)

       // Выборка1 с использованием настроек
       Построитель.Текст = 
       "ВЫБРАТЬ
       //..
       |ПОМЕСТИТЬ ВТ1
       |ИЗ
       //
       |
       |{ГДЕ
       |     Условие1 ,

       //....
       |     ОтборN
       | }
       |"
;

       Запрос = Построитель.ПолучитьЗапрос();
       Запрос.МенеджерВременныхТаблиц = МенеджерВТ;
       Запрос.Текст = Запрос.Текст
+
       "
       |;
       |ВЫБРАТЬ
       //...
       |ИЗ ВТ1 КАК ВТ1
       //...
       |;
       |УНИЧТОЖИТЬ ВТ1;
       |"
;

       Запрос.Выполнить();

       // Выборка2 с использованием настроек, но в том же пакете 
       Построитель.Текст = 
       "ВЫБРАТЬ
       //..
       |ПОМЕСТИТЬ ВТ2
       |ИЗ
       //
       |
       |{ГДЕ
       |    Условие2 ,

       //....
       |    ОтборK
       | }
       |"
;

       Запрос = Построитель.ПолучитьЗапрос();
       Запрос.МенеджерВременныхТаблиц = МенеджерВТ; // менеджер тот же
       Запрос.Текст = Запрос.Текст
+
       "
       |;
       |ВЫБРАТЬ
       //...
       |ИЗ ВТ1 КАК ВТ1
       |ЛЕВОЕ СОЕДИНЕНИЕ ВТ2 КАК ВТ2
       |ПО ВТ1.//...
       //...
       |;
       |УНИЧТОЖИТЬ ВТ1;
       |УНИЧТОЖИТЬ ВТ2;
       |"
;

       Возврат Запрос.Выполнить();

КонецФункции

3) На первый взгляд, дополнение 2) уже лучше. Но. Без "Но" ну никуда... Всякий  раз, когда текст Построителя меняется, система меняет в соответствии с текстом  и коллекцию ДоступныхПолей, в том числе и у отбора. И эта ситуация, мягко  говоря, неприятна.
Поэтому перед каждой генерацией запроса от Построителя, необходимо "руками"  указывать ему, где он прав и где виноват:

 //...
 УстановитьОтборИПараметры();
 Запрос = Построитель.ПолучитьЗапрос
();
 //...

Процедура УстановитьОтборИПараметры()

       //Отбор
       Доступные = Построитель.Отбор.ПолучитьДоступныеПоля();
       Поле = Доступные.Найти("ПараметрОтбора1");
       Если Поле <> Неопределено Тогда
              Поле.Отбор = Истина;

              Элт = Построитель.Отбор.Найти("ПараметрОтбора1");
              Если Элт = Неопределено Тогда
                    Элт = Построитель.Отбор.Добавить("ПараметрОтбора1");
                    //...
                    Элт.Использование
= Истина;
              КонецЕсли;
       КонецЕсли;
       // другие поля отбора...

       Построитель.Отбор.УстановитьДоступныеПоля(Доступные);


       //ПараметрыДанных

       Если НЕ Построитель.Параметры.Свойство("ПараметрДанных1") Тогда
             Построитель.Параметры.Вставить
("ПараметрДанных1",Истина);
       КонецЕсли;
       // другие параметры данных...

КонецПроцедуры

4) Еще одно "Но". Чтобы при написании текста пакета (выполнении запроса)  совсем уж не задумываться, "где он там найдет все параметры", Построитель нужно  проинициализировать каким-нибудь "общим" текстом, в котором будут участвовать  все необходимые отборы и параметры. Для этого не обязательно строить  Вавилонскую башню, достаточно минимально адекватного запроса вида:

 //..
 "ВЫБРАТЬ ЛОЖЬ
 |ИЗ <ВиртуальнаяТаблица>(&ДатаСреза, &ВидыСубконто {Отбор_1.*} ) КАК Запрос
 |{ЛЕВОЕ СОЕДИНЕНИЕ ...}
 |{ГДЕ Отбор1, Отбор2.* КАК Отбор2}
 |"
;
 //..

5) Вспомним о пользователе. Чтобы он "ничего не заметил", необходимо после  вызова функции ВыполнитьПакетВПостроителе() проиницилизировать  ПостроительОтчета "общим" текстом и еще раз УстановитьОтборИПараметры().

.. а кто слушал - молодец!

См. также

Подписаться Добавить вознаграждение
Комментарии
1. direktorSan (direktorSan) 24.03.10 18:37
Может я НЕ понял сути статьи, но вот такая конструкция у меня отрабатывает на ура:
п = Новый ПостроительОтчета;
п.Текст = "выбрать истина поместить т1;
|выбрать * из т1
|объединить
|выбрать ложь";
п.Выполнить();
т = п.Результат.Выгрузить();
2. direktorSan (direktorSan) 24.03.10 18:44
К сожалению, не смог отредактировать свой предыдущий коммент...

Построитель отчета НЕ переваривает передачу ему через параметр таблицы значений для использования оной в запросе в качестве источника данных...

А пакетные запросы он давно переваривает без каких-либо ухищрений.
3. Сергей (MoneG2) 26.03.10 05:36
Да, согласен.
В моей задаче нужно было выгружать промежуточный результат в ТЗ. Ну а до менеджера ВТ у Построителя не достучаться )) И потом сильно смущало, когда Построитель.ПолучитьЗапрос().Текст - пустой, если в пакете больше, чем 1 ВТ.