Текст, дата, сумма с пробелами: превращаем любое значение в число во встроенном языке 1С 8.3

· 9 мин

Содержание

Строку в число в 1С 8.3 преобразуют функцией Число(): Сумма = Число("1250.75") вернёт 1250,75. Функция работает только с «чистой» строкой: цифры, минус и точка как десятичный разделитель. Запятая, пробел внутри числа или буквы приводят к исключению Преобразование значения к типу Число не может быть выполнено.

Поэтому на практике значение сначала чистят, а потом преобразуют — с проверкой или без исключений вовсе. Всё описанное относится к встроенному языку платформы и одинаково работает в любой конфигурации: Бухгалтерии, ЗУП, УТ, самописной базе.

Функция Число(): прямое преобразование значения в число

Число(Значение) — базовый способ привести значение к числовому типу. Что она принимает:

  • ✅ строку с цифрами: Число("42") → 42;
  • ✅ отрицательное и дробное: Число("-15.5") → −15,5;
  • ✅ строку с пробелами по краям: Число(" 300 ") → 300;
  • ✅ булево: Число(Истина) → 1, Число(Ложь) → 0;
  • ✅ число — вернёт его же, это безопасно.

Что вызывает исключение:

  • ❌ запятая как разделитель: Число("15,5");
  • ❌ пробел внутри: Число("1 250");
  • ❌ неразрывный пробел, который вставляет Формат(): Число("1 250,00");
  • ❌ буквы и символы валют: Число("100 руб."), Число("15%");
  • ❌ пустая строка — её проверяйте заранее через ПустаяСтрока().

Ведущие нули отбрасываются: Число("007") → 7. Для кодов, ИНН, номеров счетов и артикулов это потеря данных. Такие значения храните строкой и в число не переводите никогда.

Если значение уже пришло числом (например, из ячейки Excel через COM), Число() ничего не испортит. Проверить тип можно так: ТипЗнч(Значение) = Тип("Число").

Простейший пример с проверкой на пустоту:

Текст = СокрЛП(ПолеВвода);
Если ПустаяСтрока(Текст) Тогда
    Количество = 0;
Иначе
    Количество = Число(Текст);
КонецЕсли;

Этого достаточно, если источник надёжный — например, строка, которую вы сами собрали через XMLСтрока(). Для пользовательского ввода и внешних файлов нужен разбор строже.

Строгий разбор строки без исключений

Отдельной функции вроде «ЧислоСтр» во встроенном языке 8.3 нет. Строгий разбор собирают из трёх инструментов: ОписаниеТипов.ПривестиЗначение(), XMLЗначение() и собственной проверки символов.

ПривестиЗначение: мягкое приведение

ТипЧисло = Новый ОписаниеТипов("Число");
Результат = ТипЧисло.ПривестиЗначение("abc"); // 0, без исключения
Результат = ТипЧисло.ПривестиЗначение("12.5"); // 12.5

Метод не падает, но и не различает «в строке был ноль» и «в строке был мусор». В обоих случаях вы получите 0. Для отчёта это терпимо, для загрузки остатков — нет: товар молча обнулится.

С квалификатором можно сразу ограничить разрядность:

ТипСумма = Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(15, 2));
Сумма = ТипСумма.ПривестиЗначение(Значение);

XMLЗначение: формат «как в файле обмена»

XMLЗначение(Тип("Число"), "1250.75") разбирает строку по правилам XML: точка как разделитель, никаких пробелов-разделителей групп. На неверной строке бросает исключение. Удобно для данных из XML, JSON и выгрузок других систем, где числа записаны машинно.

Своя функция проверки

Когда нужно точно знать, число ли перед вами, проверяйте символы сами:

Функция ЭтоКорректноеЧисло(Знач Текст) Экспорт
    Текст = СокрЛП(Текст);
    Если Лев(Текст, 1) = "-" Тогда
        Текст = Сред(Текст, 2);
    КонецЕсли;
    Если ПустаяСтрока(Текст) Или Лев(Текст, 1) = "." Или Прав(Текст, 1) = "." Тогда
        Возврат Ложь;
    КонецЕсли;
    БылаТочка = Ложь;
    Для Позиция = 1 По СтрДлина(Текст) Цикл
        Символ = Сред(Текст, Позиция, 1);
        Если Символ = "." Тогда
            Если БылаТочка Тогда
                Возврат Ложь;
            КонецЕсли;
            БылаТочка = Истина;
        ИначеЕсли СтрНайти("0123456789", Символ) = 0 Тогда
            Возврат Ложь;
        КонецЕсли;
    КонецЦикла;
    Возврат Истина;
КонецФункции

Функция принимает -15.5, 300, 0.25 и отвергает 1.2.3, .5, 12a, пустую строку. После Истина вызов Число() уже безопасен.

В конфигурациях на БСП есть готовые помощники в модуле СтроковыеФункцииКлиентСервер, например ТолькоЦифрыВСтроке(). Перед использованием откройте модуль в конфигураторе и посмотрите состав функций вашей редакции БСП.

