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