Как получить строку из числа, ссылки или NULL в запросе и коде 1С без ошибки типов

· 9 мин

Содержание

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

Ниже разобраны все частые случаи для платформы 8.3: конкатенация числа со строкой в запросе, ссылки и составные типы, NULL и Неопределено, строки неограниченной длины, динамические списки. К каждому — короткий пример, который можно вставить в консоль запросов и проверить.

Откуда берётся «Несовместимые типы» при приведении к строке

В запросе платформа проверяет типы операндов ещё до выполнения. Сообщение приходит с координатами в тексте запроса вида {(12, 5)}: первое число — строка, второе — позиция символа. По ним сразу видно, на каком выражении споткнулся разбор.

Типичные источники ошибки:

  • 🔢 Число склеивают со строкой. Количество + " шт." в запросе не работает : оператор + для разных типов не определён.
  • 🔗 Ссылку пытаются выразить как строку. ВЫРАЗИТЬ(Контрагент КАК СТРОКА(150)) — ссылку на справочник в строку не приводят.
  • 📅 Дату или булево приводят к строке. Для языка запросов это тот же случай, что и с числом.
  • 🧩 Поле составного типа. Регистратор, Субконто1, Объект в регистре сведений могут хранить и ссылки, и примитивы. Склейка такого поля со строкой падает.
  • ❓ NULL после левого соединения. Само по себе NULL ошибку не даёт, но выражение "Склад: " + Склад.Наименование вернёт NULL целиком, если склада нет.

Встроенный язык и язык запросов — разные среды. В модуле "Итого: " + 15 даст строку Итого: 15, потому что тип результата определяет первый операнд. В запросе такое выражение — ошибка. Многие ловятся именно на этом: код в модуле работал, а тот же приём в запросе — нет.

Что умеет ВЫРАЗИТЬ КАК СТРОКА и чем его заменить

ВЫРАЗИТЬ(Поле КАК СТРОКА(N)) в запросе нужен для двух задач:

  1. Обрезать строку неограниченной длины до фиксированной, чтобы по ней можно было сравнивать, группировать и сортировать.
  2. Из поля составного типа выделить строковую часть.

Для всего остального есть другие инструменты. Сводка по исходному типу:

Что нужно получить строкойВ запросеВ коде модуля
Строку неограниченной длиныВЫРАЗИТЬ(Поле КАК СТРОКА(200))уже строка, ничего не нужно
Числонет надёжного способа, выводите числомФормат(Число, "ЧГ=0"), Строка(Число)
Датунет надёжного способа, выводите датойФормат(Дата, "ДФ=dd.MM.yyyy")
Элемент справочникаПоле.Наименование, ПРЕДСТАВЛЕНИЕ(Поле)Строка(Ссылка)
ДокументПоле.Номер, ПРЕДСТАВЛЕНИЕ(Поле)Строка(Ссылка)
ПеречислениеПРЕДСТАВЛЕНИЕ(Поле) или ВЫБОРСтрока(Значение), XMLСтрока(Значение)
Уникальный идентификатор ссылкинетXMLСтрока(Ссылка), Строка(Ссылка.УникальныйИдентификатор())

Длину в СТРОКА(N) указывайте всегда. Запись КАК СТРОКА без числа даёт снова строку неограниченной длины, и ошибка при группировке или сравнении никуда не денется. Значения длиннее N символов обрезаются молча, поэтому берите длину с запасом.

Как склеить текст и число

Если в отчёте нужна колонка вида «15 шт.», в запросе её не собирайте. Получите число отдельным полем, а строку соберите после выполнения:

Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
    Подпись = СтрШаблон("%1 шт.", Формат(Выборка.Количество, "ЧН=0; ЧГ=0"));
    // ... используем Подпись
КонецЦикла;

СтрШаблон доступен с платформы 8.3.6. Формат ЧГ=0 убирает пробелы-разделители групп разрядов, ЧН=0 выводит ноль вместо пустой строки.

С датой то же самое. Если в отчёте нужна подпись «03.2026», не пытайтесь получить её в запросе. Выведите дату, а текст получите в коде: Формат(Выборка.Период, "ДФ=MM.yyyy"). Когда нужно только сгруппировать по месяцу, строка вообще не нужна: НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ) вернёт дату первого числа, и по ней группировка и сортировка будут правильными.

Если склейка нужна именно в запросе

Иногда строку надо получить внутри запроса: для условия ПОДОБНО или ключа соединения. Тогда склеивайте только строковые части:

