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