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

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

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

Как определить тип документа в запросе 1С: функция ТИПЗНАЧЕНИЯ, проверка ССЫЛКА, сравнение типов, отбор по виду документа и типичные ошибки разработчиков.

В языке запросов 1С нельзя напрямую получить «имя вида документа» строкой, как в коде через Метаданные().Имя. Вместо этого для определения типа документа используются специальные конструкции языка запросов: функция ТИПЗНАЧЕНИЯ(), оператор сравнения ССЫЛКА и литералы типов вида ТИП(Документ.РеализацияТоваровУслуг). Они позволяют проверить, каким именно видом документа является ссылка в составном поле.

Задача возникает постоянно: в регистрах, журналах документов и полях с составным типом хранятся ссылки на разные виды документов, а в отчёте или выборке нужно отобрать только определённые. Например, из регистра «Взаиморасчеты» выбрать движения только по реализациям, или в поле «ДокументОснование» отличить заказ от счёта на оплату.

Ниже разобраны все рабочие способы определения типа документа в запросе: проверка одного типа, перечисление нескольких типов, использование в полях выборки и условиях соединений, а также типичные ошибки, которые приводят к пустым выборкам и падению производительности.

Как проверить тип документа через ТИПЗНАЧЕНИЯ

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

ВЫБРАТЬ

Взаиморасчеты.Регистратор КАК Регистратор

ИЗ

РегистрНакопления.Взаиморасчеты КАК Взаиморасчеты

ГДЕ

ТИПЗНАЧЕНИЯ(Взаиморасчеты.Регистратор) = ТИП(Документ.РеализацияТоваровУслуг)

Такой запрос вернёт только те записи регистра, где регистратором является документ «Реализация товаров и услуг». Если в поле хранится ссылка на другой вид документа или значение другого типа (строка, число, справочник), условие не выполнится.

Важно понимать: сравнение идёт строго по указанному виду. Если нужны несколько видов документов, каждый проверяется отдельным условием, объединённым через ИЛИ. Никаких «масок» или шаблонов имён в языке запросов нет.

1C
ГДЕ
	ТИПЗНАЧЕНИЯ(Таб.ДокументОснование) = ТИП(Документ.ЗаказПокупателя)
	ИЛИ ТИПЗНАЧЕНИЯ(Таб.ДокументОснование) = ТИП(Документ.СчетНаОплатуПокупателю)

Как использовать оператор ССЫЛКА для проверки типа

Альтернатива функции ТИПЗНАЧЕНИЯ — оператор сравнения ССЫЛКА. Он проверяет, является ли значение ссылкой на указанный вид объекта, и записывается короче:

ВЫБРАТЬ

Журнал.Ссылка КАК Документ

ИЗ

ЖурналДокументов.СкладскиеДокументы КАК Журнал

ГДЕ

Журнал.Ссылка ССЫЛКА Документ.ПриходныйОрдерНаТовары

По результату оба способа эквивалентны для ссылочных типов. Разница в читаемости и привычках команды: ССЫЛКА компактнее, когда проверяется один тип, а ТИПЗНАЧЕНИЯ удобнее, когда тип нужно получить как значение — например, вывести в поле выборки или использовать в ВЫБОР КОГДА.

Ограничение оператора ССЫЛКА: он работает только со ссылочными типами (документы, справочники, планы видов характеристик и т.д.). Проверить им примитивный тип — строку, число, дату — нельзя, для этого используется только ТИПЗНАЧЕНИЯ с литералами ТИП(СТРОКА), ТИП(ЧИСЛО), ТИП(ДАТА).

Сравнение способов проверки типа

ТИПЗНАЧЕНИЯ(Поле) = ТИП(...)

Универсальный способ: работает и со ссылками, и с примитивными типами, результат можно вывести в поле. Запись длиннее.

Поле ССЫЛКА Документ.Вид

Короткая запись, удобна в условиях ГДЕ. Работает только со ссылочными типами, нельзя получить тип как значение.

ВЫРАЗИТЬ(Поле КАК Документ.Вид)

Приведение типа: обращение к реквизитам конкретного вида через точку. Не проверка, а «усечение» составного типа.

Как вывести тип документа в результат запроса

Иногда тип нужно не отфильтровать, а показать в отчёте. Значение, возвращаемое ТИПЗНАЧЕНИЯ(), можно поместить в поле выборки — в СКД и консоли запросов оно отобразится как тип. Но для пользователя удобнее преобразовать тип в понятную строку через ВЫБОР КОГДА:

ВЫБРАТЬ

ВЫБОР

