В форме диалога местной базы несколько реквизитов диалога (либо местные переменные):
Даты периода (НачДата и КонДата)
Элементы справочников для фильтрации (ВыбТовар, ВыбФирма, ВыбКлиент, и т.д.)
Какие-либо флажки (ТолькоЗамерзающийЗимойТовар , ..)
Мы начинаем писать запрос и сразу попадаем в такую ловушку:
ТекстЗапроса = " Период с НачДата по КонДата; "; |
Вроде все в порядке, но такой запрос не выполнится в базе OLE, так как там понятия не имеют, что такое НачДата и КонДата :)) Ведь эти переменные действительны только для местной базы! Переписываем запрос заново:
ТекстЗапроса = " Период с '" + НачДата + "' по '" + КонДата + "'; // Будет типа '01.01.02' // т.е. прямое представление даты, которое всегда поймет любой запрос | Товар = Регистр.ОстаткиТоваров.Товар; | Фирма = Регистр.ОстаткиТоваров.Фирма; | Склад = Регистр.ОстаткиТоваров.Склад; | Остаток = Регистр.ОстаткиТоваров.Остаток; | Группировка Товар без групп; | Группировка Документ; | Функция НачОст = НачОст(Остаток); | Функция КонОст = КонОст(Остаток); | Функция ПрихОст = Приход(Остаток); | Функция РасхОст = Расход(Остаток);"; |
Так... Дошли до условий отбора в запросе. Рассмотрим два варианта, когда выбран ВыбТовар:
// 1-й вариант - когда выбран элемент справочника (не группа). // Самый простой случай - коды товаров совпадают абсолютно // Вариант 1а. Если ВыбТовар.Выбран()=1 Тогда ТекстЗапроса = ТекстЗапроса + " | Условие (Товар.Код = " +ВыбТовар.Код+");"; КонецЕсли; // Вариант 1б. Чтоб запрос быстрее был: // Вначале добавим к запросу переменную в общем списке: | КодТовара = Регистр.ОстаткиТоваров.Товар.Код; // А уж потом добавим к запросу условие (такое условие будет выполнятся проще, так как // запрос при формировании таблицы запроса сразу сформирует отдельную колонку кодов и по // ней уже будет отбирать, а не будет каждый раз при обработке товаров извлекать из них // код): Если ВыбТовар.Выбран()=1 Тогда ТекстЗапроса = ТекстЗапроса + " | Условие (КодТовара = " +ВыбТовар.Код+");"; КонецЕсли; |
Казалось бы все очень просто. По аналогии - если уникальность для товаров ведется по наименованию, то простой заменой слова "код" на "наименование" мы решаем вопрос и здесь. Теперь рассмотрим, когда мы выбрали группу, т.е. текст условия должен будет выглядеть так:
| Условие (Товар.ПринадлежитГруппе(КакаяТоГруппа)=1); |
И здесь, правда можно проблему решить "двумями путями" :)) Первый пусть - когда мы имеем дело с двухуровне вымсправочником. Тогда проблема группы решается также просто, как и в 1-м варианте:
// Добавляем в списке переменных строку: | КодРодителя = Регистр.ОстаткиТоваров.Товар.Родитель.Код; // Далее пишем условие: Если ВыбТовар.Выбран()=1 Тогда ТекстЗапроса = ТекстЗапроса + " | Условие (КодРодителя = " +ВыбТовар.Код+");"; КонецЕсли; // В качестве домашнего задания - переписать условие по наименоваиню :))) |
А если справочник очень даже многоуровневый? Вот для этого мы и используем написанную ранее функцию. Предположим, что список значений запроса с индексом массива " 1 " мы будем использовать для хранения подобных значений (например, хранить в нем группы товаров, клиентов) для хитрых условий. Итак, например, в ВыбТовар у нас указана группа товаров, а в ВыбКлиент - группа клиентов, которым мы товары группы ВыбТовар продавали. Кроме того, мы должны пропустить накладные возвратов поставщикам, и не забыть, что товары надо еще отбирать по флажку ТолькоЗамерзающийЗимойТовар:
// Очистим список значений запроса Результат = БазаОле.EvalExpr("СкорректироватьСписок(1, 1)"); // Закинем в список значений запроса группу товаров (он сам найдет ее в базе OLE) // И запоминаем (в уме), что этой группе соответствует 1-е значение списка Результат = БазаОле.EvalExpr("СкорректироватьСписок(1, 2 , ""Справочник"", """ + Выбтовар.Вид())+ """, " + ВыбТовар.Код + ", """ + ВыбТовар.Наименование + """)"); // Теперь закинем в список значений запроса группу клиентов // И запоминаем, что этой группе соответствует 2-е значение списка Результат = БазаОле.EvalExpr("СкорректироватьСписок(1, 2 , ""Справочник"", """ + ВыбКлиент.Вид())+ """, " + ВыбКлиент.Код + ", """ + ВыбКлиент.Наименование + """)"); // А еще до кучи и фирму из ВыбФирма // И запоминаем, что этой фирме соответствует 3-е значение списка Результат = БазаОле.EvalExpr("СкорректироватьСписок(1, 2 , ""Справочник"", """ + ВыбФирма.Вид())+ """, " + ВыбФирма.Код + ", """ + ВыбФирма.Наименование + """)"); // Теперь формируем текст запроса ТекстЗапроса = " Период с '"+НачДата+ "' по '"+КонДата+"'; | Товар = Документ.РасходнаяНакладная.Товар; | Замерзает = Документ.РасходнаяНакладная.Товар.ЗамерзаетЗимой; | Признак = Документ.РасходнаяНакладная.ПризнакНакладной; | Фирма = Документ.РасходнаяНакладная.Фирма; | Клиент = Документ.РасходнаяНакладная.Клиент; | Количество = Документ.РасходнаяНакладная.Количество; | СуммаДок = Документ.РасходнаяНакладная.Сумма; | Группировка Товар без групп; | Группировка Документ; | Функция СуммаОтгрузки=Сумма(СуммаДок); | Условие (Признак<>Перечисление.ПризнРасхНакл.ВозвратПоставщику); | Условие (Замерзает = " + ТолькоЗамерзающийЗимойТовар + "); // Внимание! Начинается: | Условие (Товар.ПринадлежитГруппе(СписокЗначенийЗапроса[1].ПолучитьЗначение(1))=1); | Условие (Клиент.ПринадлежитГруппе(СписокЗначенийЗапроса[1].ПолучитьЗначение(2))=1); | Условие (Фирма= СписокЗначенийЗапроса[1].ПолучитьЗначение(3));"; |
Уфф. Вроде все… Остается только запустить запрос:
Запрос = БазаОле.CreateObject("Запрос"); Если Запрос.Выполнить(ТекстЗапроса)=0 Тогда Предупреждение("Запрос безутешен!"); Возврат; КонецЕсли; |
Ну, а с реквизитами запроса разбираемся так же, как указано было выше в предыдущих разделах… И не забываем, что кроме хранения конкретных значений, можно использовать другие списки значений запроса. Например, можно заполнить какой-либо список значений запроса списком клиентов и использовать его в запросе:
// Всякими правдами/неправдами заполнили список значений (хотя бы через другой запрос :)) // конкретными клиентами… // Предположим, индекс массива равен "2". Тогда в тексте запроса появится следующее: | Условие (Клиенты в СписокЗначенийЗапроса[2]); |
P.S. Чего еще нет: перенос реквизитов неограниченной длины, более подробно остановиться на "периодических реквихитах"…
ГРОМАДНЕЙШИЕ ИЗВИНЕНИЯ ЗА ВОЗМОЖНЫЕ СИНТАКСИЧЕСКИЕ И ОРФОГРАФИЧЕСКИЕ ОШИБКИ В ДОКУМЕНТЕ - ПИСАЛ БЕЗ ПРОВЕРКИ В 1С, БОЛЬШУЮ ЧАСТЬ - ПО ПАМЯТИ. ЕСЛИ ОБНАРУЖИТЕ ОШИБКИ, ДА И ВООБЩЕ, ЕСЛИ ЕСТЬ ВОПРОСЫ ПО OLE - ПИШИТЕ. ЕСЛИ ВЫКРОЮ ВРЕМЯ, ТО ПОИЩУ РЕШЕНИЕ…
С наилучшими пожеланиями, Руководитель информационно-технического отдела ООО МФФ "Аконит" Егоров Андрей Викторович