При интеграции 1С с внешними системами, такими как веб-сайты, Excel-файлы или сторонние API, программисты часто сталкиваются с проблемой «грязных» данных. Например, числовое значение может приходить в виде строки "1,978.23.". Для системы 1С такая строка не является валидным числом из-за лишней запятой (разделителя триад) и случайной точки в конце строки. В этой статье мы подробно разберем, как очистить подобные строки и корректно преобразовать их в числовой тип данных.
Рассмотрим самый простой и очевидный подход, который обсуждался на форуме. Суть метода заключается в последовательной очистке строки: сначала мы удаляем лишние знаки с конца, а затем избавляемся от ненужных разделителей внутри текста. Проанализируем пример кода:
// Допустим, входная строка: "1,978.23."
СтрокаСЧислом = "1,978.23.";
// 1. Убираем последний символ (точку)
ОчищеннаяСтрока = Лев(СтрокаСЧислом, СтрДлина(СтрокаСЧислом) - 1);
// 2. Удаляем запятые (разделители групп разрядов)
ОчищеннаяСтрока = СтрЗаменить(ОчищеннаяСтрока, ",", "");
// 3. Преобразуем результат в число
ИтоговоеЧисло = Число(ОчищеннаяСтрока);
Этот метод хорошо работает, если формат входящих данных строго фиксирован. Функция Лев с параметром СтрДлина - 1 эффективно отсекает последний символ, а СтрЗаменить полностью вычищает все вхождения запятой. Однако стоит помнить, что если точки в конце строки не окажется, данный код удалит значащую цифру. Поэтому перед использованием Лев рекомендуется добавить проверку на наличие точки в конце строки.
Существует более «продвинутый» способ, который минимизирует риск возникновения ошибок при преобразовании. Рассмотрим вариант с использованием объекта ОписаниеТипов. Этот метод позволяет системе более гибко обрабатывать входящие данные и приводить их к нужному типу.
ВхСтрока = "1,978.23.";
// Создаем описание типа "Число"
ТипЧисло = Новый ОписаниеТипов("Число");
// Комбинированный метод очистки через разделение и соединение
// Убираем запятые, делим по точкам и собираем обратно, чтобы убрать лишние вкрапления
ЧастиСтроки = СтрРазделить(СтрЗаменить(ВхСтрока, ",", ""), ".", Ложь);
// Собираем обратно только значащие части (целую и дробную)
// В данном случае мы берем все части, кроме последней, если она пустая
РезультатСтрокой = СтрСоединить(ЧастиСтроки, ".");
// Приводим к числу
Результат = ТипЧисло.ПривестиЗначение(РезультатСтрокой);
Этот подход полезен тем, что ОписаниеТипов при методе ПривестиЗначение не вызывает аварийного завершения программы (исключения), если строка окажется совсем некорректной, а просто вернет значение по умолчанию (0).
Разберем ситуацию, когда данные копируются из веб-интерфейсов или Excel. В таких строках часто присутствуют так называемые «неразрывные пробелы» (символ с кодом 160). Обычная функция СтрЗаменить(Строка, " ", "") их «не видит», из-за чего функция Число() выдает ошибку. Выясним, как с этим бороться.
Для гарантированной очистки необходимо использовать системную константу Символы.НПП (неразрывный пробел). Посмотрим на пример кода, который делает обработку универсальной:
СтрокаДляОбработки = "1 978.23"; // Здесь может быть неразрывный пробел
// Очищаем от обычных пробелов и от неразрывных пробелов
ЧистаяСтрока = СтрЗаменить(СтрокаДляОбработки, " ", "");
ЧистаяСтрока = СтрЗаменить(ЧистаяСтрока, Символы.НПП, "");
// Теперь преобразование пройдет успешно
Результат = Число(ЧистаяСтрока);
Если формат входящих строк крайне нестабилен (могут быть буквы, разные знаки препинания, случайные символы), проанализируем использование регулярных выражений (RegExp). Это наиболее мощный инструмент для работы со строками в 1С через COM-объекты Windows.
Суть метода: мы создаем шаблон, который оставляет в строке только цифры и десятичную точку, а всё остальное удаляет. Это избавляет нас от необходимости вручную прописывать СтрЗаменить для каждого возможного символа.
// Создаем объект для работы с регулярными выражениями
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.IgnoreCase = Истина;
RegExp.Global = Истина;
RegExp.MultiLine = Истина;
// Шаблон [^0-9.] означает: найти всё, что НЕ является цифрой или точкой
RegExp.Pattern = "[^0-9.]";
ВходнаяСтрока = "Цена: 1,978.23 руб.";
// Заменяем все найденные "плохие" символы на пустую строку
ТолькоЧислоСтрокой = RegExp.Replace(ВходнаяСтрока, "");
// Если в конце осталась точка (как в нашем примере 1978.23.), ее нужно убрать
Если Прав(ТолькоЧислоСтрокой, 1) = "." Тогда
ТолькоЧислоСтрокой = Лев(ТолькоЧислоСтрокой, СтрДлина(ТолькоЧислоСтрокой) - 1);
КонецЕсли;
ИтоговоеЧисло = Число(ТолькоЧислоСтрокой);
Важно помнить, что функция Число() в 1С сильно зависит от региональных настроек операционной системы. Если на сервере или компьютере пользователя в качестве разделителя дробной части установлена запятая, то попытка преобразовать строку "1978.23" (с точкой) приведет к ошибке.
Рассмотрим, как написать отказоустойчивый код, используя конструкцию Попытка...Исключение:
Попытка.
СтрокаЗначение = "1,978.23.";
// 1. Предварительная очистка
СтрокаЗначение = СтрЗаменить(СтрокаЗначение, ",", "");
Если Прав(СтрокаЗначение, 1) = "." Тогда
СтрокаЗначение = Лев(СтрокаЗначение, СтрДлина(СтрокаЗначение) - 1);
КонецЕсли;
// 2. Попытка преобразования
Попытка
Результат = Число(СтрокаЗначение);
Исключение
// Если возникла ошибка (например, из-за настроек разделителя точка/запятая)
// Попробуем заменить точку на запятую
Попытка
Результат = Число(СтрЗаменить(СтрокаЗначение, ".", ","));
Исключение
Результат = 0; // Если ничего не помогло
Сообщить("Не удалось преобразовать значение: " + СтрокаЗначение);
КонецПопытки;
КонецПопытки;
Если ваша конфигурация разработана на базе БСП (Библиотеки стандартных подсистем), рекомендуем заглянуть в общий модуль СтроковыеФункцииКлиентСервер. Там часто уже реализованы функции типа ТолькоЦифрыВСтроке или специализированные парсеры чисел, которые учитывают все вышеописанные нюансы с пробелами и разделителями.
Подведем итог: для решения задачи по очистке строки "1,978.23." эффективнее всего комбинировать удаление запятых через СтрЗаменить и проверку последнего символа. Для более сложных случаев всегда используйте регулярные выражения и не забывайте про неразрывные пробелы, которые часто становятся причиной трудноуловимых ошибок.