КОГДА Т.Регистратор ССЫЛКА Документ.РеализацияТоваровУслуг

ТОГДА "Реализация"

КОГДА Т.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг

ТОГДА "Поступление"

ИНАЧЕ "Прочее"

КОНЕЦ КАК ВидДокумента,

Т.Регистратор КАК Регистратор

ИЗ

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

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

Если нужен именно синоним вида документа «как в конфигураторе», в чистом запросе его не получить — метаданные в языке запросов недоступны. Практические варианты: захардкодить строки в ВЫБОР КОГДА (как выше), соединить с таблицей критерия отбора или журнала, либо обработать результат запроса уже в коде встроенного языка через Ссылка.Метаданные().Синоним.

Как отфильтровать документы нужного типа в составном поле

Составные поля — реквизиты, в которых разрешено несколько типов, — главный источник задач на определение типа. Типичные примеры: «ДокументОснование», «Регистратор» в регистрах, «ОбъектРасчетов», поля журналов документов. В них физически лежит ссылка, но заранее неизвестно, на какой вид документа.

Порядок действий для отбора: определите список допустимых типов поля в конфигураторе (свойство «Тип» реквизита), выберите нужные виды и соберите условие через ИЛИ. Если видов много, удобнее сгруппировать условия в скобки, чтобы не смешивать их с остальными фильтрами запроса:

ГДЕ

(Т.Основание ССЫЛКА Документ.ЗаказПокупателя

ИЛИ Т.Основание ССЫЛКА Документ.СчетНаОплатуПокупателю)

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

Обратный отбор — «все, кроме указанного вида» — записывается через отрицание: НЕ (Поле ССЫЛКА Документ.Вид). Учтите нюанс с NULL: если поле может быть незаполненным, проверка типа для NULL вернёт «ложь», и в отрицательное условие такие строки не попадут корректно. Добавляйте явную обработку: ИЛИ Поле ЕСТЬ NULL в зависимости от требуемой логики.

Порядок действий при отборе по типу
  1. 1
    Откройте в конфигураторе состав типа реквизита и выпишите допустимые виды документов
  2. 2
    Выберите способ проверки: ССЫЛКА для короткого условия или ТИПЗНАЧЕНИЯ для универсальности
  3. 3
    Соберите условие в секции ГДЕ, объединяя несколько видов через ИЛИ в скобках
  4. 4
    Проверьте результат в консоли запросов на данных, где типы заведомо разные
  5. 5
    Добавьте обработку NULL, если поле может быть незаполненным

Как обратиться к реквизитам документа конкретного типа

Проверка типа решает половину задачи. Вторая половина — достать реквизит, который есть только у одного вида документа, из составного поля. Напрямую через точку это запрещено: запрос Т.Основание.Склад не скомпилируется, если «Склад» есть не у всех допустимых типов поля.

Решение — оператор приведения типа ВЫРАЗИТЬ(Поле КАК Документ.Вид). Он «сужает» составной тип до одного вида, после чего реквизиты этого вида становятся доступны через точку:

ВЫБРАТЬ

ВЫРАЗИТЬ(Т.Основание КАК Документ.ЗаказПокупателя).Склад КАК Склад

ИЗ

Документ.РеализацияТоваровУслуг КАК Т

ГДЕ

Т.Основание ССЫЛКА Документ.ЗаказПокупателя

Для строк, где основание — другой вид документа, результат приведения будет NULL, а не ошибка. Поэтому условие ГДЕ ... ССЫЛКА ... в примере не обязательно для корректности, но полезно для производительности: оно отсекает лишние строки до вычисления полей. Сочетание ВЫРАЗИТЬ + проверка типа — стандартный приём для соединений по составным полям и для отчётов, где колонка заполняется только для определённого вида документов.

Производительность и ограничения при работе с типами

Проверка типа через ССЫЛКА и ТИПЗНАЧЕНИЯ — относительно лёгкая операция, но на больших таблицах она не использует индексы по ссылке напрямую. Если запрос выбирает малую долю записей из большого регистра, эффективнее сначала ограничить выборку другими условиями (период, организация), а проверку типа применять к уже сокращённому набору — порядок условий в тексте на это не влияет, но влияет осознанное проектирование: например, выборка по виртуальной таблице с отбором, а не полное сканирование.

Более затратный сценарий — соединение таблиц по составному полю без приведения типа. СУБД вынуждена проверять соответствие по всем таблицам допустимых типов. Приведение через ВЫРАЗИТЬ в условии соединения сокращает число проверяемых таблиц до одной и заметно ускоряет запрос на больших объёмах.

