v8: Хитрая технология виртуальных таблиц для запросовВ 1С имеются виртуальные таблицы, которые очень удобно использовать.
Часто хочется иметь и свои виртуальные таблицы.
Пример показывает, как можно реализовать такие таблицы. | | Автор статьи: Гений 1С Последняя редакция №1 от 04.04.08 URL: http://kb.mista.ru/article.php?id=652 | |
Ключевые слова: запросы, виртуальные таблицы,
Вообще видимо с выходом компоновки данных для 81 технология станет неактуальной, но для 80 все еще актуальна.
Технология позволяет в таблицу значений вытаскивать только нужные поля и ресурсы, что экономит время выполнения запроса и данные уже сразу свернуты.
Может кому и пригодится, юзайте.
Код для вызова виртуальной таблицы за период Дата1-Дата2:
ВыбОтбор=Новый Структура("Договор", ВыбДоговоры);
ПП=Новый Структура();
ПП.Вставить("Отбор", ВыбОтбор);
М=Новый Массив();
М.Добавить("Договор");
М.Добавить("СуммаФактОплата");
М.Добавить("СуммаФактПоставка");
М.Добавить("СуммаНДСФактОплата");
М.Добавить("СуммаНДСФактПоставка");
ПП.Вставить("Поля", М);
ПП.Вставить("Дата1", Дата1);
ПП.Вставить("Дата2", Дата2);
ТЗСуммы=гмВиртуальнаяТаблицаФактическаяПоставкаОплата(ПП);
Функции, описывающи виртуальную таблицу:
//Получаем виртуальную таблицу фактической оплаты или поставки
Функция гмВиртуальнаяТаблицаФактическаяПоставкаОплата(П) Экспорт
обПодготовитьВиртуальнуюТаблицу(П);
//По факту
П.Текст=
"ВЫБРАТЬ
| &Поле_Договор_ КАК Договор,
| &Поле_Статья_ КАК Статья,
| &Поле_ОП_ КАК ОП,
| &Поле_СуммаФактОплата_ КАК СуммаФактОплата,
| &Поле_СуммаНДСФактОплата_ КАК СуммаНДСФактОплата,
| &Поле_СуммаФактПоставка_ КАК СуммаФактПоставка,
| &Поле_СуммаНДСФактПоставка_ КАК СуммаНДСФактПоставка
|ИЗ
| РегистрБухгалтерии.Бюджетирование.Обороты(
| &Дата1,
| &Дата2,
| ,
| Счет В ИЕРАРХИИ (&СчетаДеньги)
| ИЛИ Счет В ИЕРАРХИИ (&СчетаПрибыль),
| ,
| ВариантБюджета = &ВыбБюджет
| И &Условие_Договор_,
| КорСчет В ИЕРАРХИИ (&СчетаКонтрагенты),
| ) КАК Т";
М=Новый Массив();
М.Добавить(ПланыСчетов.Бюджетирование.ДенежныеСредства); //51
П.Параметры.Вставить("СчетаДеньги", М);
М=Новый Массив();
//М.Добавить(ПланыСчетов.Бюджетирование.РасчетыСКонтрагентами); //76.*
М.Добавить(ПланыСчетов.Бюджетирование.Покупатели); //62.*
М.Добавить(ПланыСчетов.Бюджетирование.РасчетыСПоставщиками); //60.1
П.Параметры.Вставить("СчетаКонтрагенты", обПолучитьВложенныеЭлементы("ПланСчетов.Бюджетирование", М));
М=Новый Массив();
М.Добавить(ПланыСчетов.Бюджетирование.Покупатели); //62.*
П.Параметры.Вставить("СчетаПокупатели", обПолучитьВложенныеЭлементы("ПланСчетов.Бюджетирование", М));
М=Новый Массив();
М.Добавить(ПланыСчетов.Бюджетирование.РасчетыСПоставщиками); //60.1
П.Параметры.Вставить("СчетаПоставщики", обПолучитьВложенныеЭлементы("ПланСчетов.Бюджетирование", М));
М=Новый Массив();
М.Добавить(ПланыСчетов.Бюджетирование.ДоходыРасходы); //90
М.Добавить(ПланыСчетов.Бюджетирование.ВнеоборотныеАктивы); //01
Сч001=ПланыСчетов.Бюджетирование.НайтиПоКоду("001");
Если НЕ ЗначениеНеЗаполнено(Сч001) Тогда
М.Добавить(Сч001);
КонецЕсли;
П.Параметры.Вставить("СчетаПрибыль", обПолучитьВложенныеЭлементы("ПланСчетов.Бюджетирование", М));
П.Параметры.Вставить("ВыбБюджет", Справочники.ВариантыБюджета.ИсполнениеБюджетаВторогоУровня); //ФАКТ
П.Параметры.Вставить("ПустоеЗначение_ЗаявкаНаЗакупку_", Документы.ЗаявкаНаЗакупку.ПустаяСсылка());
П.Параметры.Вставить("ПустоеЗначение_Протокол_", Документы.Протокол.ПустаяСсылка());
П.Параметры.Вставить("ПустоеЗначение_Договор_", Документы.КарточкаДоговора.ПустаяСсылка());
П.Параметры.Вставить("ПустоеЗначение_Спецификация_", Документы.Спецификация.ПустаяСсылка());
П.Параметры.Вставить("ПустоеЗначение_Статья_", Справочники.КБК.ПустаяСсылка());
П.Параметры.Вставить("ПустоеЗначение_Лот_", Справочники.НаименованияЗакупаемойПродукции.ПустаяСсылка());
П.Параметры.Вставить("ПустоеЗначение_ЗаявкаНаЗакупку_", Документы.ЗаявкаНаЗакупку.ПустаяСсылка());
П.Параметры.Вставить("ПустоеЗначение_Мероприятие_", Справочники.Мероприятия.ПустаяСсылка());
П.Параметры.Вставить("ПустоеЗначение_ОП_", Справочники.Подразделения.ПустаяСсылка());
//Определения полей
П.Дефиниции.Вставить("Поле_Договор_", "ЕстьNULL(ВЫРАЗИТЬ(Субконто3 КАК Документ.Спецификация).ДоговорОснование, &ПустоеЗначение_Договор_)");
П.Дефиниции.Вставить("Поле_Статья_", "ЕстьNULL(ВЫРАЗИТЬ(Субконто2 КАК Справочник.СтатьиБюджета), &ПустоеЗначение_Статья_)");
П.Дефиниции.Вставить("Поле_ОП_", "ЕстьNULL(ВЫРАЗИТЬ(Субконто1 КАК Справочник.Подразделения), &ПустоеЗначение_ОП_)");
//Определения пустых полей
П.Дефиниции.Вставить("ПустоеПоле_Договор_", "&ПустоеЗначение_Договор_");
П.Дефиниции.Вставить("ПустоеПоле_Статья_", "&ПустоеЗначение_Статья_");
П.Дефиниции.Вставить("ПустоеПоле_ОП_", "&ПустоеЗначение_ОП_");
П.Дефиниции.Вставить("ПустоеПоле_СуммаФактОплата_", "0");
П.Дефиниции.Вставить("ПустоеПоле_СуммаФактПоставка_", "0");
П.Дефиниции.Вставить("ПустоеПоле_СуммаНДСФактОплата_", "0");
П.Дефиниции.Вставить("ПустоеПоле_СуммаНДСФактПоставка_", "0");
//Определение условий
П.Дефиниции.Вставить("Условие_Договор_", "(&Поле_Договор_ В (&Отбор_Договор_))");
//Вычисления
П.Дефиниции.Вставить("Выражение_ЗнакОплаты_",
"
| ВЫБОР
| КОГДА Т.Счет В (&СчетаДеньги)
| И Т.КорСчет В (&СчетаПокупатели)
| ТОГДА 1
| КОГДА Т.Счет В (&СчетаДеньги)
| И Т.КорСчет В (&СчетаПоставщики)
| ТОГДА -1
| ИНАЧЕ 0
| КОНЕЦ
|");
П.Дефиниции.Вставить("Выражение_ЗнакПоставки_",
"
| ВЫБОР
| КОГДА Т.Счет В (&СчетаПрибыль)
| И Т.КорСчет В (&СчетаПокупатели)
| ТОГДА -1
| КОГДА Т.Счет В (&СчетаПрибыль)
| И Т.КорСчет В (&СчетаПоставщики)
| ТОГДА 1
| ИНАЧЕ 0
| КОНЕЦ
|");
П.Дефиниции.Вставить("Поле_СуммаФактОплата_", "&Выражение_ЗнакОплаты_*Т.СуммаОборот");
П.Дефиниции.Вставить("Поле_СуммаФактПоставка_", "&Выражение_ЗнакПоставки_*Т.СуммаОборот");
П.Дефиниции.Вставить("Поле_СуммаНДСФактОплата_", "&Выражение_ЗнакОплаты_*Т.СуммаНДСОборот");
П.Дефиниции.Вставить("Поле_СуммаНДСФактПоставка_", "&Выражение_ЗнакПоставки_*Т.СуммаНДСОборот");
Возврат обРассчитатьВиртуальнуюТаблицу(П);
КонецФункции
//В структуре П виртуальной таблицы должны быть свойтсва:
// Отбор - структура отбора
// Поля - массив полей
Функция обПодготовитьВиртуальнуюТаблицу(П, Пустая=ложь)
Если НЕ П.Свойство("Дефиниции") ИЛИ Пустая Тогда
П.Вставить("Дефиниции", Новый Структура());
КонецЕсли;
Если НЕ П.Свойство("Текст") ИЛИ Пустая Тогда
П.Вставить("Текст", "");
КонецЕсли;
Если НЕ П.Свойство("КонечныйТекст") ИЛИ Пустая Тогда
П.Вставить("КонечныйТекст", "");
КонецЕсли;
Если НЕ П.Свойство("КоличествоЗаменТекстаЗапроса") ИЛИ Пустая Тогда
П.Вставить("КоличествоЗаменТекстаЗапроса", 0);
КонецЕсли;
Если НЕ П.Свойство("Параметры") ИЛИ Пустая Тогда
П.Вставить("Параметры", Новый Структура());
КонецЕсли;
Если НЕ П.Свойство("ТаблицаЗаменыДефиниций") ИЛИ Пустая Тогда
П.Вставить("ТаблицаЗаменыДефиниций", Новый Структура());
КонецЕсли;
Если НЕ П.Свойство("АвтоСписокПолей") ИЛИ Пустая Тогда
П.Вставить("АвтоСписокПолей", истина);
КонецЕсли;
КонецФункции
Функция обРассчитатьВиртуальнуюТаблицу(П)
П.Текст=СтрЗаменить(П.Текст, "&Договор", "ЕстьNULL(ВЫРАЗИТЬ(Субконто3 КАК Документ.Спецификация).ДоговорОснование, &ПустойДоговор)");
//Смотрим, есть ли в параметрах Дата1 И Дата2
Если П.Свойство("Дата1") Тогда
П.Параметры.Вставить("Дата1", П.Дата1);
Иначе
Если НЕ П.Дефиниции.Свойство("Дата1") Тогда
П.Дефиниции.Вставить("Дата1", "");
КонецЕсли;
КонецЕсли;
Если П.Свойство("Дата2") Тогда
П.Параметры.Вставить("Дата2", П.Дата2);
Иначе
Если НЕ П.Дефиниции.Свойство("Дата2") Тогда
П.Дефиниции.Вставить("Дата2", "");
КонецЕсли;
КонецЕсли;
//Убираем ненужные поля
Если П.АвтоСписокПолей Тогда
НаличныеПоля=Новый Структура();
//ПоляКЗамене=Новый Массив;
Для Каждого Эл Из П.Поля Цикл
НаличныеПоля.Вставить("Поле_"+Эл+"_");
КонецЦикла;
Для Каждого КЗ Из П.Дефиниции Цикл
//Проверяем, действительно ли это поле
Если Найти(КЗ.Ключ, "Поле_")=1 И НЕ НаличныеПоля.Свойство(КЗ.Ключ) Тогда
П.Дефиниции.Вставить(КЗ.Ключ, "&ПустоеПоле_"+Сред(КЗ.Ключ, 6));
КонецЕсли;
КонецЦикла;
//Для Каждого Эл ИЗ ПоляКЗамене Цикл
// П.Дефиниции.Вставить(Эл, "&ПустоеПоле_"+Сред(Эл, 6));
//КонецЦикла;
КонецЕсли;
//Делаем замены, пока не исчерпаем
//Вообще неплохо бы отсортировать дефиниции по длине строки, чтобы сначала заменять самые большие
//Пример: &ТекстДоговора и &ТекстДоговора1, сначала надо заменять &ТекстДоговора1
ТЗ=Новый ТаблицаЗначений();
ТЗ.Колонки.Добавить("Имя");
ТЗ.Колонки.Добавить("Длина");
ТЗ.Колонки.Добавить("Замена");
Для Каждого Эл Из П.Дефиниции Цикл
НСтр=ТЗ.Добавить();
НСтр.Имя=Эл.Ключ;
НСтр.Замена=Эл.Значение;
НСтр.Длина=СтрДлина(Эл.Ключ);
КонецЦикла;
ТЗ.Сортировать("Длина Убыв");
П.ТаблицаЗаменыДефиниций=ТЗ;
П.КоличествоЗаменТекстаЗапроса=0;
Пока Истина Цикл
ТекТекст=П.Текст;
Для Каждого Стр Из П.ТаблицаЗаменыДефиниций Цикл
П.Текст=СтрЗаменить(П.Текст, "&"+Стр.Имя, Стр.Замена);
КонецЦикла;
П.КоличествоЗаменТекстаЗапроса=П.КоличествоЗаменТекстаЗапроса+1;
Если ТекТекст=П.Текст Тогда
Прервать;
КонецЕсли;
//Избегаем зацикливания
Если П.КоличествоЗаменТекстаЗапроса>1000 Тогда
Сообщить("Обнаружено зацикливание текста запроса!");
Прервать;
КонецЕсли;
КонецЦикла;
Запрос=Новый Запрос(П.Текст);
Для Каждого Эл ИЗ П.Параметры Цикл
Запрос.УстановитьПараметр(Эл.Ключ, Эл.Значение);
КонецЦикла;
Для Каждого Эл ИЗ П.Отбор Цикл
Запрос.УстановитьПараметр("Отбор_"+Эл.Ключ+"_", Эл.Значение);
КонецЦикла;
ТЗ=Запрос.Выполнить().Выгрузить();
Возврат ТЗ;
КонецФункции
|