К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как в запросе указать вид движения регистра накопления 1С

Как указать вид движения регистра накопления в запросе 1С: ВидДвиженияНакопления.Приход и Расход в условиях ГДЕ, виртуальных таблицах и СКД. Примеры кода и типичные ошибки.

Вид движения — системное поле каждой записи регистра накопления, которое принимает одно из двух значений: Приход или Расход. В языке запросов 1С это поле называется ВидДвижения, а сами значения задаются через перечисление ВидДвиженияНакопления. Умение правильно отфильтровать записи по виду движения нужно при построении отчётов по оборотам, при проверке движений документа и при отладке проведения.

Типичная задача выглядит так: нужно выбрать из регистра «ТоварыНаСкладах» только приходные записи за период или, наоборот, только расходные. Без фильтра по виду движения запрос вернёт оба типа записей, и итоги придется разделять дополнительно. Фильтрация на уровне запроса быстрее и проще, чем постобработка результата в коде.

Важно понимать, что синтаксис обращения к значению перечисления в запросе отличается от обращения во встроенном языке. В коде модуля пишут ВидДвиженияНакопления.Приход, а в тексте запроса — ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход). Именно эта конструкция и становится источником большинства ошибок у начинающих разработчиков.

Как устроено поле ВидДвижения в регистре накопления

Каждая запись регистра накопления содержит системное поле ВидДвижения. Оно заполняется автоматически при проведении документа: платформа берёт значение из свойства ВидДвижения строки набора записей, которое разработчик присваивает в обработке проведения. Вручную в запросе это поле доступно только для чтения — изменить его через запрос нельзя.

Тип поля — перечисление ВидДвиженияНакопления с двумя предопределёнными значениями: Приход и Расход. Пустого или неопределённого значения у этого поля не бывает: платформа не позволит записать движение без указания вида. Поэтому проверки на NULL или пустое значение для этого поля бессмысленны.

Поле присутствует только в физической таблице регистра накопления (РегистрНакопления.ИмяРегистра). В виртуальных таблицах Остатки и ОстаткиИОбороты его нет — там данные уже агрегированы, а вид движения «растворяется» в колонках Приход и Расход. Это ключевое ограничение, о котором часто забывают.

Базовый синтаксис: фильтр через ЗНАЧЕНИЕ в секции ГДЕ

Самый распространённый способ — отобрать записи физической таблицы по виду движения в секции ГДЕ. Значение перечисления подставляется через функцию ЗНАЧЕНИЕ(), внутри которой указывается полное имя значения: имя перечисления, точка, имя значения.

ВЫБРАТЬ

Движения.Номенклатура,

Движения.Склад,

Движения.Количество

ИЗ

РегистрНакопления.ТоварыНаСкладах КАК Движения

ГДЕ

Движения.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)

И Движения.Период МЕЖДУ &НачалоПериода И &КонецПериода

Для отбора расходных записей меняется только значение внутри ЗНАЧЕНИЕ():

ГДЕ

Движения.ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход)

Если нужно исключить один вид движения, используют неравенство: Движения.ВидДвижения <> ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход). Для двухзначного перечисления это эквивалентно явному указанию противоположного значения, но явное сравнение читается понятнее и безопаснее при возможном расширении логики.

Как передать вид движения через параметр запроса

Когда вид движения должен задаваться извне — из кода модуля или настройки отчёта — его передают параметром. В тексте запроса условие выглядит обычно: ГДЕ Движения.ВидДвижения = &ВидДвижения, а значение присваивается через коллекцию параметров объекта Запрос.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Движения.Номенклатура,

| Движения.Количество

|ИЗ

| РегистрНакопления.ТоварыНаСкладах КАК Движения

|ГДЕ

| Движения.ВидДвижения = &ВидДвижения";

Запрос.УстановитьПараметр("ВидДвижения", ВидДвиженияНакопления.Приход);

Результат = Запрос.Выполнить();

Обратите внимание: в коде модуля значение задаётся без ЗНАЧЕНИЕ() — просто ВидДвиженияНакопления.Приход. Это встроенный язык, а не язык запросов, и синтаксис у них разный. Смешение двух синтаксисов — частая причина ошибок «Параметр не найден» или «Неверное имя».

Параметризация удобна, когда один и тот же запрос используется для выборки и прихода, и расхода: текст запроса не меняется, меняется только значение параметра. Это также упрощает поддержку и снижает риск опечаток в тексте запроса.

