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

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

Как в запросе 1С преобразовать строку в число

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

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

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

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

Почему в запросе 1С нельзя напрямую привести строку к числу

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

Причина в архитектуре: язык запросов 1С транслируется в SQL конкретной СУБД, и разработчики платформы сознательно не включили неявный парсинг строк, потому что поведение при нечисловом содержимом (буквы, пробелы, разделители) неоднозначно и различается между Microsoft SQL Server, PostgreSQL, Oracle и файловым вариантом.

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

Способ 1. Преобразовать значение до передачи в запрос

Самый надёжный вариант — привести строку к числу в коде до того, как значение попадёт в запрос. Это работает, когда строка приходит как параметр отбора, а не хранится в таблице.

СтрокаКод = "00125";

ЧислоКод = Число(СтрокаКод); // исключение при нечисловом значении

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Товары.Ссылка

|ИЗ

| Справочник.Товары КАК Товары

|ГДЕ

| Товары.ЧисловойКод = &Код";

Запрос.УстановитьПараметр("Код", ЧислоКод);

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

Для мягкой проверки удобно сначала очистить строку от пробелов и неразрывных пробелов через СокрЛП и СтрЗаменить, а затем проверить, что остались только цифры.

Порядок действий
  1. 1
    Очистите строку: СокрЛП, удаление неразрывных пробелов и разделителей тысяч
  2. 2
    Проверьте, что строка содержит только цифры и при необходимости знак/разделитель
  3. 3
    Выполните Число(Строка) внутри Попытка/Исключение
  4. 4
    Передайте полученное число в запрос как параметр
  5. 5
    Обработайте исключение: сообщение пользователю или значение по умолчанию

Способ 2. Обработка результата запроса в коде

Если строки хранятся в таблице и преобразовать их нужно для каждой записи, часто рациональнее выбрать строки запросом как есть, а приведение выполнить при обходе выборки или в таблице значений.

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

Попытка

ЧисловоеЗначение = Число(СокрЛП(Выборка.КодСтрокой));

Исключение

ЧисловоеЗначение = 0;

КонецПопытки;

// дальнейшая обработка

КонецЦикла;

Этот способ универсален и безопасен, но у него есть ограничение: нельзя использовать числовое значение в условии ГДЕ, соединении или сортировке на стороне запроса. Если отбор по числовому диапазону критичен, придётся выбирать более широкое множество и фильтровать в коде, что увеличивает объём передаваемых данных.

Для больших таблиц компромиссом служит добавление в объект конфигурации отдельного числового реквизита, который заполняется при записи. Тогда запрос работает с уже числовым полем, а преобразование выполняется один раз при сохранении данных.

Способ 3. Сравнение и сортировка строк как чисел без преобразования

Часто настоящая цель — не получить число, а правильно отсортировать или сравнить коды. Строковая сортировка даёт «1, 10, 2, 25», потому что сравнение идёт посимвольно. Обойти это можно без приведения типов.

Приём для сортировки — упорядочить сначала по длине строки, затем по самой строке: среди строк одинаковой длины лексикографический порядок совпадает с числовым.

ВЫБРАТЬ

Товары.Код КАК Код

ИЗ

Справочник.Товары КАК Товары

УПОРЯДОЧИТЬ ПО

ДЛИНАСТРОКИ(Товары.Код),

Товары.Код

Для сравнения двух строковых кодов как чисел применяют выравнивание длины: дополняют строку ведущими нулями или пробелами до фиксированной длины через ПОДСТРОКА и конкатенацию. После выравнивания обычные операторы сравнения строк дают числовой результат.

Ограничение приёма очевидно: он работает только для неотрицательных целых чисел без разделителей и требует, чтобы в данных не было букв.

bsl
ВЫБРАТЬ
    Товары.Код КАК Код
ИЗ
    Справочник.Товары КАК Товары
УПОРЯДОЧИТЬ ПО
    ДЛИНАСТРОКИ(Товары.Код),
    Товары.Код

Способ 4. ВЫРАЗИТЬ и временные таблицы: что реально работает

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

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

ВЫБРАТЬ

ВЫРАЗИТЬ(Данные.КодСтрокой КАК СТРОКА(11)) КАК Код

