gifts2017

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

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

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

Суть метода

 

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

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

      

ВЫБРАТЬ

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

             …

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

       ГДЕ

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

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

             Метка,

             НомерСтроки


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

      

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

 

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

 

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


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

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

 

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

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

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

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

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

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

      

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


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

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

Пример:

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

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

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

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

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

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

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

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

      

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

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

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

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

       Иначе

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

       КонецЕсли;

      

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

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

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

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

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

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

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

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

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

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

            

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

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

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

            

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

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

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

       КонецЦикла;

      

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

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

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

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

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

            

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

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

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

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

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

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

             КонецЦикла;

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

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

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

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

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

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

             Иначе

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

             КонецЕсли;

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

             //Берем дату

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

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

            

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

            

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

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

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

       КонецЕсли;

 

 

      

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

      

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

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
down.zip
.zip 10,52Kb
15.02.12
19
.zip 10,52Kb 19 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Модератор раздела Артур Аюханов (artbear) 17.02.12 10:09
Подход давно известен, конечно, применимость его очень редкая :)
Но для начинающих подойдет.
Но обязательно нужно упомянуть, что печать незаписанных документов может приводить к расхождениям бумажных документов и документов в базе.
ИМХО Название "виртуальный документ" нужно заменить на более точный термин - типа "Незаписанный документ" и т.п.
2. Осипов Сергей (fixin) 17.02.12 10:34
(1) не знаю, не знаю. я допёр сам до этого "широко известного подхода".

Здесь вроде бы были еще комменты про то, как начать транзакцию, изменить и распечатать. У меня глюки, происки модеров или глюк форума?
3. Александр Зубцов (iov) 17.02.12 13:01
(0) Конечно подход интересен но учитывая присутствие в типовых механизмов проверки на модифицированность объекта
сводит на нет многие потуги. и приходится добавлять разнообразно извращенные механизмы.
Почти согласен с применением серийных номеров/серий/характеристик и прочая типовая_геммороидальная_супер_нано_техноголия которая дает нам работу (можно как молитву перед едой читать) но самый частый вопрос - кто изменил документ и что там изменилось.
Но это нисколько не принижает достоинства приведенного метода.
+ в карму
4. Модератор раздела Сергей Лунев (luns) 22.02.12 13:02
(2) когда сообщение скрыто, нумерация остается:

Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа