Разработка и Конфигурация · 12 мин
Как в запросе указать вид движения регистра накопления 1С
Как указать вид движения регистра накопления в запросе 1С: ВидДвиженияНакопления.Приход и Расход в условиях ГДЕ, виртуальных таблицах и СКД. Примеры кода и типичные ошибки.
Вид движения — системное поле каждой записи регистра накопления, которое принимает одно из двух значений: Приход или Расход. В языке запросов 1С это поле называется ВидДвижения, а сами значения задаются через перечисление ВидДвиженияНакопления. Умение правильно отфильтровать записи по виду движения нужно при построении отчётов по оборотам, при проверке движений документа и при отладке проведения.
Типичная задача выглядит так: нужно выбрать из регистра «ТоварыНаСкладах» только приходные записи за период или, наоборот, только расходные. Без фильтра по виду движения запрос вернёт оба типа записей, и итоги придется разделять дополнительно. Фильтрация на уровне запроса быстрее и проще, чем постобработка результата в коде.
Важно понимать, что синтаксис обращения к значению перечисления в запросе отличается от обращения во встроенном языке. В коде модуля пишут ВидДвиженияНакопления.Приход, а в тексте запроса — ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход). Именно эта конструкция и становится источником большинства ошибок у начинающих разработчиков.
Как устроено поле ВидДвижения в регистре накопления
Каждая запись регистра накопления содержит системное поле ВидДвижения. Оно заполняется автоматически при проведении документа: платформа берёт значение из свойства ВидДвижения строки набора записей, которое разработчик присваивает в обработке проведения. Вручную в запросе это поле доступно только для чтения — изменить его через запрос нельзя.
Тип поля — перечисление ВидДвиженияНакопления с двумя предопределёнными значениями: Приход и Расход. Пустого или неопределённого значения у этого поля не бывает: платформа не позволит записать движение без указания вида. Поэтому проверки на NULL или пустое значение для этого поля бессмысленны.
Поле присутствует только в физической таблице регистра накопления (РегистрНакопления.ИмяРегистра). В виртуальных таблицах Остатки и ОстаткиИОбороты его нет — там данные уже агрегированы, а вид движения «растворяется» в колонках Приход и Расход. Это ключевое ограничение, о котором часто забывают.
Базовый синтаксис: фильтр через ЗНАЧЕНИЕ в секции ГДЕ
Самый распространённый способ — отобрать записи физической таблицы по виду движения в секции ГДЕ. Значение перечисления подставляется через функцию ЗНАЧЕНИЕ(), внутри которой указывается полное имя значения: имя перечисления, точка, имя значения.
ВЫБРАТЬ
Движения.Номенклатура,
Движения.Склад,
Движения.Количество
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК Движения
ГДЕ
Движения.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
И Движения.Период МЕЖДУ &НачалоПериода И &КонецПериода
Для отбора расходных записей меняется только значение внутри ЗНАЧЕНИЕ():
ГДЕ
Движения.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)
Если нужно исключить один вид движения, используют неравенство: Движения.ВидДвижения <> ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход). Для двухзначного перечисления это эквивалентно явному указанию противоположного значения, но явное сравнение читается понятнее и безопаснее при возможном расширении логики.
Как передать вид движения через параметр запроса
Когда вид движения должен задаваться извне — из кода модуля или настройки отчёта — его передают параметром. В тексте запроса условие выглядит обычно: ГДЕ Движения.ВидДвижения = &ВидДвижения, а значение присваивается через коллекцию параметров объекта Запрос.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Движения.Номенклатура,
| Движения.Количество
|ИЗ
| РегистрНакопления.ТоварыНаСкладах КАК Движения
|ГДЕ
| Движения.ВидДвижения = &ВидДвижения";
Запрос.УстановитьПараметр("ВидДвижения", ВидДвиженияНакопления.Приход);
Результат = Запрос.Выполнить();
Обратите внимание: в коде модуля значение задаётся без ЗНАЧЕНИЕ() — просто ВидДвиженияНакопления.Приход. Это встроенный язык, а не язык запросов, и синтаксис у них разный. Смешение двух синтаксисов — частая причина ошибок «Параметр не найден» или «Неверное имя».
Параметризация удобна, когда один и тот же запрос используется для выборки и прихода, и расхода: текст запроса не меняется, меняется только значение параметра. Это также упрощает поддержку и снижает риск опечаток в тексте запроса.
- 1Определите, какая таблица нужна: физическая (записи) или виртуальная (остатки/обороты)
- 2Для физической таблицы добавьте в ГДЕ условие ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
- 3Для виртуальной таблицы оборотов используйте колонки Приход/Расход вместо фильтра по виду
- 4Проверьте результат в консоли запросов на тестовых данных
- 5Сверьте количество записей с движениями известного документа
Вид движения в виртуальных таблицах: что доступно и что нет
Виртуальные таблицы регистра накопления ведут себя по-разному. В таблице Обороты вид движения как отдельное поле недоступен: вместо него платформа предоставляет ресурсы с суффиксами Приход и Расход (например, КоличествоПриход и КоличествоРасход). Если нужен только приход — выбирайте колонку КоличествоПриход, фильтр по виду движения не требуется.
В таблицах Остатки и ОстаткиИОбороты поля ВидДвижения тоже нет, поскольку остаток — это свёрнутый результат, а не набор записей. Попытка обратиться к ВидДвижения в этих таблицах завершится ошибкой «Поле не найдено».
Если нужны обороты в разрезе видов движения с детализацией до документов, есть два пути: соединить физическую таблицу с фильтром по виду движения, либо использовать Обороты с детализацией по регистратору и нужными колонками Приход/Расход. Второй вариант обычно быстрее на больших объёмах, потому что виртуальная таблица оборотов опирается на предрасчитанные итоги.
Физическая таблица или виртуальная
Подходит, когда нужны сами записи с детализацией до строк: регистратор, номер строки, точный момент времени. Медленнее на больших объёмах.
Подходит для сумм по приходу и расходу за период. Вид движения не фильтруется — используются колонки Приход/Расход. Быстрее за счёт итогов.
Подходит, когда нужны начальный остаток, обороты и конечный остаток одним запросом. Поле ВидДвижения недоступно.
Использование в СКД и динамических списках
В схеме компоновки данных фильтр по виду движения добавляется так же — в тексте запроса набора данных через ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход). Дополнительно отбор можно вынести в настройки отчёта: тогда пользователь сам выбирает вид движения в отборе, а значение перечисления доступно ему из выпадающего списка без правки запроса.
Чтобы отбор по виду движения был доступен в настройках СКД, поле ВидДвижения должно присутствовать в выборке запроса набора данных. После этого оно появляется в списке доступных полей отбора, и условие можно не зашивать в текст запроса. Такой подход гибче: один отчёт показывает и приход, и расход в зависимости от настройки пользователя.
В динамических списках (например, список движений по регистру в форме документа) отбор по виду движения настраивается через свойство «Отбор» динамического списка или программно через СхемаЗапроса. В произвольном запросе динамического списка действует тот же синтаксис с ЗНАЧЕНИЕ().
Если отчёт на СКД должен показывать приход и расход отдельными колонками, не фильтруйте записи по виду движения — берите виртуальную таблицу Обороты и выводите ресурсы Приход и Расход как два поля. Фильтрация по виду нужна только там, где требуется именно подмножество записей.
Типичные ошибки и как их диагностировать
Первая и самая частая ошибка — попытка написать в запросе ВидДвиженияНакопления.Приход без ЗНАЧЕНИЕ(). Конструктор запроса сообщит о неверном имени или синтаксической ошибке. Лечится добавлением обёртки ЗНАЧЕНИЕ() вокруг полного имени значения перечисления.
Вторая ошибка — обращение к полю ВидДвижения в виртуальной таблице Остатки или ОстаткиИОбороты. Платформа выдаёт «Поле не найдено». Решение: либо перейти на физическую таблицу, либо использовать ресурсы Приход/Расход виртуальной таблицы оборотов.
Третья ошибка — опечатка в имени регистра или перечисления внутри ЗНАЧЕНИЕ(). Имя внутри функции проверяется при выполнении запроса, а не всегда в конструкторе, поэтому ошибка может всплыть только в момент выполнения. Проверяйте точное имя перечисления: ВидДвиженияНакопления, без «Регистра» или других добавок.
Четвёртая ситуация — запрос выполняется, но возвращает пустой результат. Частая причина: в регистре нет записей нужного вида за выбранный период, либо перепутаны Приход и Расход относительно логики учёта (например, поступление товара делает Приход, а разработчик отфильтровал Расход). Проверяйте движения конкретного документа через отчёт «Движения документа» или консоль запросов.
Проверка результата и отладка запроса
Самый надёжный способ проверить фильтр — выполнить запрос в консоли запросов на копии базы и сверить результат с известными движениями. Возьмите документ, который точно делает приход (например, поступление товаров), и убедитесь, что его записи попадают в выборку с фильтром Приход и не попадают в выборку с фильтром Расход.
Полезный приём — сначала выполнить запрос без фильтра по виду движения, но с выводом поля ВидДвижения в результат. Так вы увидите, какие значения реально присутствуют в данных, и исключите ситуацию «фильтр правильный, но данных нет».
Для контроля итогов сверяйте сумму отфильтрованных записей с колонкой Приход или Расход виртуальной таблицы оборотов за тот же период. Совпадение сумм — хороший признак корректности фильтра. Расхождение обычно означает, что в условии потерялись дополнительные отборы (по складу, организации) или период задан по-разному.
Как проверить результат
Результат возвращается, поле ВидДвижения доступно в выборке
Ошибка «Поле не найдено» или синтаксическая ошибка — проверьте тип таблицы и ЗНАЧЕНИЕ()
Записи документа-поступления попадают в выборку с фильтром Приход
Записей нет — проверьте, что документ проведён и делает именно приход
Совпадает с колонкой Приход (или Расход) таблицы Обороты за тот же период
Суммы расходятся — проверьте период и дополнительные отборы
Частые вопросы
Можно ли в запросе сравнить ВидДвижения со строкой «Приход»?
Нет. Поле имеет тип перечисления, а не строку. Сравнение со строкой либо даст ошибку несовместимости типов, либо всегда вернёт ложь. Используйте ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход) или параметр со значением перечисления.
Как выбрать и приход, и расход одним запросом, но разными колонками?
Используйте виртуальную таблицу Обороты — в ней ресурсы доступны как отдельные колонки с суффиксами Приход и Расход, например КоличествоПриход и КоличествоРасход. Фильтр по виду движения при этом не нужен.
Работает ли фильтр по виду движения в запросе к регистру сведений?
Нет. Поле ВидДвижения существует только у регистров накопления. У регистров сведений этого поля нет, и перечисление ВидДвиженияНакопления к ним неприменимо.
Что вернёт запрос, если в регистре вообще нет записей нужного вида?
Пустой результат без ошибки. Это нормальное поведение: условие в ГДЕ просто отсекает все строки. Чтобы отличить «нет данных» от ошибки в запросе, выполните выборку без фильтра и посмотрите, какие виды движений реально присутствуют.
Можно ли задать вид движения в параметрах виртуальной таблицы?
Нет, в списке параметров виртуальных таблиц регистра накопления (период, условие, разрезы) отдельного параметра для вида движения нет. Для таблицы Обороты вид движения разделяется колонками Приход/Расход, а для детальных записей используйте физическую таблицу с условием в ГДЕ.
Как отфильтровать по виду движения в консоли запросов толстого клиента?
Точно так же, как в коде: добавьте в секцию ГДЕ условие ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход). Консоль запросов использует тот же язык запросов, поэтому синтаксис идентичен, а результат можно сразу посмотреть в таблице.
Что важно запомнить
Вид движения фильтруется через ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход или Расход) и только в физической таблице регистра накопления. В виртуальных таблицах вместо фильтра используются колонки Приход и Расход. В коде модуля значение передаётся параметром без ЗНАЧЕНИЕ().