Разработка и Конфигурация · 10 мин
Как преобразовать значение в число в 1С
Как преобразовать строку или другое значение в число в 1С: функция Число(), ОписаниеТипов, обработка ошибок, разделители, примеры кода и типичные ошибки разработчиков.
Преобразование значения в число — одна из самых частых операций при разработке на встроенном языке 1С. Данные приходят из файлов Excel и CSV, из веб-сервисов, из полей ввода на форме, и почти всегда они представлены строкой. Пока значение остаётся строкой, с ним нельзя выполнять арифметику, сравнения по величине и корректную сортировку.
Платформа 1С:Предприятие предлагает несколько способов такого преобразования: функцию Число(), приведение через ОписаниеТипов, методы работы со строками из типовых библиотек. У каждого способа есть ограничения: одни вызывают исключение при неверных данных, другие молча возвращают ноль. Выбор зависит от того, насколько вы доверяете источнику данных и что должно произойти при ошибке.
Ниже разобраны основные приёмы преобразования, обработка нестандартных форматов (пробелы, запятые, неразрывные пробелы), проверка результата и типичные ошибки, которые приводят к потере данных или падению кода.
Функция Число() — базовый способ преобразования
Встроенная функция Число() принимает значение и возвращает его числовое представление. Она работает со строками, булевыми значениями и датами. Синтаксис предельно прост:
Результат = Число("123,45"); // 123,45
Результат = Число(Истина); // 1
Результат = Число(Ложь); // 0
При преобразовании строки функция строга к формату. Строка должна содержать только цифры, необязательный знак минус в начале и один разделитель дробной части. Допустимы как точка, так и запятая — платформа распознаёт оба варианта. Любые другие символы (буквы, пробелы внутри числа, символы валют) приводят к ошибке «Преобразование значения к типу Число не может быть выполнено».
Важная особенность: пустая строка и строка из пробелов также вызывают исключение. Поэтому вызывать Число() напрямую на данных из внешних источников без предварительной проверки небезопасно.
Обработка ошибок через Попытка/Исключение
Самый надёжный способ защититься от падения кода — обернуть преобразование в конструкцию Попытка...Исключение. В блоке исключения можно задать значение по умолчанию и записать проблемную строку в журнал регистрации для последующего разбора.
Функция СтрокаВЧисло(Строка)
Результат = 0;
Попытка
Результат = Число(Строка);
Исключение
ЗаписьЖурналаРегистрации("Загрузка данных",
УровеньЖурналаРегистрации.Предупреждение,,,
"Не удалось преобразовать в число: " + Строка);
КонецПопытки;
Возврат Результат;
КонецФункции
Такой подход удобен при пакетной загрузке: одна «битая» строка не остановит обработку тысячи корректных записей. Недостаток — исключения в платформе относительно дорогая операция, поэтому в циклах с большим процентом ошибок лучше сначала проверять строку, а не ловить исключения.
Попытка
Значение = Число(СтрокаИзФайла);
Исключение
Значение = 0;
КонецПопытки;Очистка строки перед преобразованием
Реальные данные редко приходят в чистом виде. Числа из Excel часто содержат пробелы-разделители разрядов («1 234 567»), неразрывные пробелы (символ с кодом 160), символы валют и разные разделители дробной части. Перед вызовом Число() строку нужно нормализовать.
Типовая последовательность очистки выглядит так:
Строка = "1 234 567,89 руб.";
Строка = СтрЗаменить(Строка, Символ(160), ""); // неразрывный пробел
Строка = СтрЗаменить(Строка, " ", ""); // обычные пробелы
Строка = СтрЗаменить(Строка, "руб.", "");
Строка = СокрЛП(Строка);
Значение = Число(Строка); // 1234567,89
Неразрывный пробел — самая коварная проблема: визуально он неотличим от обычного пробела, но СокрЛП() и замена обычного пробела его не убирают. Если преобразование «непонятно почему» падает на внешне корректной строке, проверьте наличие символа с кодом 160 в первую очередь.
- 1Уберите неразрывные пробелы: СтрЗаменить(Строка, Символ(160), "")
- 2Удалите обычные пробелы и посторонние символы (валюта, единицы измерения)
- 3При необходимости приведите разделитель дробной части к точке или запятой
- 4Выполните СокрЛП() и вызовите Число() внутри Попытка/Исключение
- 5Проверьте результат на контрольном примере с дробным числом
Преобразование через ОписаниеТипов
Альтернативный способ — приведение значения через объект ОписаниеТипов. Метод ПривестиЗначение() не вызывает исключения: если преобразование невозможно, он возвращает значение по умолчанию для типа, то есть ноль.
ОписаниеЧисла = Новый ОписаниеТипов("Число",
Новый КвалификаторыЧисла(15, 2));
Значение = ОписаниеЧисла.ПривестиЗначение("abc"); // 0, без ошибки
Такой вариант удобен, когда ошибочное значение равнозначно нулю и прерывать выполнение не нужно. Кроме того, ОписаниеТипов позволяет сразу ограничить разрядность: лишние знаки после запятой будут отброшены по правилам округления платформы.
Однако у молчаливого преобразования есть обратная сторона: «тихий» ноль может замаскировать проблему в данных. Если ноль и ошибка для вашей логики — разные вещи, комбинируйте приведение с проверкой исходной строки или используйте вариант с исключением.
Сравнение вариантов
Быстро и просто, но падает с ошибкой на некорректной строке. Подходит для гарантированно чистых данных.
Надёжно для ненадёжных источников, позволяет логировать ошибки. Чуть медленнее при массовых ошибках.
Не вызывает исключений, возвращает 0 при ошибке. Риск: ошибка в данных маскируется нулём.
Преобразование других типов в число
Булево и дата
Булевы значения преобразуются однозначно: Истина становится единицей, Ложь — нулём. Это используется, например, при выгрузке флагов в форматы, где допустимы только числа.
Дата функцией Число() преобразуется в количество секунд, прошедших с начала эпохи (1 января 0001 года). На практике такое преобразование применяется редко; чаще нужен обратный приём — получить из даты год, месяц или день через функции Год(), Месяц(), День(), которые уже возвращают числа.
Значения из полей формы
Если реквизит формы имеет строковый тип, а пользователь вводит туда числа, преобразование выполняется теми же средствами. Но правильнее сразу задать реквизиту тип «Число» — тогда платформа сама контролирует ввод, не допускает буквы и хранит значение в нужном виде, избавляя от ручного преобразования.
Типичные ошибки и как их избежать
Первая распространённая ошибка — преобразование строки с разделителем групп разрядов. Число «1 000 000» после удаления пробелов превращается в корректное значение, но если разделитель — точка («1.000.000» в некоторых локалях), результат будет совершенно иным. Всегда уточняйте формат источника данных перед написанием кода очистки.
Вторая ошибка — потеря точности при работе с большими числами. Числа в 1С имеют ограниченную разрядность (по умолчанию при хранении в реквизитах — до 38 знаков, но конкретный предел задаётся квалификаторами). Если вы приводите значение через ОписаниеТипов с квалификатором 15,2, а исходное число длиннее, «лишняя» часть будет отброшена без предупреждения.
Третья ошибка — использование строковых функций поиска для проверки «числовости». Проверка вида «если в строке только цифры» через перебор символов надёжнее реализуется регулярными выражениями или попыткой преобразования, а ручные проверки часто забывают про знак минус и разделитель дробной части.
Проверка результата преобразования
После преобразования полезно убедиться, что результат соответствует ожиданиям. Минимальный набор проверок: тип значения (ТипЗнч(Значение) = Тип("Число")), попадание в допустимый диапазон и совпадение с исходной строкой после обратного форматирования.
Для контрольных примеров берите граничные случаи: отрицательное число, число с дробной частью, строку с пробелами-разделителями, пустую строку. Если обработка корректно отрабатывает все четыре случая, она с высокой вероятностью выдержит реальные данные.
Как проверить результат
ТипЗнч() возвращает Число
Осталась строка или Неопределено
1234,56 преобразуется в 1234,56
Дробная часть обрезана или число умножено на 100
Некорректная строка даёт 0 и запись в журнале
Выполнение прерывается исключением
Часто задаваемые вопросы
Что вернёт Число() для пустой строки?
Функция вызовет исключение «Преобразование значения к типу Число не может быть выполнено». Если пустые значения допустимы, проверяйте строку через ПустаяСтрока() до вызова или используйте ОписаниеТипов.ПривестиЗначение(), который вернёт 0.
Как преобразовать строку с запятой, если данные приходят с точкой?
Функция Число() понимает оба разделителя — и точку, и запятую, поэтому замена обычно не нужна. Замена требуется только когда в одной строке встречаются оба символа (например, «1,234.56»): тогда сначала удалите разделитель разрядов, затем приведите дробный разделитель к одному виду.
Можно ли преобразовать в число значение типа Неопределено или NULL?
Напрямую — нет, будет ошибка. Сначала замените такие значения, например: Строка = ?(Значение = Неопределено, "0", Значение). При работе с результатами запросов NULL удобно обрабатывать функцией ЕСТЬNULL(Поле, 0) прямо в тексте запроса.
Чем отличается Число() от приведения в запросе через ВЫРАЗИТЬ?
ВЫРАЗИТЬ(Поле КАК ЧИСЛО(15,2)) работает на уровне СУБД в запросе и при невозможности преобразования возвращает NULL, а не ошибку. Число() работает в коде встроенного языка и при ошибке вызывает исключение. Выбор зависит от того, где обрабатываются данные.
Как проверить, что строка содержит число, не вызывая исключение?
Используйте ОписаниеТипов.ПривестиЗначение() и сравните результат с исходной строкой через обратное форматирование, либо примените регулярное проверку на допустимые символы. В типовых конфигурациях также встречаются готовые функции вида СтроковыеФункцииКлиентСервер.СтрокаВЧисло() — проверьте их наличие в вашей конфигурации.
Почему после преобразования пропадают копейки?
Чаще всего причина в квалификаторах числа: если значение приводится через ОписаниеТипов с нулевой точностью или записывается в реквизит с разрядностью дробной части 0, дробная часть отбрасывается. Проверьте квалификаторы числа у реквизита или в описании типов и увеличьте точность до нужного количества знаков.
Что важно запомнить
Для чистых данных используйте Число(), для ненадёжных — очистку строки плюс Попытка/Исключение, а когда ошибка равнозначна нулю — ОписаниеТипов.ПривестиЗначение(). Всегда помните про неразрывные пробелы и контролируйте разрядность результата.