При разработке и поддержке конфигураций на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с так называемыми «черными запросами» (штатным механизмом запросов v7). Одним из неочевидных моментов для начинающих разработчиков или тех, кто переходит с «восьмерки», является поведение отборов по периоду при выборке документов. Разберем детально, как работает конструкция Период С ... ПО ..., по каким реквизитам происходит фильтрация, и какие критически важные нюансы необходимо учитывать, чтобы запрос возвращал корректные данные.
Рассмотрим классическую конструкцию, которая задает временной интервал для выполнения запроса:
|Период с ВыбНачПериода по ВыбКонПериода;
Когда мы строим запрос, направленный на выборку документов, эта конструкция выполняет фильтрацию строго по дате документа. Программа анализирует дату создания и проведения каждого документа и сопоставляет ее с границами указанного периода.
Однако простого указания дат часто бывает недостаточно. В отличие от объектных выборок, механизм запросов 1С 7.7 имеет встроенные предопределенные фильтры, которые по умолчанию отсекают часть документов. Если их не учесть, вы можете получить пустой результат или неполную выборку.
По умолчанию «черный» запрос в 1С 7.7 устроен так, что он выбирает только проведенные документы. Если вы просто напишете условие по периоду, то непроведенные документы (даже если они физически существуют в базе за этот интервал времени) в выборку не попадут.
Для управления этим поведением используется специальная директива ОбрабатыватьДокументы. Проанализируем возможные варианты ее использования:
|ОбрабатыватьДокументы Проведенные;
В этом случае запрос вернет только те документы, которые были успешно проведены в системе.
|ОбрабатыватьДокументы НеПроведенные;
Все:
|ОбрабатыватьДокументы Все;
Помимо статуса проведения, у документов существует статус пометки на удаление. За это отвечает другая директива — Обрабатывать. По умолчанию система игнорирует удаленные объекты. Если вам нужно включить их в отчет или, наоборот, проанализировать только удаленные за период документы, используйте следующие конструкции:
|Обрабатывать НеПомеченныеНаУдаление; (режим по умолчанию) — исключает корзину из результатов.|Обрабатывать ПомеченныеНаУдаление; — выберет только удаленные.|Обрабатывать Все; — выберет и «живые», и помеченные на удаление документы.Рассмотрим пример комплексного запроса, который гарантированно выберет вообще все документы конкретного вида за указанный период, независимо от их состояния:
// Создаем объект Запрос
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса =
"//{{ЗАПРОС(ВыборкаДокументов)
|Период с ВыбНачПериода по ВыбКонПериода;
|ОбрабатыватьДокументы Все;
|Обрабатывать Все;
|ТекущийДок = Документ.Реализация.ТекущийДокумент;
|Группировка ТекущийДок;
|"//}}ЗАПРОС
;
Если Запрос.Выполнить(ТекстЗапроса) = 0 Тогда
Возврат;
КонецЕсли;
Разберем по шагам, как именно позиционируются границы периода в зависимости от типов передаваемых переменных. Это принципиальное отличие 1С 7.7 от современных версий платформы (таких как 1С 8.3).
Вариант 1: В качестве параметров переданы переменные типа «Дата».
Если в ВыбНачПериода и ВыбКонПериода находятся обычные даты (например, 01.10.2023 и 31.10.2023), то платформа автоматически установит время начала на 00:00:00 стартового дня, а время окончания — на 23:59:59 конечного дня. Никаких дополнительных преобразований (вроде функции КонецДня() в v8) делать не требуется.
Вариант 2: Переданы переменные типа «Документ» или «Позиция документа».
Если в качестве границы передать ссылку на конкретный документ, то система ограничит выборку точным моментом времени (позицией) этого документа на временной оси. Это позволяет делать высокоточные запросы, например, выбирать документы строго «до» или «после» определенного события внутри одного дня.
Если полностью убрать конструкцию Период С ... ПО ... из текста запроса, система не будет сканировать базу за все время существования. Поведение платформы жестко предопределено:
При работе с черными запросами в 1С 7.7 существует старый зарегистрированный баг платформы. Если попытаться вытащить время документа непосредственно через обращение к реквизитам внутри тела запроса, например, так:
|ВремяДок = Документ.Реализация.ВремяДок; // Внимание: так делать не рекомендуется!
то на выходе вы рискуете получить некорректные данные (пустые значения, нули или сбитые секунды).
Правильное решение проблемы: В самом запросе необходимо выбирать только ссылку на документ (ТекущийДокумент). А уже затем, при обходе результатов запроса в цикле, получать время документа стандартным методом объектной модели:
Пока Запрос.Группировка(1) = 1 Цикл
Док = Запрос.ТекущийДок;
// Получаем корректное время документа вне тела запроса
Док.ПолучитьВремя(Часы, Минуты, Секунды);
Сообщить("Документ " + Док + " создан в " + Часы + ":" + Минуты);
КонецЦикла;
На больших базах данных (особенно при использовании файловой версии DBF) «черный» запрос по документам за протяженный период может работать крайне медленно. Происходит это потому, что движок v7 выполняет последовательное сканирование физической таблицы журнала документов 1CJOURN.
Если перед вами стоит задача оптимизации производительности, рассмотрите следующие альтернативы:
ВыбратьДокументы() с графой отбора.
ВыбратьДокументы(НачДата, КонДата);