В практике разработки на платформе 1С:Предприятие 7.7 программисты часто сталкиваются с ситуацией, когда стандартный объект Запрос возвращает только проведенные документы, игнорируя те, что были просто записаны. Это может стать серьезной проблемой при построении отчетов по заказам, анализе планируемых поступлений или проверке корректности ввода данных. Разберем подробно, почему так происходит и какие механизмы платформы влияют на состав выборки.
Проанализируем базовый механизм работы встроенного языка запросов 7.7. По умолчанию, если в тексте запроса явно не указано иное, система настраивается на работу только с проведенными документами. Это логично для бухгалтерских или оперативных отчетов, которые должны опираться на свершившиеся факты хозяйственной жизни, отраженные в регистрах. Однако для получения полной картины нам необходимо изменить поведение запроса.
Рассмотрим пример кода, который часто приводит к ошибке «невидимости» данных:
Запрос = СоздатьОбъект("Запрос");
ТекстЗапроса = "
|Докум = Документ.ЗаявкаПокупателя.ТекущийДокумент;
|Группировка Докум;
|";
В данном случае запрос проигнорирует все заказы, которые не были проведены. Чтобы исправить ситуацию, мы должны использовать специальную директиву. Рассмотрим правильный вариант написания:
ТекстЗапроса = "
|ОбрабатыватьДокументы Все;
|Докум = Документ.ЗаявкаПокупателя.ТекущийДокумент;
|Группировка Докум;
|";
Важно помнить разницу в синтаксисе. Директива ОбрабатыватьДокументы может принимать следующие значения:
Обратите внимание, что сокращение Обрабатывать Все (без слова "Документы") в некоторых релизах платформы или контекстах может интерпретироваться неверно, поэтому всегда рекомендуется использовать полный синтаксис ОбрабатыватьДокументы Все.
Даже если мы правильно указали директиву ОбрабатыватьДокументы Все, мы можем столкнуться с тем, что часть документов (особенно новых или созданных «будущим числом») все равно не попадает в результат. Выясним причину этого поведения.
В 1С 7.7 существует понятие Точки Актуальности (ТА). Если в тексте запроса не задан период с помощью оператора Период С ... По ..., платформа устанавливает временные границы запроса автоматически. Чаще всего конечной границей становится именно ТА. Если документ был записан временем позже, чем установленная ТА, он окажется «за бортом» выборки.
Рассмотрим, как правильно задать период, чтобы гарантированно захватить все документы:
ТекстЗапроса = "
|Период С '01.01.2000' По '31.12.2099';
|ОбрабатыватьДокументы Все;
|Докум = Документ.ЗаявкаПокупателя.ТекущийДокумент;
|Группировка Докум;
|";
Указание широкого диапазона дат позволяет обойти ограничение ТА. Проанализируем ситуацию: если мы создаем документ сегодняшним числом, но ТА в базе по какой-то причине (например, из-за долгого отсутствия последовательного проведения) осталась в прошлом месяце, запрос без периода этот документ не увидит.
Существует специфическая особенность работы движка запросов 7.7: запрос может отрабатывать некорректно, если в нем объявлены переменные и группировки, но нет ни одной Функции. В некоторых случаях это приводит к тому, что строки, не имеющие числовых показателей, просто отсекаются.
Посмотрим на пример добавления фиктивной или полезной функции для стабилизации выборки:
ТекстЗапроса = "
|ОбрабатыватьДокументы Все;
|Докум = Документ.ЗаявкаПокупателя.ТекущийДокумент;
|СуммаДок = Документ.ЗаявкаПокупателя.СуммаВзаиморасчетов;
|Функция ВсегоСумма = Сумма(СуммаДок);
|Группировка Докум;
|";
Добавление функции Сумма или Счёт заставляет механизм запроса более тщательно перебирать записи таблицы документов.
Стоит учитывать, что директива ОбрабатыватьДокументы Все включает и проведенные, и непроведенные документы, но не включает документы, помеченные на удаление. Если ваша задача — увидеть абсолютно все записи в журнале, включая «корзину», необходимо добавить еще одну инструкцию:
|Обрабатывать ПомеченныеНаУдаление;
Хотя на практике это требуется редко, об этой особенности важно знать при отладке расхождений в данных.
Проанализируем ситуацию, когда использование объекта Запрос может быть избыточным. Если вам не нужно агрегировать данные (считать суммы, количества) и не нужно связывать данные документа с итогами регистров, гораздо надежнее и быстрее использовать объектный метод ВыбратьДокументы().
Рассмотрим пример реализации:
Док = СоздатьОбъект("Документ.ЗаявкаПокупателя");
// Выбираем документы за весь период
Док.ВыбратьДокументы(Дата('01.01.2000'), РабочаяДата());
Пока Док.ПолучитьДокумент() = 1 Цикл
// Здесь мы гарантированно видим и проведенные, и непроведенные документы
// Проверить статус можно через Док.Проведен()
Сообщить("Найден документ: " + Док.ТекущийДокумент());
КонецЦикла;
Этот метод работает напрямую с таблицами базы данных и не зависит от настроек «Точки Актуальности» или внутренних механизмов оптимизации запросов, которые могут отсекать данные по статусу проведения.
Если вы применили все вышеперечисленные советы (указали ОбрабатыватьДокументы Все, задали период, добавили функцию), но документ все равно не виден, выясним возможные технические причины:
_1SJOURN). Если запись в этой таблице повреждена или отсутствует, хотя сам документ в своей таблице существует, запрос его не найдет. В этом случае поможет «Тестирование и исправление ИБ».Подводя итог, можно сказать, что решение проблемы «невидимости» документов в 1С 7.7 чаще всего кроется в комбинации правильной директивы обработки и явного указания периода. Всегда проверяйте эти два параметра в первую очередь.