Виртуализация документов в запросах

В типовых конфигурациях при печати документов обычно используется запрос к базе данных для получения данных о документе. Это не всегда удобно, когда требуется вместо реального объекта отправить на печать модифицированный, измененный объект. В таких случаях рекомендую не переписывать запросы типовых, а использовать виртуализацию запросов.

Суть метода

 

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

Например, в типовой конфигурации УТ есть запрос по печати расходной накладной в модуле объекта:

       ВЫБРАТЬ

             РеализацияТоваровУслуг.Номенклатура,

             …

             Документ.РеализацияТоваровУслуг.ВозвратнаяТара КАК РеализацияТоваровУслуг

       ГДЕ

             РеализацияТоваровУслуг.Ссылка = &ТекущийДокумент

       УПОРЯДОЧИТЬ ПО

             Метка,

             НомерСтроки

Этот запрос помещается в текст запроса Запрос.Текст, затем вызывается выполнение:

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

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

ОбработатьЗапросПоВиртуальномуДокументу(Запрос, Ссылка.ПолучитьОбъект(), ЭтотОбъект());

Этот метод заменяет обращения к таблицам документа на обращения к виртуальным таблицам, помещаемым в менеджер временных таблиц.

Функция позволяет можно заменить табличные части и реквизиты шапки документа.

 

Более интересное применение виртуализации – модификация документа перед его проведением.

Например, в УТ серии должны храниться в документе по одной строке на каждую серию. Это неудобно для пользователей. Поэтому можно серии вынести в отдельную таблицу, но при проведении эмулировать документ с заполненными сериями, т.е. проставлять для каждой строки серию. В этом случае и пригодится вызов виртуализации при контроле остатков, запросе по табличной части документа и т.п.

Демонстрационная обработка для УТ

В обработке-примере используется документ РеализацияТоваровУслуг из УТ.

В обработку скопирована процедура печати накладной.

Перед вызовом каждого из двух запросов добавлена строка:

       ОбработатьЗапросПоВиртуальномуДокументу(Запрос, Ссылка.ПолучитьОбъект(), ЭтотОбъект);

Этого достаточно, чтобы печатная форма брала объект из памяти, а не из базы данных. Сравните с трудоемкостью изменения запроса, если бы вы захотели сделать это другим способом!

В форме можно нажать кнопку «Показать форму документа», внести изменения в документ, затем, не закрывая форму документа, нажать кнопку «Распечатать документ» и получить печатную форму накладной по несохраненному в базе объекту.

Пример:

Открываем обработку, выбираем документ:

Открываем документ:

Нажимаем распечатать:

Модифицируем номер, контрагента и количество товара в первой строке:

Нажимаем распечатать:

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

Код процедуры виртуализации

Функция ОбработатьЗапросПоВиртуальномуДокументу(Запрос, ДокументОбъект, ДокументОбъектНовый) Экспорт

      

       ЗапросТМП = Новый Запрос();

       Если  Запрос.МенеджерВременныхТаблиц = Неопределено Тогда

             ЗапросТМП.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

             Запрос.МенеджерВременныхТаблиц=ЗапросТМП.МенеджерВременныхТаблиц;

       Иначе

             ЗапросТМП.МенеджерВременныхТаблиц = Запрос.МенеджерВременныхТаблиц;

       КонецЕсли;

      

       //Заменяем запрос к документу на запрос к таблице...

       ИмяДокумента = ДокументОбъект.Метаданные().Имя;

       МД = ДокументОбъект.Метаданные();

       ТипСсылка = Новый ОписаниеТипов("ДокументСсылка." + ИмяДокумента);

       Для Каждого МДТЧ ИЗ МД.ТабличныеЧасти Цикл

             ИмяТЧ = МДТЧ.Имя; //Идентификатор табличной части

             МаскаТЧ = "Документ." + ИмяДокумента + "." + ИмяТЧ;

             Если Найти(Запрос.Текст, МаскаТЧ) = 0 Тогда Продолжить; КонецЕсли;

             ИмяВТ = "ВТТаб" + ИмяТЧ;//Идентификатор временной таблицы

             Запрос.Текст = СтрЗаменить(Запрос.Текст, МаскаТЧ, " " + ИмяВТ + " ");

            

             ТЗТабличнаяЧасть = ДокументОбъектНовый[ИмяТЧ].Выгрузить();

             ТЗТабличнаяЧасть.Колонки.Добавить("Ссылка", ТипСсылка);

             ТЗТабличнаяЧасть.ЗаполнитьЗначения(ДокументОбъект.Ссылка, "Ссылка");

            

             ЗапросТМП.Текст = "Выбрать * ПОМЕСТИТЬ " + ИмяВТ + " Из &Таб Как Т";

             ЗапросТМП.УстановитьПараметр("Таб", ТЗТабличнаяЧасть);

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

       КонецЦикла;

      

       //Заменяем запросы к шапке

       МаскаШапки = "Документ." + ИмяДокумента;

       Если Найти(Запрос.Текст, МаскаШапки) <> 0 Тогда

             ИмяВТ = "ВТТабШапка" ;//Идентификатор временной таблицы

             Запрос.Текст = СтрЗаменить(Запрос.Текст, МаскаШапки, " " + ИмяВТ + " ");

            

             //Делаем одну строку таблицы на шапку

             ТЗШапка = Новый ТаблицаЗначений();

             СтрокаШапки = ТЗШапка.Добавить();

             //Берем реквизиты шапки

             Для Каждого МДРеквизит ИЗ МД.Реквизиты Цикл

                    ТЗШапка.Колонки.Добавить(МДРеквизит.Имя, МДРеквизит.Тип);

             КонецЦикла;

             //Берем ссылку

             ТЗШапка.Колонки.Добавить("Ссылка", ТипСсылка);

             //СтрокаШапки.Ссылка = ДокументОбъект.Ссылка;

             //Берем номер

             Если МД.ТипНомера = Метаданные.СвойстваОбъектов.ТипНомераДокумента.Строка Тогда

                    ТЗШапка.Колонки.Добавить("Номер", Новый ОписаниеТипов("Строка",,Новый КвалификаторыСтроки(МД.ДлинаНомера)));

             Иначе

                    ТЗШапка.Колонки.Добавить("Номер", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(МД.ДлинаНомера)));

             КонецЕсли;

             //СтрокаШапки.Номер = ДокументОбъектНовый.Номер;

             //Берем дату

             ТЗШапка.Колонки.Добавить("Дата", Новый ОписаниеТипов("Дата",,, Новый КвалификаторыДаты(ЧастиДаты.ДатаВремя)));

             //СтрокаШапки.Дата = ДокументОбъектНовый.Дата;

            

             ЗаполнитьЗначенияСвойств(СтрокаШапки, ДокументОбъектНовый);

            

             ЗапросТМП.Текст = "Выбрать * ПОМЕСТИТЬ " + ИмяВТ + " Из &Таб Как Т";

             ЗапросТМП.УстановитьПараметр("Таб", ТЗШапка);

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

       КонецЕсли;

 

 

      

       Возврат ДокументОбъектНовый;

      

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

Скачать