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

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

1С: как выразить значение как несколько типов

Как в 1С выразить значение как несколько типов: составной тип реквизита, функция ВЫРАЗИТЬ в запросах, приведение типов в коде, ограничения и типичные ошибки.

В 1С одно и то же поле или реквизит может хранить значения разных типов: строку, число, ссылку на справочник или документ. Такая возможность называется составным типом данных, а операция приведения значения к конкретному виду — выражением типа. В запросах для этого служит конструкция ВЫРАЗИТЬ, в коде — методы приведения и проверки типа.

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

Ниже разобраны все три подхода: настройка составного типа в конфигураторе, оператор ВЫРАЗИТЬ в языке запросов и работа с типами во встроенном языке. Отдельно рассмотрены ограничения, проверка результата и ошибки, которые чаще всего приводят к падению запросов и отчётов.

Что такое составной тип данных в 1С

Составной тип — это свойство реквизита, позволяющее хранить значения нескольких типов одновременно. Например, реквизит «Ответственный» может ссылаться и на справочник «Пользователи», и на справочник «Сотрудники», а поле «Комментарий» может быть одновременно строкой и ссылкой на файл. Платформа хранит в таком поле не только значение, но и информацию о его типе.

Составной тип задаётся в конфигураторе в палитре свойств реквизита: в поле «Тип» через кнопку выбора отмечаются нужные типы флажками. Можно комбинировать примитивные типы (Строка, Число, Дата, Булево) и ссылочные (справочники, документы, перечисления, планы видов характеристик). Для строки и числа дополнительно указываются длина и точность.

Важно понимать: составной тип — это не «несколько значений», а одно значение одного из допустимых типов. Хранить одновременно строку и число в одном поле нельзя — в каждый момент времени там лежит конкретное значение конкретного типа.

Как настроить составной тип реквизита в конфигураторе

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

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

Отдельный частный случай — реквизиты типа «ХранилищеЗначения» и определяемые типы. Определяемый тип удобен, когда один и тот же состав типов используется в нескольких объектах: меняете состав в одном месте, и он обновляется везде, где тип применён.

Порядок действий
  1. 1
    Откройте реквизит объекта в конфигураторе и в палитре свойств нажмите кнопку выбора в поле «Тип»
  2. 2
    Отметьте флажками все нужные типы, для строки и числа задайте длину и точность
  3. 3
    Сохраните конфигурацию и выполните обновление конфигурации базы данных
  4. 4
    Проверьте запросом, что существующие данные соответствуют новому составу типов

Оператор ВЫРАЗИТЬ в языке запросов

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

Главное применение ВЫРАЗИТЬ — обращение к реквизитам через точку от составного поля. Запрос Товары.Номенклатура.Артикул упадёт с ошибкой, если поле «Номенклатура» составное, потому что платформа не знает, у какого типа брать реквизит «Артикул». Конструкция ВЫРАЗИТЬ(Товары.Номенклатура КАК Справочник.Номенклатура).Артикул решает проблему.

Вторая типовая задача — обрезка строки. Если строковый реквизит имеет неограниченную длину, группировки и соединения по нему работают некорректно или медленно. Приведение ВЫРАЗИТЬ(Комментарий КАК Строка(100)) обрезает значение и делает поле пригодным для группировки и сравнения.

ВЫБРАТЬ

ВЫРАЗИТЬ(Регистр.Объект КАК Справочник.Контрагенты) КАК Контрагент,

ВЫРАЗИТЬ(Регистр.Комментарий КАК Строка(100)) КАК Комментарий

ИЗ

РегистрСведений.ДанныеОбъектов КАК Регистр

ГДЕ

Регистр.Объект ССЫЛКА Справочник.Контрагенты

Проверка типа: ССЫЛКА и ТИПЗНАЧЕНИЯ в запросе

Когда составное поле нужно не привести, а отфильтровать по типу, применяют оператор ССЫЛКА: условие Поле ССЫЛКА Справочник.Номенклатура пропустит только те записи, где значение является ссылкой нужного вида. Это удобно для разделения выборки на части по типам объектов.

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

Комбинация ССЫЛКА в условии и ВЫРАЗИТЬ в выборке — стандартный приём для отчётов по регистрам с составными измерениями: сначала отбираются записи нужного типа, затем поле приводится к нему, и дальше доступны все реквизиты объекта через точку.

Сравнение вариантов

ВЫРАЗИТЬ