Обработка ошибок при преобразовании в число

Если строку заранее не проверили, оборачивайте Число() в Попытка:

Попытка
    Цена = Число(Текст);
Исключение
    Цена = 0;
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Текст = СтрШаблон("Строка %1: не удалось прочитать цену «%2»", НомерСтроки, Текст);
    Сообщение.Сообщить();
КонецПопытки;

Три правила, которые экономят время при разборе логов:

  1. Пишите в сообщение исходный текст и номер строки. Фраза «ошибка преобразования» без контекста бесполезна.
  2. Не глушите исключение пустым блоком Исключение КонецПопытки. Ошибка исчезнет, а ноль останется в документе.
  3. Для полного текста системной ошибки используйте ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()) — он нужен в журнале регистрации, а не пользователю.

Исключение — дорогая операция. Если загружаете файл на десятки тысяч строк, где мусор встречается часто, сначала проверяйте строку функцией вроде ЭтоКорректноеЧисло(), а Попытка оставьте страховкой.

Диагностика: выберите симптом

Разделители и пробелы: почему число из Формат() не читается обратно

Главный источник ошибок — локализация. Формат(1250.5, "ЧДЦ=2") в русской локали вернёт 1 250,50. Здесь два «сюрприза»:

  • 🔸 разделитель групп — неразрывный пробел, а не обычный;
  • 🔸 десятичный разделитель — запятая.

Число() не принимает ни то, ни другое. Обычная замена СтрЗаменить(Текст, " ", "") неразрывный пробел не тронет, и ошибка останется. Убирать нужно оба вида пробелов:

Функция СтрокаВЧисло(Знач Текст, ЗначениеПоУмолчанию = 0) Экспорт
    Текст = СокрЛП(Текст);
    Текст = СтрЗаменить(Текст, Символы.НПП, "");
    Текст = СтрЗаменить(Текст, " ", "");
    Текст = СтрЗаменить(Текст, ",", ".");
    Если ПустаяСтрока(Текст) Тогда
        Возврат ЗначениеПоУмолчанию;
    КонецЕсли;
    Попытка
        Возврат Число(Текст);
    Исключение
        Возврат ЗначениеПоУмолчанию;
    КонецПопытки;
КонецФункции

Функция переварит 1 250,50, 1 250.50, -300. А вот европейский формат 1.250,50 (точка — тысячи, запятая — дробь) после замены превратится в 1.250.50 и уйдёт в значение по умолчанию. Если такие файлы бывают, сначала удалите точки, потом замените запятую.

Неоднозначный случай — строка 1.250 или 1,250. Это может быть и «одна целая двести пятьдесят тысячных», и «тысяча двести пятьдесят». Угадывать нельзя: договоритесь о формате с источником данных или вынесите выбор разделителя в настройку загрузки.

Как получить строку, которую 1С прочтёт обратно

Если число нужно сохранить в текст и потом восстановить, не используйте «красивый» Формат() без параметров:

ЗадачаВыражениеРезультат для 1250.5
Машинная строкаXMLСтрока(1250.5)1250.5
Без разделителя группФормат(1250.5, "ЧГ=0")1250,5
Точка вместо запятойФормат(1250.5, "ЧРД=.; ЧГ=0")1250.5
Ноль не пропадаетФормат(0, "ЧН=0; ЧГ=0")0

Формат(0) возвращает пустую строку, а не «0». При обратном чтении такая пустота упадёт в Число() или превратится в значение по умолчанию. Параметр ЧН=0 задаёт, что выводить для нуля.

Даты и денежные суммы: как перевести их в число

Суммы с валютой, процентами и скобками

Выгрузки из банков и таблиц часто содержат 12 500,00 руб., 15% или бухгалтерскую запись отрицательного числа в скобках (3 400,00). Их очищают перед преобразованием:

Функция СуммаИзТекста(Знач Текст) Экспорт
    Текст = НРег(СокрЛП(Текст));
    Отрицательная = СтрНачинаетсяС(Текст, "(") И СтрЗаканчиваетсяНа(Текст, ")");
    Для Каждого Лишнее Из СтрРазделить("руб.|руб|₽|$|€|%|(|)", "|") Цикл
        Текст = СтрЗаменить(Текст, Лишнее, "");
    КонецЦикла;
    Сумма = СтрокаВЧисло(Текст);
    Возврат ?(Отрицательная, -Сумма, Сумма);
КонецФункции

Порядок в списке важен: сначала руб., потом руб. Иначе после удаления руб останется висящая точка. Для процентов решите заранее, что хранить: 15 или 0.15. Если долю — разделите результат на 100.

Функции СтрНачинаетсяС, СтрЗаканчиваетсяНа, СтрНайти и СтрРазделить появились в платформе 8.3.6. В базе с режимом совместимости ниже этой версии используйте Лев, Прав и Найти.

Дата как число

