Разработка и Конфигурация · 11 мин
Выразить строку как число в 1С: способы и подводные камни
Как в 1С выразить строку как число: функция Число(), СтрокаВЧисло, обработка пробелов и разделителей, проверка корректности, типичные ошибки и примеры кода.
Задача выразить строку как число в 1С возникает постоянно: данные приходят из файлов Excel и CSV, из веб-сервисов, из обменов с сайтом, из пользовательского ввода — и почти всегда в виде строки. Пока значение остаётся строкой, с ним нельзя выполнять арифметику, сравнивать по величине, использовать в итогах запросов и проводках. Поэтому преобразование — одна из первых операций при любой загрузке внешних данных.
Во встроенном языке 1С есть несколько способов такого преобразования: конструктор Число(), функция СтроковыеФункцииКлиентСервер.СтрокаВЧисло() из БСП, операторная форма через описание типов и неявное приведение в запросах. Каждый способ ведёт себя по-разному с пробелами, разделителями, знаком минус и некорректными значениями, и именно эти различия чаще всего становятся источником ошибок в обменах.
Ниже разобраны рабочие варианты преобразования, поведение функций в спорных ситуациях, способы проверить строку до конвертации и типичные ошибки, из-за которых в учёт попадают нули вместо реальных сумм.
Базовый способ: функция Число()
Конструктор Число() — штатный способ явного преобразования строки в число во встроенном языке. Он принимает строковое представление и возвращает значение типа «Число»:
СтрокаСумма = "1250.75";
Сумма = Число(СтрокаСумма); // 1250.75, тип Число
Функция ожидает, что дробная часть отделена точкой, а минус стоит перед числом без пробела. Если строка не может быть интерпретирована как число, исключения не возникает — функция молча возвращает 0. Именно это поведение опаснее всего: ошибка формата не останавливает обработку, а превращается в нулевую сумму, которая затем уходит в документы и отчёты.
Ещё одна особенность — пустая строка. Число("") также вернёт 0, что формально корректно, но не позволяет отличить «в файле был ноль» от «в файле ничего не было». Если для учёта важно различие, проверяйте строку на пустоту до преобразования.
Подготовка строки перед преобразованием
Реальные данные из файлов почти никогда не приходят в «чистом» виде. Типичные помехи: пробелы-разделители тысяч («1 250 000»), неразрывные пробелы из Excel (символ с кодом 160), запятая как десятичный разделитель в русской локали, символ валюты, знак минус в конце строки из некоторых выгрузок. Каждая из этих помех превратит Число() в 0.
Минимальная чистка перед преобразованием выглядит так:
Функция СтрокаВЧислоБезопасно(ИсходнаяСтрока)
Результат = СокрЛП(ИсходнаяСтрока);
Результат = СтрЗаменить(Результат, Символ(160), ""); // неразрывный пробел
Результат = СтрЗаменить(Результат, " ", ""); // разделители тысяч
Результат = СтрЗаменить(Результат, ",", "."); // десятичный разделитель
Возврат Число(Результат);
КонецФункции
Обратите внимание на порядок: сначала удаляются все пробельные символы, потом заменяется запятая. Если в исходных данных запятая используется как разделитель тысяч (английский формат «1,250.75»), такая замена испортит число — для этого формата запятую нужно удалять, а не заменять. Поэтому перед написанием обработки всегда смотрите на реальные образцы данных, а не на предположения о формате.
- 1Получите реальный образец строки из файла или сервиса и определите формат: разделитель дробной части, разделитель тысяч, положение знака
- 2Очистите строку: СокрЛП, удаление неразрывных пробелов (Символ(160)) и разделителей тысяч
- 3Приведите десятичный разделитель к точке, если в данных используется запятая
- 4Проверьте строку регулярным выражением или посимвольно: остались ли только цифры, точка и минус
- 5Выполните Число() и зафиксируйте результат; при расхождении с ожиданием запишите строку в протокол ошибок
Проверка строки до преобразования
Раз Число() не сообщает об ошибке, проверку приходится делать вручную. Самый надёжный критерий: строка должна состоять только из цифр, не более одной точки и, возможно, ведущего минуса. Простая проверка посимвольным перебором:
Функция ЭтоЧисло(Строка)
Допустимые = "0123456789.-";
Для Позиция = 1 По СтрДлина(Строка) Цикл
Если СтрНайти(Допустимые, Сред(Строка, Позиция, 1)) = 0 Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
В конфигурациях на базе Библиотеки стандартных подсистем есть готовая функция СтроковыеФункцииКлиентСервер.СтрокаВЧисло(). Она возвращает число либо Неопределено, если строка не является числом, — это удобнее, чем молчаливый ноль, потому что позволяет явно отличить ошибку от нулевого значения:
Значение = СтроковыеФункцииКлиентСервер.СтрокаВЧисло(СтрокаИзФайла);
Если Значение = Неопределено Тогда
// строка не число — фиксируем ошибку загрузки
КонецЕсли;
Также есть классический приём с ОписаниеТипов: метод ПривестиЗначение() пытается привести строку к заданному типу. Для строки, не являющейся числом, он вернёт 0, поэтому как валидатор он подходит слабо, но удобен, когда нужно одновременно ограничить разрядность, например привести к «Число(15,2)».
Сравнение способов
Универсально и без зависимостей, но при ошибке формата молча возвращает 0 — нужна ручная проверка
Возвращает Неопределено при ошибке — удобно для загрузок; требует БСП в конфигурации
Позволяет сразу задать разрядность и отсечь лишние знаки; ошибку формата тоже маскирует в 0
Работает только в тексте запроса, для строковых реквизитов; не подходит для произвольного кода
Преобразование в запросах: ВЫРАЗИТЬ и подводные камни
Когда строка хранится в реквизите объекта или регистра, преобразование делается прямо в запросе оператором ВЫРАЗИТЬ:
ВЫБРАТЬ
ВЫРАЗИТЬ(Данные.СтрокаСумма КАК ЧИСЛО(15, 2)) КАК Сумма
ИЗ
РегистрСведений.ЗагруженныеДанные КАК Данные
Здесь действуют те же правила формата: строка должна содержать корректное строковое представление числа. Если в поле попадёт «1 200,50» или «abc», результат приведения зависит от СУБД, но рассчитывать на корректное значение нельзя — чаще получите 0 или NULL. Поэтому ВЫРАЗИТЬ применяют к данным, формат которых контролируется на этапе записи, а не к сырым выгрузкам.
Отдельное предупреждение: не используйте ВЫРАЗИТЬ к числу как способ сравнения строк. Если реквизит строковый и в нём коды вида «000123», приведение к числу уничтожит ведущие нули и нарушит соединения. Для кодов и артикулов строковый тип обычно нужно сохранять, а не преобразовывать.
Типичные сценарии и особые случаи
Отрицательные числа и знак в конце строки
Некоторые банковские и бухгалтерские выгрузки ставят минус после числа: «1250.00-». Функция Число() такую строку не поймёт. Обработка — проверить последний символ и перенести знак в начало:
Если Прав(Строка, 1) = "-" Тогда
Строка = "-" + Лев(Строка, СтрДлина(Строка) - 1);
КонецЕсли;
Число в экспоненциальной записи
Из научных систем и некоторых API приходят значения вида «1.25E+3». Поведение Число() с такой записью зависит от платформы, поэтому надёжнее распарсить мантиссу и порядок вручную или нормализовать формат ещё на стороне источника.
Строка с числом и единицей измерения
Строки вида «15 кг» или «1200 руб.» требуют предварительного извлечения числовой части — например, перебором символов до первого нечислового или регулярным выражением. Только после отделения числа от единицы применяйте преобразование.
Проверка результата и контроль загрузки
После преобразования результат стоит верифицировать, особенно при массовой загрузке. Минимальный набор контролей: количество успешно преобразованных строк против общего числа, сумма по загруженным числовым полям против контрольной суммы из источника, список строк, которые не удалось преобразовать.
Хорошая практика — вести протокол: для каждой строки, где преобразование дало 0 при непустой исходной строке, записывать исходное значение и номер строки файла. Это позволяет быстро найти новый формат данных, который обработка не учитывает, вместо того чтобы искать расхождения уже в учётных регистрах.
При разовых операциях полезен ручной контроль: возьмите 3–5 строк из файла, преобразуйте их в консоли кода и сравните с ожидаемыми значениями до запуска полной загрузки. Это занимает минуту и отсекает большинство проблем формата.
Как проверить результат
Совпадает с числом в исходной строке с учётом формата
0 при непустой исходной строке с видимым числом
Сходится с контрольной суммой источника
Расхождение или подозрительно много нулевых строк
Пуст или содержит только реально пустые значения
Строки с числами, которые не распознаны
FAQ
Почему Число("1 250") возвращает 0?
Потому что пробел внутри строки делает её некорректным представлением числа, а Число() при невозможности преобразования возвращает 0 без ошибки. Удалите пробелы через СтрЗаменить, включая неразрывный пробел Символ(160), и повторите преобразование.
Как отличить ошибку формата от реального нуля в данных?
Функцией Число() — никак, она в обоих случаях даёт 0. Используйте СтроковыеФункцииКлиентСервер.СтрокаВЧисло() из БСП: она вернёт Неопределено при ошибке. Либо проверяйте строку собственной функцией до преобразования.
Как преобразовать строку с запятой, например "123,45"?
Сначала замените запятую на точку: СтрЗаменить(Строка, ",", "."), затем примените Число(). Но убедитесь, что запятая в ваших данных — именно десятичный разделитель, а не разделитель тысяч, иначе число будет испорчено.
Можно ли преобразовать строку в число прямо в запросе?
Да, оператором ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15,2)). Но это работает корректно только для строк в ожидаемом формате: с точкой и без пробелов. Для сырых данных из файлов надёжнее преобразовывать в коде при загрузке.
Что делать с числами вида "1250.00-" из банковской выгрузки?
Проверьте последний символ строки: если это минус, перенесите его в начало (Прав() и Лев()), затем выполняйте преобразование. Число() понимает только ведущий знак минус.
Теряются ли ведущие нули при преобразовании "000123" в число?
Да, результатом будет число 123, и обратно исходную строку не восстановить без форматирования. Если значение — код или артикул, а не величина для расчётов, храните его строкой и не преобразовывайте.
Что важно запомнить
Число() преобразует строку с точкой-разделителем и молча возвращает 0 при любой ошибке формата. Перед преобразованием очищайте строку от пробелов (включая неразрывные), приводите разделитель к точке и проверяйте результат. Для загрузок удобнее СтрокаВЧисло() из БСП, а контроль итогов после загрузки — обязательный шаг.