В практике разработчика 1С часто возникают ситуации, когда данные поступают в виде строк, содержащих не только цифры, но и пояснительные знаки, такие как символ процента %, обозначения валют или единицы измерения. Для выполнения арифметических операций с такими данными нам необходимо преобразовать строку в чистый числовой тип. В рамках этой статьи мы подробно разберем, как эффективно отделить число от лишних символов в управляемых формах, проанализируем различные подходы и выберем наиболее надежные методы.
Если мы заранее точно знаем, какой именно символ мешает нам получить число (в нашем случае это знак процента), самым быстрым и простым способом будет использование встроенной функции СтрЗаменить. Рассмотрим ситуацию, когда строка гарантированно содержит число и знак % в конце.
Разберем пример кода:
&НаКлиенте
Функция ОчиститьСтрокуОтПроцента(ИсходнаяСтрока)
// Убираем знак процента, заменяя его на пустую строку
ОчищеннаяСтрока = СтрЗаменить(ИсходнаяСтрока, "%", "");
// Преобразуем результат в число
Попытка
Возврат Число(ОчищеннаяСтрока);
Исключение
Возврат 0; // Если в строке был не только процент, возвращаем 0
КонецПопытки;
КонецФункции
Важный нюанс: при работе с процентами стоит помнить, что в математическом смысле "10%" — это не просто число 10, а 0.1. Если ваша задача предполагает дальнейшие финансовые расчеты, логично будет сразу делить полученный результат на 100, чтобы получить корректный коэффициент.
Зачастую данные могут быть "загрязнены" не только одним знаком процента. В строке могут встретиться пробелы, неразрывные пробелы (код 160), кавычки или буквы. В таких случаях метод простой замены перестает быть эффективным. Рассмотрим более универсальный подход: мы проанализируем каждый символ строки и оставим только те, которые относятся к числам или разделителям дробной части.
Выполним это с помощью цикла:
&НаКлиентеНаСервереБезКонтекста
Функция ИзвлечьЧислоИзСтроки(Знач СтрокаСЧислом)
// Определим, является ли значение процентом для корректной математики
ЭтоПроцент = СтрЗаканчиваетсяНа(СтрокаСЧислом, "%");
РазрешенныеСимволы = "0123456789,.";
РезультатСтрокой = "";
// Пройдем по каждому символу строки по порядку
Для Счетчик = 1 По СтрДлина(СтрокаСЧислом) Цикл
ТекСимвол = Сред(СтрокаСЧислом, Счетчик, 1);
// Если символ входит в список разрешенных, добавляем его в новую строку
Если СтрНайти(РазрешенныеСимволы, ТекСимвол) > 0 Тогда
// Заменяем точку на запятую для корректной работы функции Число() в русской локализации
Если ТекСимвол = "." Тогда
ТекСимвол = ",";
КонецЕсли;
РезультатСтрокой = РезультатСтрокой + ТекСимвол;
КонецЕсли;
КонецЦикла;
// Проверяем, не пустая ли строка получилась после очистки
Если ПустаяСтрока(РезультатСтрокой) Тогда
Возврат 0;
КонецЕсли;
// Финальное преобразование
ЧисленноеЗначение = Число(РезультатСтрокой);
Если ЭтоПроцент Тогда
Возврат ЧисленноеЗначение / 100;
Иначе
Возврат ЧисленноеЗначение;
КонецЕсли;
КонецФункции
Проанализируем ситуацию: данный метод хорош тем, что он игнорирует любые текстовые приписки. Если в функцию придет строка "Скидка: 15.5%", она корректно извлечет 0.155.
Для наиболее сложных случаев, когда нам нужно отсечь всё лишнее максимально быстро, профессионалы используют объект VBScript.RegExp. Это мощный инструмент поиска и замены по шаблонам, который доступен в среде Windows (на стороне клиента или Windows-сервера).
Рассмотрим, как это реализовать:
&НаКлиенте
Функция ОчиститьСтрокуRegExp(Знач ВходнаяСтрока)
РегВыражение = Новый COMОбъект("VBScript.RegExp");
// Шаблон [^0-9,] означает: "всё, что НЕ является цифрой или запятой"
РегВыражение.Pattern = "[^0-9,]";
РегВыражение.Global = Истина;
// Заменяем всё неподходящее на пустую строку
Результат = РегВыражение.Replace(ВходнаяСтрока, "");
Попытка
Возврат Число(Результат);
Исключение
Возврат 0;
КонецПопытки;
КонецФункции
Этот метод работает значительно быстрее циклов на больших объемах данных, но требует осторожности при работе в кроссплатформенных средах (например, на серверах под управлением Linux этот объект не создастся).
Разберем основные подводные камни, с которыми сталкиваются разработчики при отделении чисел от символов:
Число() не понимает его и выдает ошибку. Перед обработкой всегда рекомендуется делать СтрЗаменить(Строка, Символ(160), "").Число(). Вызов этой функции от пустой строки приведет к аварийному завершению кода, если он не обернут в Попытка...Исключение.СтрРазделить с набором цифр в качестве разделителя. Это ошибочный путь, так как эта функция удалит сами цифры и оставит только "мусорные" символы, что прямо противоположно нашей задаче.Если задача стоит в том, чтобы пользователь вводил проценты в поле на форме, а в базе хранилось число, нам не обязательно писать функции парсинга. Разберем, как это настроить в свойствах элемента формы:
Выясним причину, почему это удобно: 1С умеет форматировать данные автоматически. Если у числового реквизита в свойстве Формат (или Формат редактирования) указать строку ЧЦ=10; ЧДЦ=2; ЧФ=0.00'%', то система сама будет рисовать знак процента в поле ввода. При этом в программном коде значение этого реквизита всегда будет чистым числом. Это избавляет от необходимости отделения символа от числа, так как символ существует только визуально для пользователя.
Подведем итог: для разовых задач по очистке данных из внешних источников лучше всего подходит универсальный цикл (Метод 2) или регулярные выражения (Метод 3). Для интерфейсных решений в управляемых формах оптимально использовать штатные свойства форматирования элементов формы.