Явного Число(Дата) нет, зато разность двух дат в 1С — это количество секунд:

Секунд = ДатаКонца - ДатаНачала;               // интервал в секундах
Дней = Цел((КонецДня(ДатаКонца) - НачалоДня(ДатаНачала) + 1) / 86400);
ЮниксВремя = ТекущаяДатаСеанса() - Дата(1970, 1, 1);
КлючДаты = Число(Формат(ДатаДокумента, "ДФ=yyyyMMdd")); // 20261007

Пересчитаем пример с днями: с 01.10 по 07.10 включительно — от начала 1 октября до конца 7 октября проходит 7 × 86 400 − 1 секунда. Плюс 1 даёт ровно 604 800, делим на 86 400 — получаем 7 дней.

Части даты уже числа: Год(), Месяц(), День(), Час() возвращают числовой тип, преобразовывать их не нужно.

Обратная операция для Unix-времени: Дата(1970, 1, 1) + ЮниксВремя. Учтите, что Unix-время принято считать в UTC, а ТекущаяДатаСеанса() возвращает дату в часовом поясе сеанса. Для обмена с внешними сервисами берите ТекущаяУниверсальнаяДата().

Строку с датой 07.10.2026 в число не переводят целиком. Её разбирают на части и собирают дату:

Части = СтрРазделить("07.10.2026", ".");
ДатаДок = Дата(Число(Части[2]), Число(Части[1]), Число(Части[0]));

Индексы здесь от нуля: Части[0] — день, Части[1] — месяц, Части[2] — год.

Практические сценарии: CSV, табличный документ, запрос

Загрузка из CSV

Строку файла делят по разделителю и прогоняют каждое числовое поле через проверку:

Поля = СтрРазделить(СтрокаФайла, ";");
Если ЭтоКорректноеЧисло(СтрЗаменить(Поля[2], ",", ".")) Тогда
    Количество = Число(СтрЗаменить(Поля[2], ",", "."));
Иначе
    // записать номер строки и значение в протокол загрузки
КонецЕсли;

Если в CSV разделитель полей — запятая, а дробная часть тоже через запятую, файл неоднозначен. Попросите выгрузку с ; или с числами в кавычках.

Чтение из табличного документа

Текст ячейки табличного документа — всегда строка, даже если в Excel там было число. Поэтому после ТабличныйДокумент.Прочитать() значения из Область.Текст проходят через СтрокаВЧисло() из раздела про разделители. Excel при сохранении может подставить разделители групп и знак валюты из формата ячейки.

Язык запросов

В языке запросов 1С привести строку к числу через ВЫРАЗИТЬ нельзя. Строковые реквизиты выбирайте как есть и преобразуйте в коде после выборки. Если сравнение «как чисел» нужно прямо в запросе, это повод хранить реквизит числовым типом.

Частые ошибки при приведении значения к числу

  • 🔹 Сравнение строк вместо чисел. "10" < "9" даёт Истина: строки сравниваются посимвольно. Сначала приведите к числу, потом сравнивайте и сортируйте.
  • 🔹 Склейка строки с числом. "Итого: " + Сумма выведет число по формату локали с пробелами. Для читаемого текста используйте Формат(Сумма, "ЧДЦ=2"), для файлов — XMLСтрока().
  • 🔹 Потеря копеек при записи. Реквизит с длиной 15, 0 не сохранит копейки: 1250,75 запишется целым числом. Проверяйте квалификатор числа у реквизита, а не только код преобразования.
  • 🔹 Округление вместо отсечения. Окр(2.5) даёт 3, Цел(2.5) даёт 2. Для количества штук и для денег это разные функции.
  • 🔹 Неопределено и NULL из запроса. Поле из левого соединения может прийти как NULL. Перед арифметикой используйте ЕСТЬNULL(Поле, 0) в самом запросе.

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

Работает ли Число() одинаково на клиенте и на сервере?
Да. Функция глобального контекста доступна везде и не зависит от региональных настроек Windows: десятичный разделитель для неё всегда точка.
Как проверить, что строка состоит только из цифр?
Пройдите по символам и проверьте каждый через СтрНайти(“0123456789”, Символ). В конфигурациях на БСП можно сравнить строку с результатом СтроковыеФункцииКлиентСервер.ТолькоЦифрыВСтроке().
Почему ПривестиЗначение не сообщает об ошибке?
Так задумано: метод приводит значение к типу или возвращает значение по умолчанию для типа, для числа это 0. Если важно отличать мусор от нуля, проверяйте строку заранее.
Можно ли преобразовать в число значение перечисления или ссылку?
Нет, к числу приводятся строки, числа и булево. Для перечисления берут индекс: Перечисления.Имя.Индекс(Значение). Для ссылки используют числовой реквизит объекта, если он есть.
Сколько знаков после запятой сохранит Число()?
Столько, сколько в строке. Ограничение появляется при записи в реквизит или переменную с описанием типов: лишние знаки округлятся по квалификатору.