Строка в число на встроенном языке 1С: от Число() до массовой загрузки
Содержание
Строку переводят в число функцией Число(Строка): Число("1250.75") вернёт 1250,75. Если в строке есть что-то кроме цифр, знака минус и точки, платформа выбросит исключение Преобразование значения к типу Число не может быть выполнено. Поэтому в рабочем коде вызов оборачивают в Попытка или заменяют на ОписаниеТипов("Число").ПривестиЗначение(), которое не падает, а возвращает 0.
Типичная ситуация: бухгалтер присылает выгрузку из банка или Excel, суммы в ней записаны как «1 250,75», и обработка загрузки валится на первой же строке. Перевести строку в число в 1С несложно, но сначала строку нужно привести к виду, который понимает платформа. Ниже — способы, подготовка данных, скорость на больших объёмах и что делать в запросе. Всё относится к платформе 8.3 и не зависит от конфигурации.
Чем перевести строку в число в 1С: четыре способа
В платформе нет функции ЧислоИзСтроки — это название встречается в форумах и чужих общих модулях. Штатных путей четыре.
Функция Число()
Самый прямой вариант. Ждёт строку с точкой в качестве десятичного разделителя.
Сумма = Число("1250.75"); // 1250.75
Сдача = Число("-15"); // -15
Код = Число("007"); // 7, ведущие нули отбрасываются
На некорректной строке — исключение. Это не баг, а способ сказать, что данные плохие.
ОписаниеТипов.ПривестиЗначение()
Приводит значение к указанному типу. Если привести нельзя, возвращает значение по умолчанию для типа, то есть 0.
ТипЧисло = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2));
Сумма = ТипЧисло.ПривестиЗначение("1250.756"); // 1250.76 — округлено до 2 знаков
Брак = ТипЧисло.ПривестиЗначение("abc"); // 0, без исключения
Минус способа: «0» в исходной строке и мусор дают один результат. Если важно отличить ошибку от нуля — этот вариант не подходит.
XMLЗначение()
Читает число из XML-представления, где разделитель всегда точка.
Сумма = XMLЗначение(Тип("Число"), "1250.75");
Удобно в паре с XMLСтрока(): что записали XMLСтрока(Сумма), то гарантированно прочитаете обратно. На мусоре тоже выбрасывает исключение.
СтрокаВЧисло() из БСП
Во всех типовых конфигурациях на Библиотеке стандартных подсистем есть СтроковыеФункцииКлиентСервер.СтрокаВЧисло(Значение). Если строку не удалось преобразовать, функция возвращает Неопределено. В самописной конфигурации без БСП её нет.
| Способ | Ошибка на мусоре | Плюс | Минус |
|---|---|---|---|
Число() | исключение | быстрый, понятный | нужен Попытка |
ОписаниеТипов.ПривестиЗначение() | возвращает 0 | не падает, округляет по квалификатору | 0 и ошибка неразличимы |
XMLЗначение() | исключение | надёжен для обмена | только «XML-формат» строки |
СтрокаВЧисло() (БСП) | Неопределено | ошибка видна явно | только в конфигурациях с БСП |
Как преобразовать строку в число без падения обработки
Попытка — Исключение
Базовый шаблон для единичного значения:
Попытка
Количество = Число(СтрокаКоличества);
Исключение
Количество = 0;
Сообщить(СтрШаблон("Строка %1: не число «%2»", НомерСтроки, СтрокаКоличества));
КонецПопытки;
Не глотайте исключение молча. Пустой блок Исключение превращает кривые данные в нули, и бухгалтер узнает о проблеме только при сверке остатков.
Склеивая сообщение, не подставляйте число напрямую: "Строка " + 1250 даст «1 250» с неразрывным пробелом. Для номеров строк используйте Формат(НомерСтроки, "ЧГ=0") или СтрШаблон().
Проверка перед преобразованием
Если нужно точно знать, что строка — число, проверьте её посимвольно. Функция ниже допускает цифры, одну точку и минус только в начале:
Функция ЭтоЗаписьЧисла(Текст)
Цифры = "0123456789";
БылаТочка = Ложь;
БылаЦифра = Ложь;
Для Позиция = 1 По СтрДлина(Текст) Цикл
Символ = Сред(Текст, Позиция, 1);
Если СтрНайти(Цифры, Символ) > 0 Тогда
БылаЦифра = Истина;
ИначеЕсли Символ = "." И Не БылаТочка Тогда
БылаТочка = Истина;
ИначеЕсли Символ = "-" И Позиция = 1 Тогда
Продолжить;
Иначе
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат БылаЦифра;
КонецФункции
Строки «-», «.» и пустая строка вернут Ложь: флаг БылаЦифра не даст их пропустить.
Универсальная функция для общего модуля
Объединим очистку, проверку и преобразование. Функцию удобно положить в общий модуль с флагами «Клиент» и «Сервер»:
Функция СтрокаВЧислоБезопасно(Знач Значение, ПоУмолчанию = 0) Экспорт
Если ТипЗнч(Значение) = Тип("Число") Тогда
Возврат Значение;
КонецЕсли;
Текст = СокрЛП(Строка(Значение));
Текст = СтрЗаменить(Текст, Символы.НПП, "");
Текст = СтрЗаменить(Текст, " ", "");
Текст = СтрЗаменить(Текст, ",", ".");
Если Не ЭтоЗаписьЧисла(Текст) Тогда
Возврат ПоУмолчанию;
КонецЕсли;
Возврат Число(Текст);
КонецФункции
После ЭтоЗаписьЧисла строка содержит только допустимые символы, поэтому Попытка здесь уже не нужна. Через параметр ПоУмолчанию можно передать Неопределено, чтобы отличать ошибку от нуля.
Отдельно о значениях, которые приходят из запроса или реквизита составного типа. Там вместо строки бывает Null или Неопределено. Строка(Null) даёт пустую строку, поэтому функция вернёт ПоУмолчанию, а не упадёт. Но если такие значения в данных встречаться не должны, лучше поймать их раньше: проверьте Значение = Null до вызова и запишите номер строки в журнал загрузки. Тогда пустые суммы не растворятся среди честных нулей.
Запятая, пробелы и валюта: как подготовить строку к переводу в число
Чаще всего строка не переводится не из-за букв, а из-за формата. Вот что приходит из внешних источников и что с этим делать:
| Исходная строка | Откуда берётся | Что сделать |
|---|---|---|
1250,75 | Excel, ручной ввод | заменить запятую на точку |
1 250,75 (неразрывный пробел) | Строка() от числа, печатные формы | убрать Символы.НПП и запятую заменить |
1 250.75 (обычный пробел) | CSV, банковские выписки | убрать пробелы |
1250.75 руб. | текстовые отчёты | отрезать хвост, оставить цифры |
(1250.75) | бухгалтерские отчёты, отрицательные суммы | скобки → минус |
1,250.75 | англоязычные системы | сначала убрать запятую, точку не трогать |
Последняя строка — ловушка. Если универсально менять запятую на точку, «1,250.75» превратится в «1.250.75», проверка вернёт Ложь, и сумма станет нулём. Когда источник известен, пишите отдельную очистку под него.
💡 При загрузке из табличного документа читайте не Область.Текст, а значение ячейки, если оно хранится как число. Текст ячейки — это то, что видно на экране, с разделителями групп и форматом. Значение (свойство Значение при СодержитЗначение = Истина) уже является числом, и переводить ничего не нужно.
- 🔍 Перед загрузкой файла проверьте 5–10 строк глазами: где разделитель, есть ли пробелы.
- 🧹 Чистите строку в одной функции, а не разбросанными
СтрЗаменитьпо всей обработке. - 🧾 Логируйте исходное значение строки, которая не прошла: так проще найти виновника в файле.
Обратный путь: как записать число в строку, чтобы потом её прочитать
Классическая ошибка — сохранить число через Строка() и потом пытаться прочитать его через Число():
Текст = Строка(1250.75); // "1 250,75" — с разделителем групп и запятой
Сумма = Число(Текст); // исключение
Строка() форматирует число по региональным настройкам: разделитель групп разрядов и запятая. Чтобы записать число в «машинный» вид, есть два варианта:
Текст1 = Формат(1250.75, "ЧРД=.; ЧГ=0"); // "1250.75"
Текст2 = XMLСтрока(1250.75); // "1250.75"
ЧРД задаёт символ десятичного разделителя, ЧГ=0 отключает группировку разрядов. Для хранения в реквизитах, регистрах сведений и файлах обмена берите XMLСтрока() — пару к ней составляет XMLЗначение().
Нулевое значение Формат() по умолчанию возвращает пустую строку. Если затем передать её в Число(), будет исключение. Добавьте параметр ЧН=0, чтобы ноль выводился как «0»: Формат(0, "ЧРД=.; ЧГ=0; ЧН=0").
Перевод строк в числа при массовой загрузке: скорость
На десятке строк разницы между способами нет. На выписке в 50 000 операций или прайсе на 200 000 позиций она становится заметной.
Что тормозит
- 🐢 Исключения. Выброс и перехват исключения стоит намного дороже обычной проверки. Если в файле много пустых или текстовых ячеек, цикл с
Попыткана каждой строке замедляется сильнее всего. - 🐢 Создание объектов в цикле.
Новый ОписаниеТипов(...)внутри цикла создаёт объект на каждой итерации. - 🐢 Клиент-серверные вызовы. Преобразование каждой строки отдельным серверным вызовом из формы — самый медленный вариант из возможных.
Как ускорить
- Создайте
ОписаниеТиповодин раз до цикла и используйте его повторно. - Отсекайте пустые значения проверкой
ПустаяСтрока()до любого преобразования. - Передавайте на сервер весь файл или таблицу значений целиком и преобразуйте там одним проходом.
- Если источник надёжный (собственная выгрузка через
XMLСтрока()), не делайте посимвольную проверку — хватитЧисло()вПопытка.
ТипСумма = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2));
Для Каждого СтрокаТЗ Из ТаблицаЗагрузки Цикл
Если ПустаяСтрока(СтрокаТЗ.СуммаТекст) Тогда
СтрокаТЗ.Сумма = 0;
Продолжить;
КонецЕсли;
Текст = СтрЗаменить(СтрЗаменить(СтрокаТЗ.СуммаТекст, " ", ""), ",", ".");
СтрокаТЗ.Сумма = ТипСумма.ПривестиЗначение(Текст);
КонецЦикла;
Ещё быстрее — сразу задать колонке таблицы значений тип «Число» через ОписаниеТипов: при присвоении строки в такую колонку значение будет приведено к типу колонки. Правило то же, что у ПривестиЗначение: непреобразуемое станет нулём.
Строка в число в запросе 1С
В языке запросов ВЫРАЗИТЬ не умеет превращать строку в число. Конструкция ВЫРАЗИТЬ(Таблица.Код КАК ЧИСЛО(10, 0)) для строкового поля даст ошибку несовместимости типов. Функции Число() в запросе нет.
Что делают на практике:
- Преобразуют после запроса. Выгружают результат в таблицу значений и проходят по ней кодом. Самый простой и надёжный вариант.
- Добавляют числовой реквизит. Если поле постоянно нужно как число (сортировка, сравнение), заведите реквизит типа «Число» и заполняйте его при записи объекта. В том числе в расширении, если конфигурация типовая.
- Разбирают по символам через ВЫБОР. Для коротких строк фиксированной длины цифру можно получить так:
ВЫБОР ПОДСТРОКА(Т.Код, 1, 1)
КОГДА "1" ТОГДА 1 КОГДА "2" ТОГДА 2 КОГДА "3" ТОГДА 3
КОГДА "4" ТОГДА 4 КОГДА "5" ТОГДА 5 КОГДА "6" ТОГДА 6
КОГДА "7" ТОГДА 7 КОГДА "8" ТОГДА 8 КОГДА "9" ТОГДА 9
ИНАЧЕ 0
КОНЕЦ * 100
Для трёхзначного кода повторяют блок для второго и третьего символа с множителями 10 и 1 и складывают. Работает, но читается тяжело и ломается на любом нецифровом символе. Используйте этот приём только когда без вычисления в самом запросе не обойтись — например, в условии отбора по диапазону кодов.
💡 Часто числовое преобразование кода нужно только для правильной сортировки («2» после «10»). Если коды одной длины с ведущими нулями («0002», «0010»), строковая сортировка уже совпадает с числовой.
Ошибки при переводе строки в число и как их разобрать
Частые вопросы
Как проверить, что значение уже является числом?
ТипЗнч(Значение) = Тип("Число"). Если условие истинно, преобразование не нужно.Можно ли перевести в число строку с шестнадцатеричной записью?
ЧислоИзШестнадцатеричнойСтроки() и ЧислоИзДвоичнойСтроки(). Требования к формату строки уточните в синтаксис-помощнике конфигуратора.Почему Число() принимает «007» и возвращает 7?
Как перевести строку в число с округлением до копеек?
ОписаниеТипов с квалификатором Новый КвалификаторыЧисла(15, 2) или примените Окр(Число(Текст), 2) после преобразования.Что вернёт СтрокаВЧисло из БСП на пустой строке?
Неопределено, как и на любой непреобразуемой строке. Проверяйте результат на Неопределено до использования в расчётах.