Почему при преобразовании числа в строку в 1С хаотично пропадает или появляется разделитель групп и как это исправить?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При массовой загрузке данных (например, парсинге больших объемов данных из JSON или веб-сервисов) разработчики 1С нередко сталкиваются с ситуацией, когда стандартная функция Строка() или неявное приведение типов работают нестабильно. В одной и той же выборке числовые идентификаторы могут преобразовываться в текст по-разному: часть записей форматируется с разделителем групп разрядов (неразрывным пробелом Символы.НПП), а часть — сплошной строкой цифр. Разберем детально, почему это происходит и какими способами можно гарантировать требуемый формат строки.

Причины нестабильного форматирования чисел в платформе

Рассмотрим, из-за чего возникает плавающее поведение при преобразовании чисел в строковый тип:

  1. Зависимость функции Строка() от региональных установок: функция Строка() всегда использует текущие национальные настройки сеанса. По умолчанию для русской локали в качестве разделителя групп разрядов используется неразрывный пробел (код 160). Если разработчику требуется числовой идентификатор без пробелов, использование Строка() является архитектурной ошибкой.
  2. Сброс локали в многопоточных процессах на серверах Linux: при интенсивном разборе данных (например, через объект ЧтениеJSON) низкоуровневые системные библиотеки могут переключать системную переменную LC_NUMERIC в значение C для корректного чтения чисел с плавающей точкой. В некоторых релизах платформы этот сброс кратковременно затрагивает параллельные потоки одного рабочего процесса rphost, в результате чего числа форматируются без учета региональных разделителей.
  3. Неявные настройки переменных окружения сервера: если служба сервера 1С запущена без явного указания локали LANG и LC_ALL (например, ru_RU.UTF-8), рабочий процесс может произвольно переключаться на стандартную локаль POSIX.

Проанализируем практические решения для каждой из типовых задач: когда нужно получить строку строго без разделителей и когда строку требуется сформировать строго с неразрывными пробелами.

Решение 1: Получение строки без разделителей разрядов (для идентификаторов и артикулов)

Если числовое поле используется как строковый идентификатор, разделители тысяч в нем присутствовать не должны. Для надежного преобразования числа в плоскую строку цифр рассмотрим два проверенных инструмента.

Вариант А. Использование функции XMLСтрока():

Функция XMLСтрока() работает строго по каноническим правилам сериализации XML и схемы типов decimal. Она полностью игнорирует региональные настройки пользователя, операционной системы и сервера, всегда возвращая число без пробелов и с точкой в качестве десятичного разделителя.


// Гарантированное строковое представление без пробелов и разделителей тысяч
СтроковыйИдентификатор = XMLСтрока(ЧисловоеЗначение);

Вариант Б. Применение функции Формат() с отключением группировки:

Для явного отключения группировки разрядов в форматной строке используется параметр ЧГ=0 или ЧГ=. Чтобы исключить дробную часть у целых чисел, дополнительно задают параметр ЧДЦ=0.


// Явное отключение группировки и дробной части
СтроковыйИдентификатор = Формат(ЧисловоеЗначение, "ЧДЦ=0; ЧГ=0");

Решение 2: Гарантированное добавление разделителей тысяч (Символы.НПП)

Бывают обратные ситуации: сторонние закрытые модули конфигурации или строгие алгоритмы сверки ожидают, что число в строковом реквизите обязательно содержит неразрывный пробел Символы.НПП в качестве разделителя тысяч. В условиях сбоящей локали полагаться на Строка() нельзя. Рассмотрим варианты принудительного форматирования.

Вариант А. Явное указание локали в функции Формат():

Чтобы функция Формат() не зависела от системного сброса локали рабочего процесса, передадим код локали третьим параметром функции или пропишем его прямо в форматной строке через параметр Л=ru_RU:


// Принудительное задание русской локали и неразрывного пробела в разделителе групп
СтрокаСРазделителями = Формат(ЧисловоеЗначение, "ЧГ=3,0; ЧРГ=" + Символы.НПП, "ru_RU");

Вариант Б. Форматирование через обычный пробел с последующей заменой:

Если в конкретной версии платформы параметр ЧРГ ведет себя нестабильно при прямой передаче спецсимвола, применим надежный двухэтапный шаблон: отформатируем число с обычным символом пробела, а затем заменим его на Символы.НПП через функцию СтрЗаменить().


// Форматируем число с использованием стандартного пробела
ВременнаяСтрока = Формат(ЧисловоеЗначение, "ЧЦ=15; ЧДЦ=0; ЧГ=3,0; ЧРГ=' '");

// Заменяем обычный пробел на неразрывный пробел 1С
ИтоговаяСтрока = СтрЗаменить(ВременнаяСтрока, " ", Символы.НПП);

Вариант В. Автономный алгоритм вставки разделителей (без вызова Формат):

Когда требуется стопроцентная изоляция от любых платформенных и системных механизмов локализации, разберем алгоритмическую расстановку Символы.НПП с конца строки:


ИсходныйТекст = XMLСтрока(ЧисловоеЗначение);
Длина = СтрДлина(ИсходныйТекст);
ИтоговаяСтрока = "";

Счетчик = 0;
Для Позиция = Длина По 1 Цикл
    Символ = Сред(ИсходныйТекст, Позиция, 1);
    Если Счетчик > 0 И Счетчик % 3 = 0 Тогда
        ИтоговаяСтрока = Символы.НПП + ИтоговаяСтрока;
    КонецЕсли;
    ИтоговаяСтрока = Символ + ИтоговаяСтрока;
    Счетчик = Счетчик + 1;
КонецЦикла;

Решение 3: Проверка и настройка окружения на сервере Linux

Если сервер 1С функционирует под управлением ОС Linux, проверим корректность глобальных локалей операционной системы, в среде которых стартует служба ragent / rphost.

  1. Убедимся, что в операционной системе сгенерирована русскоязычная UTF-8 локаль: locale -a | grep ru_RU
  2. В скрипте инициализации службы сервера 1С или конфигурационном файле (в зависимости от дистрибутива — /etc/default/srv1cv83, /etc/sysconfig/srv1cv83 либо Unit-файле systemd) явно укажем экспорт переменных перед запуском бинарных файлов платформы:
    
    export LANG=ru_RU.UTF-8
    export LC_ALL=ru_RU.UTF-8
    
  3. Перезапустим службу сервера 1С:Предприятие для применения параметров окружения.

Таким образом, для безопасной работы с текстовыми полями в коде конфигураций следует избегать неявных преобразований типов и функции Строка(), заменяя их на XMLСтрока() (для точных данных без оформления) или Формат() с явным указанием локали и параметров группировки.

← На главную