ПОМЕСТИТЬ ВТ_Коды

ИЗ

РегистрСведений.ВнешниеКоды КАК Данные

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

Типичные ошибки
01
Использовать ВЫРАЗИТЬ(Строка КАК ЧИСЛО) и ждать парсинга — платформа такого преобразования не выполняет
02
Забыть СокрЛП перед Число() — пробелы и неразрывные пробелы приводят к исключению
03
Сортировать строковые коды без учёта длины — получается порядок 1, 10, 2 вместо 1, 2, 10
04
Применять неявные приёмы СУБД к данным с буквами — запрос падает целиком с ошибкой
05
Не обрабатывать исключение Число() — одна «грязная» запись останавливает всю обработку

Способ 5. Преобразование в СКД и вычисляемых полях

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

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

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

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

Число() в коде до запроса

Подходит для параметров отбора. Полный контроль ошибок, но не работает для данных внутри таблиц

Обработка выборки после запроса

Универсально и безопасно. Не позволяет фильтровать и сортировать по числу на стороне СУБД

Сортировка по длине и значению строки

Решает задачу порядка кодов без преобразования. Только целые неотрицательные числа без букв

Вычисляемое поле СКД с функцией

Удобно для отчётов: отборы и итоги работают. Медленнее на больших объёмах

Отдельный числовой реквизит

Самый быстрый в запросах вариант. Требует изменения конфигурации и заполнения при записи

Проверка результата и границы безопасной работы

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

Особое внимание уделите разрядности: при хранении больших чисел строкой (например, длинных идентификаторов) преобразование в число может потерять точность или переполнить допустимую разрядность типа «Число». Если идентификатор длиннее 15–20 цифр, хранить и сравнивать его следует как строку.

Перед изменением конфигурации (добавлением числового реквизита) сделайте резервную копию информационной базы и проверьте обновление на копии: заполнение нового реквизита для большой таблицы может занять заметное время и потребовать монопольного доступа.

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

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

Значения после преобразования
Норма

Числа совпадают с исходными строками с точностью до ведущих нулей и пробелов

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

Часть значений обнулилась или вызвала исключения

Сортировка кодов
Норма

Порядок 1, 2, 10, 25 — числовой

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

Порядок 1, 10, 2, 25 — строковый

Выполнение запроса на реальных данных
Норма

Запрос отрабатывает без ошибок на всей таблице

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

Запрос падает на записях с буквами или спецсимволами

Скорость отчёта с вычисляемым полем
Норма

Время формирования приемлемо для пользователей

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

Отчёт заметно замедлился — нужна материализация числового поля

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

Почему ВЫРАЗИТЬ(Поле КАК ЧИСЛО) не преобразует строку в число?

Конструкция ВЫРАЗИТЬ в языке запросов 1С уточняет тип составного поля или меняет разрядность уже числового значения, но не выполняет парсинг строк. Платформа сознательно не поддерживает такое преобразование, потому что поведение при нечисловом содержимом различается между СУБД.

Как отсортировать строковые коды как числа в запросе?

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

Что делать, если в строке встречаются буквы или пробелы?

Перед вызовом Число() очистите строку через СокрЛП и СтрЗаменить (убрать неразрывные пробелы и разделители), а сам вызов поместите в Попытка/Исключение. Для записей, не прошедших проверку, определите поведение: пропуск, значение по умолчанию или запись в журнал.

Можно ли преобразовать строку в число прямо в отчёте на СКД?

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

Число() выдаёт ошибку на строке с ведущими нулями — это нормально?

Нет, ведущие нули не мешают: Число("00125") корректно вернёт 125. Чаще всего причина ошибки — пробелы, неразрывные пробелы, разделители тысяч или символы валюты в строке. Очистите значение перед преобразованием.

Какой способ выбрать для больших таблиц?

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

Итог

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

Прямого преобразования строки в число в языке запросов 1С нет. Приводите значение в коде через Число() с обработкой ошибок, сортируйте строковые коды по длине и значению, используйте вычисляемые поля СКД для отчётов, а для постоянной работы с большими данными заведите отдельный числовой реквизит.