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