Приводит поле к одному типу в выборке. Подходит для доступа к реквизитам через точку и обрезки строк. Не фильтрует записи — несоответствующие значения станут NULL.

ССЫЛКА

Проверяет тип в условии ГДЕ. Подходит для отбора записей нужного типа, но не даёт доступа к реквизитам.

ТИПЗНАЧЕНИЯ + ТИП

Гибкая проверка типа, в том числе в вычисляемых полях и ВЫБОР. Более громоздкий синтаксис.

Работа с типами во встроенном языке

В коде модуля составной тип обрабатывается через функцию ТипЗнч() и сравнение с Тип(). Типичный шаблон: Если ТипЗнч(Значение) = Тип("СправочникСсылка.Номенклатура") Тогда ... КонецЕсли;. Для проверки принадлежности к группе типов удобны функции вида ЭтоСсылка() из общих модулей типовых конфигураций.

Для явного приведения примитивных типов используются функции Строка(), Число(), Дата() и методы форматирования. В отличие от ВЫРАЗИТЬ в запросе, здесь происходит именно преобразование значения: число 100.5 станет строкой «100,5» с учётом региональных настроек, если не задать форматную строку явно.

Если значение может быть NULL (например, пришло из запроса с левым соединением), проверку типа нужно выполнять до обращения к свойствам — обращение к реквизиту NULL вызовет ошибку исполнения. Безопасный порядок: проверка на NULL, затем ТипЗнч(), затем работа со значением.

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

Ограничения и особенности платформы

Не все сочетания типов допустимы. Например, тип ХранилищеЗначения нельзя комбинировать с другими типами в одном реквизите, а для чисел в составном типе действуют общие ограничения длины и точности. В запросах ВЫРАЗИТЬ нельзя применять к полям типа ХранилищеЗначения и к полям неограниченной длины без указания новой длины.

Составные типы влияют на производительность: индексы по составным полям менее эффективны, а соединения по ним заставляют СУБД проверять тип каждой записи. Если составной тип не нужен по логике предметной области, лучше разделить данные на отдельные реквизиты или использовать план видов характеристик для универсальных ссылок.

В СКД и динамических списках составные поля требуют той же аккуратности: настройки отбора по составному полю предлагают пользователю выбор типа значения, а вывод реквизитов через точку без ВЫРАЗИТЬ в тексте запроса набора данных приведёт к ошибке при формировании отчёта.

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

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

Запрос с ВЫРАЗИТЬ выполняется
Норма

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

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

Ошибка «Поле не найдено» или пустые значения там, где должны быть данные

Составной реквизит в форме
Норма

Поле ввода предлагает выбор из всех допустимых типов объектов

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

Выбор ограничен одним типом — составной тип не сохранён

Данные после изменения типа
Норма

Старые значения на месте, тип соответствует новому составу

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

Значения очищены — тип был сужен без предварительной проверки

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

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

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

Чем ВЫРАЗИТЬ отличается от ССЫЛКА в запросе?

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

Что происходит со значениями, не подходящими под тип в ВЫРАЗИТЬ?

Для ссылочных типов результатом будет NULL, для примитивных — пустое значение соответствующего типа. Сама запись из выборки не исчезает, поэтому при необходимости отбора нужно добавлять условие ССЫЛКА или проверку на NULL.

Как обрезать строку неограниченной длины в запросе?

Используйте ВЫРАЗИТЬ(Поле КАК Строка(N)), где N — нужная длина. Это необходимо перед группировкой, соединением или помещением поля во временную таблицу, так как строки неограниченной длины в этих операциях работают некорректно или запрещены.

Почему запрос падает с ошибкой при обращении к реквизиту составного поля?

Платформа не может определить, к реквизиту какого типа идёт обращение, потому что составное поле хранит разные типы. Решение — сначала привести поле оператором ВЫРАЗИТЬ к конкретному типу, затем обращаться к реквизиту через точку.

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

Можно, но с осторожностью. Расширение состава типов безопасно: старые значения сохранятся. Сужение приведёт к очистке значений исключённых типов при обновлении конфигурации базы данных, поэтому заранее сделайте резервную копию и проверьте данные запросом.

Итог

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

Составной тип задаётся в конфигураторе и позволяет реквизиту хранить значения нескольких типов. В запросах поле приводится к одному типу оператором ВЫРАЗИТЬ, а фильтрация по типу выполняется через ССЫЛКА. В коде используются ТипЗнч() и Тип(). Перед сужением составного типа реквизита с данными обязательно делайте резервную копию.