Порядок действий при фильтрации по виду движения
  1. 1
    Определите, какая таблица нужна: физическая (записи) или виртуальная (остатки/обороты)
  2. 2
    Для физической таблицы добавьте в ГДЕ условие ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
  3. 3
    Для виртуальной таблицы оборотов используйте колонки Приход/Расход вместо фильтра по виду
  4. 4
    Проверьте результат в консоли запросов на тестовых данных
  5. 5
    Сверьте количество записей с движениями известного документа

Вид движения в виртуальных таблицах: что доступно и что нет

Виртуальные таблицы регистра накопления ведут себя по-разному. В таблице Обороты вид движения как отдельное поле недоступен: вместо него платформа предоставляет ресурсы с суффиксами Приход и Расход (например, КоличествоПриход и КоличествоРасход). Если нужен только приход — выбирайте колонку КоличествоПриход, фильтр по виду движения не требуется.

В таблицах Остатки и ОстаткиИОбороты поля ВидДвижения тоже нет, поскольку остаток — это свёрнутый результат, а не набор записей. Попытка обратиться к ВидДвижения в этих таблицах завершится ошибкой «Поле не найдено».

Если нужны обороты в разрезе видов движения с детализацией до документов, есть два пути: соединить физическую таблицу с фильтром по виду движения, либо использовать Обороты с детализацией по регистратору и нужными колонками Приход/Расход. Второй вариант обычно быстрее на больших объёмах, потому что виртуальная таблица оборотов опирается на предрасчитанные итоги.

Физическая таблица или виртуальная

Физическая таблица + фильтр по ВидДвижения

Подходит, когда нужны сами записи с детализацией до строк: регистратор, номер строки, точный момент времени. Медленнее на больших объёмах.

Виртуальная таблица Обороты

Подходит для сумм по приходу и расходу за период. Вид движения не фильтруется — используются колонки Приход/Расход. Быстрее за счёт итогов.

ОстаткиИОбороты

Подходит, когда нужны начальный остаток, обороты и конечный остаток одним запросом. Поле ВидДвижения недоступно.

Использование в СКД и динамических списках

В схеме компоновки данных фильтр по виду движения добавляется так же — в тексте запроса набора данных через ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход). Дополнительно отбор можно вынести в настройки отчёта: тогда пользователь сам выбирает вид движения в отборе, а значение перечисления доступно ему из выпадающего списка без правки запроса.

Чтобы отбор по виду движения был доступен в настройках СКД, поле ВидДвижения должно присутствовать в выборке запроса набора данных. После этого оно появляется в списке доступных полей отбора, и условие можно не зашивать в текст запроса. Такой подход гибче: один отчёт показывает и приход, и расход в зависимости от настройки пользователя.

В динамических списках (например, список движений по регистру в форме документа) отбор по виду движения настраивается через свойство «Отбор» динамического списка или программно через СхемаЗапроса. В произвольном запросе динамического списка действует тот же синтаксис с ЗНАЧЕНИЕ().

Если отчёт на СКД должен показывать приход и расход отдельными колонками, не фильтруйте записи по виду движения — берите виртуальную таблицу Обороты и выводите ресурсы Приход и Расход как два поля. Фильтрация по виду нужна только там, где требуется именно подмножество записей.
ПЗ
Практическое замечание

Типичные ошибки и как их диагностировать

Первая и самая частая ошибка — попытка написать в запросе ВидДвиженияНакопления.Приход без ЗНАЧЕНИЕ(). Конструктор запроса сообщит о неверном имени или синтаксической ошибке. Лечится добавлением обёртки ЗНАЧЕНИЕ() вокруг полного имени значения перечисления.

Вторая ошибка — обращение к полю ВидДвижения в виртуальной таблице Остатки или ОстаткиИОбороты. Платформа выдаёт «Поле не найдено». Решение: либо перейти на физическую таблицу, либо использовать ресурсы Приход/Расход виртуальной таблицы оборотов.

Третья ошибка — опечатка в имени регистра или перечисления внутри ЗНАЧЕНИЕ(). Имя внутри функции проверяется при выполнении запроса, а не всегда в конструкторе, поэтому ошибка может всплыть только в момент выполнения. Проверяйте точное имя перечисления: ВидДвиженияНакопления, без «Регистра» или других добавок.