ВЫБРАТЬ
    Реализация.Ссылка,
    "№" + Реализация.Номер + " / " + Реализация.Контрагент.Наименование КАК Подпись
ИЗ
    Документ.РеализацияТоваровУслуг КАК Реализация

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

NULL и Неопределено при получении строки

Это два разных значения, и ведут они себя по-разному.

NULL появляется в запросе после ЛЕВОЕ СОЕДИНЕНИЕ, когда справа ничего не нашлось, и при обращении через точку к реквизиту пустой ссылки. Любая склейка с NULL даёт NULL. Защита — ЕСТЬNULL до склейки:

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

Без ЕСТЬNULL для товаров без остатка колонка «Описание» была бы пустой целиком, хотя наименование есть. Правило простое: оборачивайте в ЕСТЬNULL каждое поле, пришедшее из правой таблицы соединения, ещё до склейки, а не результат склейки.

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

Если Значение = Неопределено Тогда
    Текст = "не указано";
Иначе
    Текст = Строка(Значение);
КонецЕсли;

Проверка ЗначениеЗаполнено() для числа 0 вернёт Ложь. Если ноль — нормальное значение (нулевой остаток), не подменяйте его на «не указано» через эту функцию.

Ссылки, документы и перечисления: как получить текст

Справочники и документы

Ссылку в запросе в строку не приводят. Есть три рабочих варианта:

  1. Строковый реквизит через точку. Контрагент.Наименование, Документ.Номер, Контрагент.ИНН. Подходит для условий, сортировки и склейки.
  2. ПРЕДСТАВЛЕНИЕ(Поле). Даёт тот же текст, что пользователь видит в форме. Удобно для вывода в отчёт и табличный документ. Для фильтров и соединений лучше брать реквизит из п. 1.
  3. Преобразование в коде. Строка(Ссылка) вернёт представление, XMLСтрока(Ссылка) — уникальный идентификатор строкой. Второй вариант нужен для обменов и хранения ключа во внешней системе.

Перечисления

Строка(Перечисления.СтавкиНДС.НДС20) в коде вернёт синоним значения — то, что видит пользователь. XMLСтрока() для перечисления вернёт имя значения из конфигурации. Имя не меняется при правке синонима, поэтому для сравнения и выгрузки надёжнее его.

В запросе перечисление удобно разложить через ВЫБОР:

ВЫБОР
    КОГДА Документ.ВидОперации = ЗНАЧЕНИЕ(Перечисление.ВидыОперацийРеализацияТоваров.ПродажаКомиссия)
        ТОГДА "Комиссия"
    ИНАЧЕ "Продажа"
КОНЕЦ КАК ВидОперацииТекстом

Имя перечисления и его значения сверьте в дереве конфигурации своей базы: в разных конфигурациях они называются по-разному.

Поля составного типа

Регистратор, Субконто, ДокументОснование могут ссылаться на десятки таблиц. Перед получением текста сузьте тип:

ВЫБРАТЬ
    ВЫРАЗИТЬ(Движения.Регистратор КАК Документ.ПоступлениеТоваровУслуг).Номер КАК НомерПоступления
ИЗ
    РегистрНакопления.ТоварыНаСкладах КАК Движения
ГДЕ
    Движения.Регистратор ССЫЛКА Документ.ПоступлениеТоваровУслуг

Условие ССЫЛКА отбирает строки нужного типа, а ВЫРАЗИТЬ даёт доступ к реквизитам одного документа. Для строк другого типа выражение вернуло бы NULL.

Строки неограниченной длины в запросах и динамических списках

Вторая большая группа ошибок связана не с числами, а с длинными строками. Реквизиты вроде Комментарий, Описание, ТекстСообщения часто объявлены с неограниченной длиной. С такими полями в запросе нельзя:

  • 🚫 сравнивать через = с параметром или другим полем;
  • 🚫 группировать в СГРУППИРОВАТЬ ПО;
  • 🚫 использовать в РАЗЛИЧНЫЕ и в ОБЪЕДИНИТЬ без ВСЕ (оба режима убирают дубли, а значит, сравнивают);
  • 🚫 сортировать в УПОРЯДОЧИТЬ ПО.

Лечится одинаково — приведением к фиксированной длине:

ВЫБРАТЬ
    ВЫРАЗИТЬ(Заказы.Комментарий КАК СТРОКА(300)) КАК Комментарий,
    КОЛИЧЕСТВО(Заказы.Ссылка) КАК Заказов
ИЗ
    Документ.ЗаказКлиента КАК Заказы