Есть и функциональные ограничения, о которых стоит помнить. В параметрах виртуальных таблиц и в пакетных запросах конструкции с типами работают, но литерал ТИП(...) нельзя передать параметром — параметр может содержать только значение, а не описание типа. Если нужно параметризовать вид документа, передавайте массив или список конкретных ссылок/пустых ссылок и проверяйте через В (&СписокВидов) по пустым ссылкам соответствующих видов.

Типичные ошибки
01
Использовать синоним документа вместо имени метаданных: ТИП(Документ.Реализация) вызовет ошибку, если вид называется РеализацияТоваровУслуг
02
Обращаться к реквизиту конкретного вида без ВЫРАЗИТЬ — запрос не пройдёт проверку в конструкторе
03
Забыть ветку ИНАЧЕ в ВЫБОР КОГДА — для неперечисленных типов в отчёт попадёт NULL и собьёт группировки
04
Сравнивать тип через строковое представление ссылки — такой запрос медленный и нестабильный
05
Игнорировать NULL в составном поле при отрицательном отборе — незаполненные строки выпадают из результата

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

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

Затем добавьте условие и сравните количество строк: если выборка пустая, хотя документы нужного вида точно есть, проверьте имя вида в метаданных и отсутствие опечаток. Если строк слишком много — убедитесь, что условия через ИЛИ взяты в скобки и не «переопределены» соседним И из-за приоритета операторов.

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

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

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

Имя вида документа в литерале ТИП(...)
Норма

Совпадает с именем в дереве метаданных конфигуратора

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

Использован синоним или пользовательское название — запрос не выполняется

Количество строк после отбора по типу
Норма

В выборке только документы нужных видов, число строк правдоподобно

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

Пустая выборка при наличии данных или попадание посторонних видов

Поля, полученные через ВЫРАЗИТЬ
Норма

Заполнены для строк нужного вида, NULL для остальных

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

NULL везде — значит, вид в ВЫРАЗИТЬ не совпадает с реальными данными

Часто задаваемые вопросы

Можно ли в запросе получить строковое имя вида документа, например «РеализацияТоваровУслуг»?

Напрямую — нет, язык запросов не обращается к метаданным. Практические варианты: сопоставить типы строкам через ВЫБОР КОГДА ... ССЫЛКА ... ТОГДА "НужноеНазвание" либо получить имя уже в коде через Ссылка.Метаданные().Имя после выполнения запроса.

Чем отличается ТИПЗНАЧЕНИЯ от ССЫЛКА и что выбрать?

Функционально для ссылочных типов они дают одинаковый результат проверки. ССЫЛКА короче и читается легче в условиях ГДЕ. ТИПЗНАЧЕНИЯ универсальнее: работает с примитивными типами и возвращает тип как значение, которое можно вывести в поле выборки.

Почему запрос с условием по типу возвращает пустой результат, хотя документы есть?

Чаще всего указано неверное имя вида документа (синоним вместо имени метаданных) или проверяется не то поле — например, реквизит шапки вместо регистратора. Проверьте фактические типы данных, выведя ТИПЗНАЧЕНИЯ(Поле) без отбора.

Как отобрать документы нескольких видов одним условием?

Перечислите проверки через ИЛИ, взяв их в скобки: (Поле ССЫЛКА Документ.Вид1 ИЛИ Поле ССЫЛКА Документ.Вид2). Скобки обязательны, если рядом есть условия через И, иначе приоритет операторов исказит логику отбора.

Работает ли проверка типа в СКД и динамических списках?

Да, обе конструкции — ТИПЗНАЧЕНИЯ и ССЫЛКА — поддерживаются в тексте запроса набора данных СКД и в произвольном запросе динамического списка. В отборах СКД проверку типа обычно выносят в вычисляемое поле или фиксируют в тексте запроса, так как пользовательский отбор по типу через интерфейс настроек задать сложно.

Можно ли передать вид документа в запрос параметром?

Литерал типа параметром передать нельзя. Обходной путь — передать пустую ссылку нужного вида и сравнивать ТИПЗНАЧЕНИЯ(Поле) = ТИПЗНАЧЕНИЯ(&ПустаяСсылка), либо передать список ссылок и использовать условие В (&Список).

Итог

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

Тип документа в запросе проверяется через ТИПЗНАЧЕНИЯ(Поле) = ТИП(Документ.Вид) или Поле ССЫЛКА Документ.Вид. Для доступа к реквизитам конкретного вида используйте ВЫРАЗИТЬ. Имена видов берите из метаданных, обрабатывайте NULL и ИНАЧЕ, а результат проверяйте в консоли запросов на реальных данных.