Разработка и Конфигурация · 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 символов запрос становится неудобным в сопровождении.
Способ 2. Преобразование через временную таблицу
Более универсальный путь — выгрузить исходные строки во временную таблицу значений, преобразовать их функцией Число() встроенного языка и передать результат обратно в запрос как временную таблицу. Такой подход работает с любыми строками: дробными, отрицательными, с пробелами.
Порядок действий: выполнить первый запрос, выбрать строковые значения, пройти по выборке циклом, заполнить таблицу значений с колонкой числового типа, затем поместить её в менеджер временных таблиц и соединить с основными данными во втором запросе.
- 1Создайте МенеджерВременныхТаблиц и выполните запрос, выбирающий строковые значения
- 2Обойдите результат циклом и заполните таблицу значений: ключ связи и Число(СтроковоеЗначение)
- 3Оберните преобразование в попытку или проверяйте строку перед вызовом Число()
- 4Поместите таблицу значений в запрос через ВТ и соедините с основными данными
- 5Проверьте итоговый результат на NULL и нулевые значения
Пример фрагмента на встроенном языке:
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("Ссылка");
ТЗ.Колонки.Добавить("ЗначениеЧислом", Новый ОписаниеТипов("Число"));
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Строка = ТЗ.Добавить();
Строка.Ссылка = Выборка.Ссылка;
Попытка
Строка.ЗначениеЧислом = Число(Выборка.СтроковоеЗначение);
Исключение
Строка.ЗначениеЧислом = 0;
КонецПопытки;
КонецЦикла;
Функция Число() сама выбрасывает исключение на нечисловых строках, поэтому обработка через Попытка/Исключение обязательна, если качество данных не гарантировано. Альтернатива — предварительная проверка строки: пробелы, запятая вместо точки, посторонние символы.
Способ 3. Изменение типа данных в конфигурации
Если преобразование строки в число требуется постоянно — в отчётах, отборах, сортировках — правильное решение находится на уровне конфигурации, а не запроса. Числовые данные должны храниться в числовых реквизитах; строковое хранение чисел — признак ошибки проектирования или наследие обмена с внешними системами.
Варианты действий: изменить тип существующего реквизита с переносом данных обработкой, добавить новый числовой реквизит и заполнять его при записи объекта, либо хранить оба поля — строковое для отображения и числовое для расчётов. Последний вариант типичен для кодов с лидирующими нулями: строка «00123» как код и число 123 для сортировки.
Сравнение способов и условия выбора
Выбор зависит от длины строки, допустимости изменения конфигурации и требований к производительности. Посимвольный разбор оправдан, когда запрос должен остаться самодостаточным — например, в СКД или динамическом списке, где нет возможности выполнить код на встроенном языке.
| Способ | Когда подходит | Ограничения |
|---|---|---|
| ПОДСТРОКА + ВЫБОР | Короткие целые числа, запрос в СКД или динамическом списке | Только целые, фиксированная длина, громоздкий текст |
| Временная таблица + Число() | Пакетная обработка, отчёты на встроенном языке | Требует кода вне запроса, два обращения к данным |
| Числовой реквизит | Постоянная потребность в числовых операциях | Изменение конфигурации, реструктуризация |
Как выбрать действие
Проверка результата преобразования
После любого преобразования нужно убедиться, что данные не потерялись и не исказились. Основные риски: NULL вместо числа, обнуление нечисловых значений, потеря дробной части и лидирующих нулей.
Для контроля полезно сравнить количество строк до и после преобразования, посчитать строки с нулевым или NULL-результатом и выборочно сверить несколько значений вручную. Если строка содержала лидирующие нули («007»), после преобразования в число они теряются — это нормально для расчётов, но недопустимо, если строка является кодом.
Как проверить результат
Совпадает с количеством исходных строк
Строки потеряны при соединении с временной таблицей
NULL отсутствуют, нули только там, где строка была пустой
Массовые NULL или нули на непустых строках
Сохранена при посимвольном разборе не применялся
Дробная часть обрезана — разбор рассчитан только на целые
Потеря нулей допустима для расчётного поля
Код с нулями используется как строка, а преобразование их уничтожило
Частые вопросы
Можно ли в запросе 1С преобразовать строку «123,45» в число с дробной частью?
Штатными средствами языка запросов — нет. Посимвольный разбор теоретически можно расширить на дробную часть, обрабатывая символы после запятой с делением на 10, 100 и так далее, но на практике проще и надёжнее использовать функцию Число() встроенного языка через временную таблицу.
Почему ВЫРАЗИТЬ(Поле КАК ЧИСЛО(10, 2)) возвращает ошибку?
Потому что поле имеет строковый тип, а ВЫРАЗИТЬ не выполняет разбор текста — она только приводит уже числовые значения к указанной разрядности. Для строк такая конструкция не поддерживается платформой.
Что делать, если в строке встречаются пробелы или неразрывные пробелы?
Перед преобразованием очистите строку средствами встроенного языка: СтрЗаменить для удаления пробелов и символа неразрывного пробела (Символ(160)), затем СокрЛП. В запросе такая очистка практически невозможна.
Как отсортировать строковые числа по числовому значению без преобразования?
Если все строки одинаковой длины, строковая сортировка совпадает с числовой. Для строк разной длины можно дополнить их лидирующими нулями до одинаковой длины либо отсортировать сначала по длине строки, затем по самой строке.
Работает ли посимвольный разбор в СКД и динамических списках?
Да, конструкции ПОДСТРОКА и ВЫБОР полностью поддерживаются языком запросов, поэтому работают в наборах данных СКД, динамических списках и любых других местах, где выполняется запрос без возможности вставить код на встроенном языке.
Что важно запомнить
Прямого преобразования строки в число в запросе 1С не существует: ВЫРАЗИТЬ к типу Число работает только с уже числовыми значениями. Для коротких целых строк применяйте разбор через ПОДСТРОКА и ВЫБОР, для произвольных строк — преобразование через временную таблицу с Число(), а при постоянной потребности — храните данные в числовом реквизите.