Четвёртая ситуация — запрос выполняется, но возвращает пустой результат. Частая причина: в регистре нет записей нужного вида за выбранный период, либо перепутаны Приход и Расход относительно логики учёта (например, поступление товара делает Приход, а разработчик отфильтровал Расход). Проверяйте движения конкретного документа через отчёт «Движения документа» или консоль запросов.

Типичные ошибки
01
Написать ВидДвиженияНакопления.Приход без ЗНАЧЕНИЕ() — синтаксическая ошибка запроса
02
Искать поле ВидДвижения в виртуальных таблицах Остатки или Обороты — ошибка «Поле не найдено»
03
Передать в параметр строку «Приход» вместо значения перечисления — сравнение не сработает, результат пустой
04
Перепутать Приход и Расход относительно логики учёта — пустой или неверный результат без сообщения об ошибке

Проверка результата и отладка запроса

Самый надёжный способ проверить фильтр — выполнить запрос в консоли запросов на копии базы и сверить результат с известными движениями. Возьмите документ, который точно делает приход (например, поступление товаров), и убедитесь, что его записи попадают в выборку с фильтром Приход и не попадают в выборку с фильтром Расход.

Полезный приём — сначала выполнить запрос без фильтра по виду движения, но с выводом поля ВидДвижения в результат. Так вы увидите, какие значения реально присутствуют в данных, и исключите ситуацию «фильтр правильный, но данных нет».

Для контроля итогов сверяйте сумму отфильтрованных записей с колонкой Приход или Расход виртуальной таблицы оборотов за тот же период. Совпадение сумм — хороший признак корректности фильтра. Расхождение обычно означает, что в условии потерялись дополнительные отборы (по складу, организации) или период задан по-разному.

Контрольные точки

Как проверить результат

Запрос выполняется без ошибок
Норма

Результат возвращается, поле ВидДвижения доступно в выборке

Тревожный признак

Ошибка «Поле не найдено» или синтаксическая ошибка — проверьте тип таблицы и ЗНАЧЕНИЕ()

Движения тестового документа
Норма

Записи документа-поступления попадают в выборку с фильтром Приход

Тревожный признак

Записей нет — проверьте, что документ проведён и делает именно приход

Сумма по отфильтрованным записям
Норма

Совпадает с колонкой Приход (или Расход) таблицы Обороты за тот же период

Тревожный признак

Суммы расходятся — проверьте период и дополнительные отборы

Частые вопросы

Можно ли в запросе сравнить ВидДвижения со строкой «Приход»?

Нет. Поле имеет тип перечисления, а не строку. Сравнение со строкой либо даст ошибку несовместимости типов, либо всегда вернёт ложь. Используйте ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход) или параметр со значением перечисления.

Как выбрать и приход, и расход одним запросом, но разными колонками?

Используйте виртуальную таблицу Обороты — в ней ресурсы доступны как отдельные колонки с суффиксами Приход и Расход, например КоличествоПриход и КоличествоРасход. Фильтр по виду движения при этом не нужен.

Работает ли фильтр по виду движения в запросе к регистру сведений?

Нет. Поле ВидДвижения существует только у регистров накопления. У регистров сведений этого поля нет, и перечисление ВидДвиженияНакопления к ним неприменимо.

Что вернёт запрос, если в регистре вообще нет записей нужного вида?

Пустой результат без ошибки. Это нормальное поведение: условие в ГДЕ просто отсекает все строки. Чтобы отличить «нет данных» от ошибки в запросе, выполните выборку без фильтра и посмотрите, какие виды движений реально присутствуют.

Можно ли задать вид движения в параметрах виртуальной таблицы?

Нет, в списке параметров виртуальных таблиц регистра накопления (период, условие, разрезы) отдельного параметра для вида движения нет. Для таблицы Обороты вид движения разделяется колонками Приход/Расход, а для детальных записей используйте физическую таблицу с условием в ГДЕ.

Как отфильтровать по виду движения в консоли запросов толстого клиента?

Точно так же, как в коде: добавьте в секцию ГДЕ условие ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход). Консоль запросов использует тот же язык запросов, поэтому синтаксис идентичен, а результат можно сразу посмотреть в таблице.

Итог

Что важно запомнить

Вид движения фильтруется через ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход или Расход) и только в физической таблице регистра накопления. В виртуальных таблицах вместо фильтра используются колонки Приход и Расход. В коде модуля значение передаётся параметром без ЗНАЧЕНИЕ().