СГРУППИРОВАТЬ ПО
    ВЫРАЗИТЬ(Заказы.Комментарий КАК СТРОКА(300))

Выражение в СГРУППИРОВАТЬ ПО должно совпадать с выражением в списке полей, иначе получите новую ошибку уже про группировку. Для поиска по фрагменту ВЫРАЗИТЬ не нужен: ПОДОБНО работает со строками неограниченной длины напрямую.

Динамический список с произвольным запросом

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

ВЫБРАТЬ
    Документ.Ссылка,
    Документ.Дата,
    ВЫРАЗИТЬ(Документ.Комментарий КАК СТРОКА(150)) КАК Комментарий
ИЗ
    Документ.ЗаказКлиента КАК Документ

В типовой конфигурации меняйте запрос списка не в основной конфигурации, а в расширении: так обновление релиза не затрёт правку.

Как не плодить лишние преобразования

Приведение типов в запросе — не бесплатная операция. Несколько приёмов, которые сокращают и ошибки, и время выполнения:

  • ⚡ Сужайте составной тип один раз. Регистратор.Дата без ВЫРАЗИТЬ заставляет платформу соединиться со всеми таблицами документов, на которые может ссылаться регистратор. Одно ВЫРАЗИТЬ во вложенном запросе или временной таблице — и дальше работаете с одним типом.
  • 📦 Выносите строку во временную таблицу. Если одно и то же ВЫРАЗИТЬ(... КАК СТРОКА(300)) нужно в трёх местах пакета, посчитайте его один раз в ПОМЕСТИТЬ и обращайтесь к полю по имени.
  • 🧮 Форматируйте на выходе. Числа и даты оставляйте своими типами до самого вывода. Сортировка по строке «10», «9», «100» даст неверный порядок, а по числу — правильный.
  • 🔤 Сравнивайте коды, а не тексты. Отбор по ПРЕДСТАВЛЕНИЕ() медленнее и ломается при переименовании. Отбирайте по ссылке или по ЗНАЧЕНИЕ(...).
ПодходКогда уместенРиск
ВЫРАЗИТЬ в каждом месте запросаодиночное поле, простой запросдублирование, расхождение длин
Временная таблица с готовой строкойпакет из нескольких запросовлишняя запись временных данных на больших объёмах
Сборка строки в кодевывод пользователю, печать, обменне годится для условий внутри запроса

Как найти выражение, на котором падает запрос

  1. Прочитайте координаты в сообщении. {(12, 5)} — двенадцатая строка текста запроса. Скопируйте текст из кода в консоль запросов, чтобы нумерация строк совпала.
  2. Откройте запрос в конструкторе. В конфигураторе установите курсор внутрь текста запроса и вызовите конструктор из контекстного меню. Конструктор подсвечивает ошибку синтаксиса и типов при попытке закрыть его кнопкой «ОК».
  3. Упростите выражение. Уберите склейку, оставьте поля по отдельности. Если ошибка ушла — виновата одна из частей склейки.
  4. Проверьте тип поля в отладчике. Остановитесь на строке после выполнения запроса и вычислите ТипЗнч(Выборка.Поле) через «Вычислить выражение» (Shift+F9). Для поля составного типа проверьте несколько строк: тип может меняться от записи к записи.
  5. Посмотрите тип реквизита в конфигурации. Свойство «Тип» реквизита покажет, составной ли он и какая у строки длина. Длина 0 означает неограниченную строку.
Диагностика: выберите симптом

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

Можно ли в запросе 1С превратить число в строку?
Штатного приведения числа к строке в языке запросов нет. Выводите число своим типом, а строку собирайте после выполнения запроса через Формат() или СтрШаблон().
Какую длину указывать в КАК СТРОКА(N)?
С запасом относительно реальных данных: для комментариев обычно 150–500 символов. Всё, что длиннее N, обрежется без предупреждения.
Почему ПРЕДСТАВЛЕНИЕ() не подходит для отбора?
Представление зависит от настроек объекта и может меняться при переименовании. Для отбора надёжнее ссылка, код или строковый реквизит.
Чем XMLСтрока отличается от Строка для ссылки?
Строка() даёт текст для человека, например «ООО Ромашка». XMLСтрока() даёт уникальный идентификатор, который не меняется при переименовании и подходит для обмена.
В СКД такая же ошибка — что делать?
Если ошибка в тексте запроса набора данных, правила те же. Поля для вывода в виде текста удобнее оформлять в настройках вывода, а не склейкой в запросе.