В разработке на платформе 1С часто возникают задачи, связанные с преобразованием данных из одного типа в другой. Одна из таких стандартных операций — перевод числа в строку. Однако здесь могут поджидать неожиданности. Разберем ситуацию, когда при программном преобразовании числа в строку в качестве разделителя разрядов появляется обычный пробел (код 32), хотя ожидался неразрывный пробел (НПП, код 160). Это может привести к ошибкам, например, в модулях интеграции с внешними системами, где код явно ищет и заменяет именно символ НПП.
Проанализируем, почему так происходит и как правильно и надежно выполнять такие преобразования, чтобы код был предсказуемым и не зависел от окружения.
Основная причина такого "плавающего" поведения — это настройки, которые определяют, как именно платформа должна форматировать числа при их неявном преобразовании в строку. Платформа 1С не использует жестко заданный символ-разделитель; вместо этого она обращается к установленным параметрам. Эти параметры могут находиться на двух уровнях.
Это главный и приоритетный источник настроек форматирования для всей базы данных. Если они заданы, платформа будет использовать именно их. Проверить эти установки можно в режиме конфигуратора:
Администрирование -> Региональные установки ИБ
В открывшемся окне нас интересует поле "Разделитель групп". Именно в этом поле может быть указан как неразрывный пробел, так и обычный. Если там стоит обычный пробел, то все неявные преобразования, например, через функцию Строка() или простое присваивание числовой переменной строковой, будут использовать его.
Если в конфигураторе региональные установки ИБ не заданы (установлено значение "Использовать системные установки"), то 1С обратится к настройкам операционной системы, на которой выполняется код. Для клиент-серверного варианта это будут настройки сервера "1С:Предприятия", для файлового — настройки компьютера пользователя. Различия в этих настройках на тестовом и рабочем серверах часто и становятся причиной трудноуловимых ошибок, когда "на одной машине работает, а на другой — нет".
Таким образом, корень проблемы — в зависимости от внешних настроек. Код, который полагается на неявное преобразование, становится хрупким и непереносимым.
Чтобы сделать код надежным и независимым от любых настроек, следует использовать встроенную функцию Формат(). Это стандарт и лучшая практика для управляемого преобразования значений в строку в 1С. Она позволяет явно указать все параметры форматирования.
Как получить строку с числом без каких-либо разделителей?
В большинстве интеграционных задач (например, для формирования ключа или отправки данных в СБП) требуется "чистое" число в виде строки, без пробелов или других разделителей. Для этого используется специальный параметр форматирования "ЧГ=0" (Число без Группировки).
Посмотрим на пример. Вместо ненадежного кода:
// Ненадежный вариант, зависит от настроек
СуммаЧисло = 15000.50;
СуммаСтрока = Строка(СуммаЧисло); // Может вернуть "15 000,50" или "15 000,50"
СуммаСтрока = СтрЗаменить(СуммаСтрока, Символы.НПП, "");
Следует использовать такой:
// Надежный и предсказуемый вариант
СуммаЧисло = 15000.50;
СуммаСтрока = Формат(СуммаЧисло, "ЧГ=0"); // Всегда вернет "15000,50" (с запятой по умолчанию)
Функция Формат() имеет множество параметров, которые позволяют гибко управлять представлением числа: задавать точность, разделитель целой и дробной части, символ-заполнитель и многое другое. Использование этой функции — залог стабильности вашего кода.
Когда речь идет об обмене данными с другими системами, особенно если они используют форматы XML или JSON, существует еще один крайне надежный способ — функция XMLСтрока().
Эта функция преобразует любое значение 1С в его каноническое строковое представление согласно стандартам XML. Для чисел это означает:
..Этот метод гарантирует универсальный и предсказуемый результат, который не зависит ни от региональных установок ИБ, ни от настроек операционной системы.
// Идеально для интеграций
СуммаЧисло = 15000.50;
ДанныеДляОтправки = XMLСтрока(СуммаЧисло); // Всегда вернет "15000.50"
В обсуждении на форуме были приведены примеры подходов, которых стоит избегать. Рассмотрим их, чтобы закрепить правильные методы.
1. Полагаться на неявное преобразование и множественные `СтрЗаменить()`
Пытаться "угадать", какой разделитель может появиться в строке (пробел, НПП, или что-то еще), и заменять их все подряд — это плохой стиль. Такой код становится громоздким и все равно может пропустить какой-то редкий случай. Не надейтесь на неявное преобразование типов, когда важен точный формат строки.
2. Преобразовывать числа и форматировать строки в запросах
Запросы предназначены для эффективного извлечения данных из базы, а не для их форматирования. Попытки преобразовать число в строку прямо в тексте запроса, а затем манипулировать этой строкой, приводят к усложнению и замедлению кода. Это перекладывание логики представления данных на уровень СУБД, что является антипаттерном.
Пример кода, который никогда не следует использовать:
// КРАЙНЕ ПЛОХОЙ ПРИМЕР
ВЫБРАТЬ
СТРЗАМЕНИТЬ(СТРОКА(ГОД(РеализацияТоваровУслуг.Дата)), ВЫРАЗИТЬ(&СимволНПП КАК СТРОКА), "") КАК ГодБезНПП
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
Правильный подход — получить данные из запроса в их "сыром" виде (числа, даты) и форматировать их уже в коде 1С при обработке результата запроса с помощью функции Формат().
Подводя итог, можно сформулировать простое правило: если вам нужно преобразовать число в строку с определенным форматом, всегда используйте функцию Формат(). Это сделает ваш код чистым, надежным и независимым от внешних факторов.