При разработке внешних обработок в среде 1С:Предприятие одной из самых распространенных задач является выборка данных (например, документов) за определенный интервал времени. Несмотря на кажущуюся простоту, начинающие программисты часто сталкиваются с синтаксическими ошибками и логическими нюансами работы с типом Дата. В этой статье мы подробно разберем, как правильно составить запрос, передать параметры и избежать "ловушек" времени.
Рассмотрим ситуацию, когда в коде обработки объявляются параметры для начала и конца периода. Одной из первых ошибок, которую мы можем заметить, является невнимательность при копировании строк кода. Проанализируем типичный пример ошибки в установке параметров:
Запрос.УстановитьПараметр("НачПериода", НачПериода);
Запрос.УстановитьПараметр("НачПериода", КонПериода); // Ошибка: переопределение одного и того же параметра
В данном случае вторая строка просто затирает значение первой. В результате запрос будет пытаться найти документы, у которых дата одновременно больше и меньше КонПериода, что приведет к пустому результату. Правильный вариант всегда подразумевает уникальные имена для каждой границы:
Запрос.УстановитьПараметр("НачПериода", НачПериода);
Запрос.УстановитьПараметр("КонПериода", КонПериода);
В языке 1С работа со строками запроса требует строгого соблюдения правил оформления. Если вы переносите текст запроса на новую строку, каждая последующая строка должна начинаться с символа вертикальной черты |, а весь блок текста должен быть заключен в кавычки. Разберем ошибку, которая часто приводит к сообщению "Ожидается ключевое слово КонецПроцедуры":
Если закрыть кавычку раньше времени и продолжить текст на новой строке без оператора конкатенации или правильного продолжения строки, компилятор решит, что процедура завершена преждевременно. Посмотрим, как должен выглядеть корректный текст запроса:
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 5000
| СчетНаОплатуПокупателю.Ссылка КАК Ссылка,
| СчетНаОплатуПокупателю.Номер КАК Номер,
| СчетНаОплатуПокупателю.Дата КАК Дата
|ИЗ
| Документ.СчетНаОплатуПокупателю КАК СчетНаОплатуПокупателю
|ГДЕ
| СчетНаОплатуПокупателю.Дата МЕЖДУ &НачПериода И &КонПериода";
Обратите внимание, что условие ГДЕ является частью единой строки. Мы рекомендуем использовать Конструктор запроса (правой кнопкой мыши в модуле — "Конструктор запроса"), который автоматически расставит все кавычки и вертикальные черты правильно.
Важно понимать, как 1С обрабатывает тип Дата. Если пользователь выбирает дату в поле на форме (например, 31.12.2023), то значением в коде будет 31.12.2023 00:00:00. Если документ был создан в этот же день, но в 10 утра, условие МЕЖДУ его не включит, так как 10:00:00 больше, чем 00:00:00.
Чтобы избежать потери данных за последний день периода, мы должны всегда приводить конец периода к концу дня. Разберем, как это сделать программно:
// Приводим дату к последней секунде дня (23:59:59)
КонецПериодаДляЗапроса = КонецДня(КонПериода);
Запрос.УстановитьПараметр("КонПериода", КонецПериодаДляЗапроса);
Использование функции КонецДня() гарантирует, что в выборку попадут все документы, созданные до самого последнего момента указанной даты.
Вместо создания двух отдельных реквизитов НачПериода и КонПериода, мы предлагаем использовать встроенный тип данных СтандартныйПериод. Это значительно повышает удобство интерфейса.
СтандартныйПериод (назовем его ПериодОтчета).
Запрос.УстановитьПараметр("НачПериода", Объект.ПериодОтчета.ДатаНачала);
// ДатаОкончания в СтандартномПериоде уже включает время 23:59:59
Запрос.УстановитьПараметр("КонПериода", Объект.ПериодОтчета.ДатаОкончания);
Проанализируем использование конструкции ВЫБРАТЬ ПЕРВЫЕ 5000. Если мы используем ограничение количества записей без явной сортировки, СУБД вернет "случайный" набор документов. Чтобы результат был предсказуемым (например, получить последние созданные документы), необходимо добавить конструкцию УПОРЯДОЧИТЬ ПО.
|ИЗ
| Документ.СчетНаОплатуПокупателю КАК СчетНаОплатуПокупателю
|ГДЕ
| СчетНаОплатуПокупателю.Дата МЕЖДУ &НачПериода И &КонПериода
|УПОРЯДОЧИТЬ ПО
| СчетНаОплатуПокупателю.Дата УБЫВ
Важное замечание: Поле Дата у документов в 1С является индексированным "из коробки". Это означает, что поиск по интервалу дат через оператор МЕЖДУ будет работать максимально быстро даже в базах с миллионами записей. Однако, если бы мы работали с регистрами накопления или бухгалтерии, правильнее было бы использовать Виртуальные таблицы и передавать период в их параметры, а не в условие ГДЕ.
Подведем итог. Чтобы ваша выборка по периоду работала корректно, выполните следующие шаги:
&НачПериода и &КонПериода имеют разные имена и им присвоены правильные значения.КонецДня() для верхней границы периода.Консоль запросов для предварительной отладки текста — это сэкономит время и поможет сразу увидеть результат выполнения с вашими параметрами.Соблюдение этих простых правил поможет вам писать надежный код и избегать типичных ошибок начинающих разработчиков 1С.