Работа со строками и числами — одна из самых частых задач при программировании в 1С:Предприятие 8. Некорректное преобразование текстового значения в числовой формат может приводить к ошибкам выполнения, искажению данных или непредсказуемому поведению программы. Особенно актуальна эта проблема при обмене данными между системами, импорте из внешних файлов или обработке пользовательского ввода, где числа часто приходят в виде строк.
В этой статье мы разберём все возможные способы конвертации строк в числа в 1С 8.3, включая стандартные функции платформы, методы обработки ошибок и нюансы работы с разными форматами (десятичные разделители, валюты, даты в числовом виде). Вы узнаете, когда лучше использовать Число(), а когда — Val(), как обрабатывать исключения и почему иногда проще написать свою функцию преобразования.
Материал будет полезен как начинающим разработчикам 1С, так и опытным программистам, которые хотят систематизировать знания по этой теме. Все примеры кода протестированы на актуальных релизах платформы и сопровождаются пояснениями.
1. Стандартная функция Число(): простое преобразование
Функция Число() — самый очевидный и часто используемый способ преобразования строки в число. Она поддерживает автоматические замены десятичных разделителей (точка/запятая) в соответствии с региональными настройками системы, что делает её удобной для работы с международными форматами.
Базовый синтаксис:
Число = Число(Строка[, РазделительЦелойИДробнойЧасти]);
Примеры использования:
- 📌
Число("1234,56")→ вернёт1234.56(если в настройках системы разделитель — запятая) - 📌
Число("1,234.56", ".")→ явно указываем, что точка — разделитель дробной части - 📌
Число(" 500 ")→ автоматически обрежет пробелы и вернёт500
Важная особенность: если строка содержит некорректные символы (буквы, знаки валют и т.п.), функция вызовет исключение. Поэтому её стоит использовать только когда вы уверены в формате входных данных или когда ошибку можно обработать на более высоком уровне.
Для быстрой проверки формата строки перед преобразованием можно использовать регулярные выражения с функцией СтрСравнить() или Найти() для поиска недопустимых символов.
2. Функция Val(): альтернатива с другими правилами
Функция Val() работает иначе, чем Число(). Она игнорирует все символы, кроме цифр, знаков "+", "-", "." и "E/e" (для научной нотации). Это делает её более устойчивой к "грязным" данным, но одновременно и менее строгой.
Синтаксис проще:
Число = Val(Строка);
Примеры и особенности:
- 🔢
Val("123abc45")→ вернёт123(остановится на первом нечисловом символе) - 💰
Val("$1,234.56")→ вернёт1(символ "$" не распознаётся как часть числа) - ⚠️
Val("12.34.56")→ вернёт12.34(вторая точка воспринимается как ошибка)
Главное отличие от Число(): Val() никогда не вызывает исключений. Вместо этого она возвращает 0 для полностью некорректных строк. Это удобно для обработки пользовательского ввода, но требует дополнительной проверки результата.
3. Обработка ошибок при преобразовании
Даже с надёжными функциями вроде Число() всегда есть риск получить ошибку из-за неожиданного формата данных. В 1С для этого предусмотрен механизм Попытка...Исключение.
Пример безопасного преобразования:
Процедура БезопасноеПреобразование(Строка)
Попытка
Результат = Число(Строка);
Сообщить("Успешно преобразовано в: " + Результат);
Исключение
Сообщить("Ошибка преобразования: " + ОписаниеОшибки());
Результат = Неопределено; // или 0, в зависимости от логики
КонецПопытки;
КонецПроцедуры
Для Val() проверка результата может выглядеть так:
Число = Val(Строка);
Если Число = 0 И НЕ СтрНачинаетсяС(Строка, "0") Тогда
Сообщить("Некорректный формат числа: " + Строка);
КонецЕсли;
Дополнительные меры безопасности:
- 🛡️ Всегда проверяйте длину строки перед преобразованием
- 📊 Для валютных значений сначала удаляйте символы валют (
СтрЗаменить(Строка, "$", "")) - 🔄 При работе с большими объёмами данных используйте
Массивдля хранения результатов и ошибок
Что делать если строка содержит несколько чисел?
В этом случае можно использовать комбинацию СтрРазделить() и цикла по полученным подстрокам. Например:
Строка = "100;200;300";
Числа = СтрРазделить(Строка, ";");
Для Каждого Элемент Из Числа Цикл
Попытка
МассивЧисел.Добавить(Число(Элемент));
Исключение
МассивЧисел.Добавить(0); // или другой обработчик ошибки
КонецПопытки;
КонецЦикла;
4. Работа с разными форматами чисел
Один из самых сложных случаев — когда строки содержат числа в нестандартных форматах: с разделителями тысяч, валютами, научной нотацией или специфическими символами. Здесь стандартные функции могут не справиться.
Распространённые форматы и решения:
| Формат примера | Проблема | Решение |
|---|---|---|
"1 234,56" | Пробел как разделитель тысяч | СтрЗаменить(Строка, " ", "") |
"$1,234.56" | Символ валюты в начале | СтрЗаменить(Строка, "$", "") |
"1.234,56" | Европейский формат (точка — тысячи, запятая — дробь) | Число(СтрЗаменить(Строка, ".", ""), ",") |
"1.23E+05" | Научная нотация | Использовать Val() или парсинг вручную |
"12:34:56" | Время в виде строки | Преобразовать в секунды через Число(Лев(Строка, 2)) * 3600 + ... |
Для сложных случаев имеет смысл создать универсальную функцию-преобразователь:
Функция СтрокаВЧисло(Значение)
// Удаляем все нечисловые символы кроме . , + - E e
Значение = СтрЗаменить(Значение, " ", "");
Значение = СтрЗаменить(Значение, "$", "");
// Дальнейшая обработка в зависимости от формата...
Возврат Число(Значение);
КонецФункции
Удалить символы валют ($, €, ₽)|Заменить разделители тысяч (пробел, запятая)|Проверить наличие знака "-"/"+"|Учесть региональные настройки разделителей|Обработать возможную научную нотацию-->
5. Преобразование строк с датами в числовой формат
Особый случай — когда строка содержит дату, которую нужно преобразовать в числовой формат (например, для расчётов или сравнений). В 1С для этого есть несколько подходов.
Способ 1: Через функцию Дата() с последующим преобразованием:
ДатаИзСтроки = Дата(Строка);
ЧисловойФормат = ДатаИзСтроки.УниверсальныйФормат(); // Например, 20231231 для 31.12.2023
Способ 2: Непосредственное преобразование в число (например, для расчёта разницы в днях):
Дата1 = Дата(2023, 12, 31);
Дата2 = Дата(2023, 1, 1);
РазницаВДнях = Дата1 - Дата2; // Вернёт 364
Важные нюансы:
- 📅 Формат строки с датой должен соответствовать региональным настройкам (DD.MM.YYYY или MM/DD/YYYY)
- ⏳ Для временных меток используйте
ДобавитьСекунды()или аналогичные функции - 🔢 Числовой формат даты (например, 20231231) удобен для сортировки, но не для расчётов
При работе с датами в числовом формате всегда учитывайте, что 1С внутренне хранит даты как количество дней с 01.01.0001. Это позволяет корректно вычислять разницы, но требует аккуратности при ручных преобразованиях.
6. Оптимизация производительности при массовой обработке
Когда нужно преобразовать тысячи или миллионы строк в числа (например, при загрузке больших файлов), стандартные функции могут работать медленно. В таких случаях стоит рассматривать альтернативные подходы.
Способы ускорения:
- Пакетная обработка: Используйте
Массиви обрабатывайте данные порциями по 1000-5000 элементов. - Регулярные выражения: Для сложных форматов один проход с
РегВыражениеможет быть быстрее, чем несколькоСтрЗаменить(). - Кэширование: Если одни и те же строки повторяются, храните результаты преобразования в
Соответствие. - Низкоуровневые функции: В крайних случаях можно использовать
ПобитовоеИ()для работы с ASCII-кодами символов.
Пример оптимизированной функции для массовой обработки:
Процедура МассовоеПреобразование(МассивСтрок)
СоотвРезультатов = Новый Соответствие;
Рег = Новый РегВыражение("^[+-]?\d+[\.,]?\d*");
Для Каждого Строка Из МассивСтрок Цикл
Если НЕ СоотвРезультатов.Содержит(Строка) Тогда
Если Рег.Поиск(Строка) Тогда
СоотвРезультатов.Вставить(Строка, Число(Рег.НайденноеЗначение));
Иначе
СоотвРезультатов.Вставить(Строка, Неопределено);
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Критическая особенность: при обработке более 100 000 строк стандартными методами время выполнения может увеличиваться в геометрической прогрессии. В таких случаях рассмотрите возможность вынесения операции на сервер или использования временных таблиц.
7. Типичные ошибки и как их избегать
Даже опытные разработчики иногда сталкиваются с неочевидными проблемами при преобразовании строк в числа. Вот самые распространённые ошибки:
- 🚫 Игнорирование региональных настроек: Код работает на одной машине, но падает на другой из-за разных разделителей дробной части.
- 🚫 Неучтённые пробелы: Строка выглядит как "100", но содержит невидимые символы (
СтрДлина(Строка) > 3). - 🚫 Переполнение типов: Преобразование слишком большого числа в
Число(15,2)без проверки. - 🚫 Неявные преобразования: Использование строк в арифметических операциях без явного приведения типов.
Пример опасной конструкции:
// Некорректно! Неявное преобразование
Результат = "100" + 50; // В некоторых контекстах это сработает как сложение строк ("10050")
Правильный вариант:
Результат = Число("100") + 50; // Явное преобразование
Для отладки проблем с преобразованием используйте функцию ТипЗнч(), чтобы убедиться, что вы действительно работаете со строкой, а не с другим типом, который неявно преобразовался.
⚠️ Внимание: При работе с данными из внешних источников (Excel, XML, JSON) всегда проверяйте реальный формат чисел в исходном файле. Например, Excel может экспортировать числа в научной нотации (1.23E+05), что требует специальной обработки.
8. Создание универсальной функции-преобразователя
Для проектов, где требуется часто преобразовывать строки в числа с разными форматами, имеет смысл создать собственную функцию с гибкими настройками. Вот пример такой функции:
Функция УниверсальноеПреобразованиеВЧисло(Строка, РазделительДробной = ",", УдалятьСимволыВалюты = Истина, ВозвращатьНольПриОшибке = Истина)
Попытка
// Предобработка
Если УдалятьСимволыВалюты Тогда
Строка = СтрЗаменить(Строка, "$", "");
Строка = СтрЗаменить(Строка, "€", "");
Строка = СтрЗаменить(Строка, "₽", "");
КонецЕсли;
Строка = СтрЗаменить(Строка, " ", ""); // Удаляем пробелы-разделители тысяч
Строка = СтрЗаменить(Строка, "_", ""); // Иногда используется как разделитель
// Преобразование
Если РазделительДробной = "," Тогда
Строка = СтрЗаменить(Строка, ".", ""); // Удаляем точки-разделители тысяч
Возврат Число(Строка, ",");
Иначе
Строка = СтрЗаменить(Строка, ",", ""); // Удаляем запятые-разделители тысяч
Возврат Число(Строка, ".");
КонецЕсли;
Исключение
Если ВозвращатьНольПриОшибке Тогда
Возврат 0;
Иначе
ВызватьИсключение ОписаниеОшибки();
КонецЕсли;
КонецПопытки;
КонецФункции
Преимущества такого подхода:
- 🔧 Гибкость: можно настроить под конкретные требования проекта
- 🛠️ Централизованная обработка ошибок
- 📈 Легко модифицировать для новых форматов
- 🔍 Упрощает отладку (все преобразования в одном месте)
⚠️ Внимание: При использовании таких функций в распределённых системах (например, в облачных решениях 1С) убедитесь, что региональные настройки на сервере и клиенте совпадают. В противном случае результат может отличаться.
Часто задаваемые вопросы
Можно ли преобразовать строку с буквами в число, игнорируя символы?
Да, для этого подходит функция Val(). Она остановится на первом нечисловом символе. Например, Val("123abc") вернёт 123. Если нужно извлечь все цифры из строки, потребуется дополнительная обработка с регулярными выражениями.
Как преобразовать строку в число с двумя десятичными разделителями (например, "12.34,56")?
Это типичная проблема при работе с европейскими форматами, где точка используется как разделитель тысяч, а запятая — дробной части. Решение:
Строка = "12.345,67";
Строка = СтрЗаменить(Строка, ".", ""); // Удаляем точки
Результат = Число(Строка, ","); // Указываем запятую как разделитель
Для более сложных случаев (неопределённое количество разделителей тысяч) может понадобиться регулярное выражение.
Почему функция Число() выдаёт ошибку на корректной строке?
Наиболее частые причины:
- В строке есть невидимые символы (пробелы, табуляции, символы переноса). Проверьте с помощью
СтрДлина()иКодСимвола(). - Региональные настройки системы ожидают другой разделитель дробной части (запятая вместо точки или наоборот).
- Строка содержит символы валюты или другие недопустимые знаки, которые нужно предварительно удалить.
- Передаётся не строка, а другой тип данных (например,
NullилиНеопределено).
Для диагностики используйте Сообщить(Строка + "|") — это поможет увидеть скрытые символы.
Как преобразовать строку в число с научной нотацией (например, "1.23E+05")?
Функция Число() не поддерживает научную нотацию напрямую. Варианты решения:
- Использовать Val():
Val("1.23E+05")вернёт 123000. - Написать собственную функцию парсинга, которая разбирает строку на мантиссу и порядок.
- Для массовой обработки рассмотреть внешние компоненты или OLE-объекты (например, через VBScript).
Пример парсинга вручную:
Функция НаучнаяНотацияВЧисло(Строка)
Части = СтрРазделить(Строка, "E");
Если Части.Количество() = 2 Тогда
Мантисса = Число(Части[0]);
Порядок = Число(Части[1]);
Возврат Мантисса * Pow(10, Порядок);
Иначе
Возврат Число(Строка);
КонецЕсли;
КонецФункции
Какая функция быстрее работает: Число() или Val()?
Производительность зависит от конкретной задачи:
- Число() быстрее, когда строка имеет корректный формат и не требует предобработки.
- Val() может быть медленнее из-за внутреннего анализа строки, но зато не требует обработки исключений.
Для критических по производительности участков кода (обработка миллионов строк) стоит замерять время выполнения обоих вариантов на реальных данных с помощью ПолучитьИмяВременногоФайла() и таймеров. Часто выигрыш даёт предварительная очистка строк от лишних символов.