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

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

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

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

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

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

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

Почему ВЫРАЗИТЬ не преобразует строку в число

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

Если передать в ВЫРАЗИТЬ строковое поле, поведение зависит от СУБД, на которой работает информационная база. На файловом варианте чаще всего возникает ошибка выполнения запроса, на клиент-серверном варианте поведение может отличаться, но корректного разбора строки «123,45» в число не произойдёт нигде. Рассчитывать на такую конструкцию нельзя.

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

Способ 1. Посимвольный разбор строки через ПОДСТРОКА

Классический приём для строк фиксированной небольшой длины — разобрать строку на символы функцией ПОДСТРОКА, преобразовать каждую цифру через конструкцию ВЫБОР и собрать число умножением на разряды. Способ подходит для целых чисел из 3–6 знаков, например кодов и номеров.

Пример для строки из трёх цифр:

ВЫБРАТЬ

ВЫБОР КОГДА ПОДСТРОКА(Таб.Код, 1, 1) = "1" ТОГДА 1

КОГДА ПОДСТРОКА(Таб.Код, 1, 1) = "2" ТОГДА 2

ИНАЧЕ 0 КОНЕЦ * 100

+ ВЫБОР КОГДА ПОДСТРОКА(Таб.Код, 2, 1) = "1" ТОГДА 1

ИНАЧЕ 0 КОНЕЦ * 10

+ ВЫБОР КОГДА ПОДСТРОКА(Таб.Код, 3, 1) = "1" ТОГДА 1

ИНАЧЕ 0 КОНЕЦ КАК КодЧислом

Для краткости в примере показаны не все ветки ВЫБОР — в реальном запросе нужно перечислить цифры от 0 до 9 для каждого разряда. Текст запроса получается громоздким, но выполняется полностью на стороне СУБД и не требует промежуточной обработки.

Ограничения приёма очевидны: не поддерживаются дробная часть, знак минуса, разделители и пробелы; длина строки должна быть фиксированной или известной заранее; при каждом новом разряде текст запроса растёт линейно. Для строк длиннее 5–6 символов запрос становится неудобным в сопровождении.

Типичные ошибки
01
Писать ВЫРАЗИТЬ(Строка КАК ЧИСЛО) и ожидать разбора текста — запрос вернёт ошибку или NULL
02
Забыть ветку ИНАЧЕ в ВЫБОР — при нецифровом символе вся сумма превратится в NULL
03
Не учесть пробелы и неразрывные пробелы в строке — посимвольный разбор даст неверный результат
04
Применять посимвольный разбор к строкам переменной длины без выравнивания

Способ 2. Преобразование через временную таблицу

Более универсальный путь — выгрузить исходные строки во временную таблицу значений, преобразовать их функцией Число() встроенного языка и передать результат обратно в запрос как временную таблицу. Такой подход работает с любыми строками: дробными, отрицательными, с пробелами.

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

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

Пример фрагмента на встроенном языке:

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Ссылка");

ТЗ.Колонки.Добавить("ЗначениеЧислом", Новый ОписаниеТипов("Число"));

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

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

Строка = ТЗ.Добавить();

Строка.Ссылка = Выборка.Ссылка;

Попытка

Строка.ЗначениеЧислом = Число(Выборка.СтроковоеЗначение);

Исключение

Строка.ЗначениеЧислом = 0;

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

КонецЦикла;

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

Способ 3. Изменение типа данных в конфигурации

Если преобразование строки в число требуется постоянно — в отчётах, отборах, сортировках — правильное решение находится на уровне конфигурации, а не запроса. Числовые данные должны храниться в числовых реквизитах; строковое хранение чисел — признак ошибки проектирования или наследие обмена с внешними системами.

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

Сравнение способов и условия выбора

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

СпособКогда подходитОграничения
ПОДСТРОКА + ВЫБОРКороткие целые числа, запрос в СКД или динамическом спискеТолько целые, фиксированная длина, громоздкий текст
Временная таблица + Число()Пакетная обработка, отчёты на встроенном языкеТребует кода вне запроса, два обращения к данным
Числовой реквизитПостоянная потребность в числовых операцияхИзменение конфигурации, реструктуризация
Маршрут решения

Как выбрать действие

Строка — целое число до 4–5 знаков и запрос используется в СКДПримените посимвольный разбор через ПОДСТРОКА и ВЫБОР
Строки произвольного формата, есть дробные и отрицательные значенияПреобразуйте данные через временную таблицу и функцию Число()
Преобразование нужно постоянно во многих отчётах и отборахДобавьте числовой реквизит и заполняйте его при записи объекта
Данные приходят из обмена и строки могут содержать мусорОчищайте строку в коде перед вызовом Число()

Проверка результата преобразования

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

Для контроля полезно сравнить количество строк до и после преобразования, посчитать строки с нулевым или NULL-результатом и выборочно сверить несколько значений вручную. Если строка содержала лидирующие нули («007»), после преобразования в число они теряются — это нормально для расчётов, но недопустимо, если строка является кодом.

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

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

Количество строк в результате
Норма

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

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

Строки потеряны при соединении с временной таблицей

Значения NULL и 0
Норма

NULL отсутствуют, нули только там, где строка была пустой

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

Массовые NULL или нули на непустых строках

Дробная часть
Норма

Сохранена при посимвольном разборе не применялся

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

Дробная часть обрезана — разбор рассчитан только на целые

Лидирующие нули
Норма

Потеря нулей допустима для расчётного поля

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

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

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

Можно ли в запросе 1С преобразовать строку «123,45» в число с дробной частью?

Штатными средствами языка запросов — нет. Посимвольный разбор теоретически можно расширить на дробную часть, обрабатывая символы после запятой с делением на 10, 100 и так далее, но на практике проще и надёжнее использовать функцию Число() встроенного языка через временную таблицу.

Почему ВЫРАЗИТЬ(Поле КАК ЧИСЛО(10, 2)) возвращает ошибку?

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

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

Перед преобразованием очистите строку средствами встроенного языка: СтрЗаменить для удаления пробелов и символа неразрывного пробела (Символ(160)), затем СокрЛП. В запросе такая очистка практически невозможна.

Как отсортировать строковые числа по числовому значению без преобразования?

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

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

Да, конструкции ПОДСТРОКА и ВЫБОР полностью поддерживаются языком запросов, поэтому работают в наборах данных СКД, динамических списках и любых других местах, где выполняется запрос без возможности вставить код на встроенном языке.

Итог

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

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