Как убрать неразрывный пробел в числах при выгрузке данных в CSV в 1С?

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

В процессе работы с платформой 1С:Предприятие часто возникает задача выгрузки различных данных в формат CSV (Comma Separated Values). Этот формат является универсальным и широко используется для обмена информацией между разными системами благодаря своей простоте и текстовому представлению. Однако, пользователи регулярно сталкиваются с проблемой, когда числовые данные, которые ожидаются в формате "1000", отображаются в результирующем CSV-файле как "1 000" или "1 000". Причиной такого отображения являются неразрывные пробелы, которые 1С использует по умолчанию для повышения читаемости больших числовых значений, особенно в соответствии с региональными стандартами (например, для русского языка). При последующем импорте такого файла в другие программы, эти "числа" могут быть восприняты как текст, или некорректно обработаны, что неизбежно приводит к ошибкам и потере данных.

Мы рассмотрим, как можно эффективно решить эту проблему, обеспечив корректное форматирование числовых значений непосредственно перед их записью в CSV-файл. Наша цель – минимизировать необходимость в трудоемкой постобработке файла и гарантировать чистоту данных.

Понимание природы неразрывных пробелов в числах 1С

Прежде чем приступить к непосредственному решению, давайте проанализируем, почему вообще появляются неразрывные пробелы. В системе 1С:Предприятие, как и во многих других информационных системах, для строкового представления числовых значений используются настройки локализации и форматирования. Для русскоязычной локали по умолчанию часто устанавливается разделитель групп разрядов в виде неразрывного пробела (специальный символ Символы.НПП), что соответствует принятым стандартам оформления чисел. Это сделано исключительно для удобства визуального восприятия больших числовых последовательностей, например, "1 234 567" становится гораздо легче читать, чем "1234567".

Критически важно понимать, что на уровне данных — будь то в запросе 1С или в переменной типа "Число" — никаких пробелов не существует. Число хранится как единое целое или дробное значение. Пробелы появляются только в тот момент, когда число преобразуется в строковое представление для его вывода: на форму, в отчет, или, как в нашем случае, в текстовый файл для дальнейшей выгрузки. Следовательно, нашей основной задачей будет именно управление этим процессом преобразования числа в строку, чтобы исключить добавление неразрывных пробелов.

Основное решение: Использование функции Формат() с параметром ЧГ=""

Наиболее эффективный, надежный и правильный способ избавиться от неразрывных пробелов в числах при формировании CSV-файла — это явное управление форматированием числовых значений с помощью стандартной функции Формат(). Мы применим ее непосредственно в серверном коде 1С, который отвечает за построчное формирование CSV-строк из табличной части данных.

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


&НаСервере
Функция СоздатьСтрокуCSV(ЗаписьТЗ, СимволРазделителя)    
    
    стрЗапись = "";    
    
    Для каждого Поле Из ЗаписьТЗ Цикл
        
        Если СтрДлина(стрЗапись) > 0 Тогда
            стрЗапись = стрЗапись + СимволРазделителя;
        КонецЕсли;    
        
        Если ТипЗнч(поле) = Тип("Число") Тогда
            стрПоле = ?(ЗначениеЗаполнено(поле),Формат(поле,"ЧРД=."),"0");        
        ИначеЕсли ТипЗнч(поле) = Тип("Дата") Тогда 
            стрПоле = Формат(поле,"ДФ=dd.MM.yyyy");             
        Иначе //Если ТипЗнч(поле) = Тип("Строка") Тогда            
            стрПоле = СтрЗаменить(Строка(поле),"""","""""");           
            Если 
                ( СтрНайти(стрПоле," ") > 0  ) ИЛИ
                ( СтрНайти(стрПоле,"""") > 0 ) ИЛИ
                ( СтрНайти(стрПоле,",") > 0  ) ИЛИ
                ( СтрНайти(стрПоле,";") > 0  ) ИЛИ
                ( СтрНайти(стрПоле,Символы.Таб) > 0 )  ИЛИ
                ( СтрНайти(стрПоле,Символы.ВК) > 0 )   ИЛИ
                ( СтрНайти(стрПоле,Символы.ПФ) > 0 )   ИЛИ
                ( СтрНайти(стрПоле,Символы.ВТаб) > 0 ) ИЛИ
                ( СтрНайти(стрПоле,Символы.НПП) > 0 )  ИЛИ
                ( СтрНайти(стрПоле,Символы.ПС) > 0 ) 
            Тогда 
                стрПоле = """" + стрПоле + """";
            КонецЕсли;                
        КонецЕсли;    
        
        стрЗапись = стрЗапись + Строка(стрПоле);
        
    КонецЦикла; 
    
    Возврат стрЗапись;
    
КонецФункции

Нас интересует блок кода, который непосредственно обрабатывает поля типа "Число":


Если ТипЗнч(поле) = Тип("Число") Тогда
    стрПоле = ?(ЗначениеЗаполнено(поле),Формат(поле,"ЧРД=."),"0");        

В этой строке мы видим вызов функции Формат(). Строка форматирования "ЧРД=." указывает, что разделителем дробной части должна быть точка. Однако, этот формат не содержит явных указаний по разделителю групп разрядов (тысяч). Из-за отсутствия такого указания, система 1С применяет свои настройки по умолчанию, которые для русского языка часто включают неразрывный пробел. Именно это и приводит к появлению нежелательных пробелов в ваших числовых значениях.

Чтобы полностью исключить использование разделителей групп разрядов, нам необходимо добавить в строку форматирования параметр ЧГ="" (Число, Группировка). Пустое значение этого параметра явно указывает системе, что группировка разрядов не должна применяться вовсе. Таким образом, мы получаем число в строковом представлении без каких-либо разделителей групп разрядов.

Давайте внесем необходимое изменение в строку форматирования:


Если ТипЗнч(поле) = Тип("Число") Тогда
    стрПоле = ?(ЗначениеЗаполнено(поле),Формат(поле,"ЧРД=.; ЧГ="),"0");
КонецЕсли;

Что мы конкретно изменили? Мы добавили параметр ЧГ= с пустым значением. Это означает: "используй точку как разделитель дробной части, но *не используй* никакого символа для группировки разрядов". В результате, число "1 000" будет преобразовано в строку "1000", а "1 234 567.89" – в "1234567.89". Это изменение гарантирует, что в формируемый CSV-файл попадут строковые представления чисел без каких-либо неразрывных пробелов или других разделителей групп разрядов, которые могут помешать корректному импорту в целевые системы.

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

Подробный анализ процесса форматирования чисел в 1С

Давайте глубже рассмотрим механику работы функции Формат() и особенности её параметров применительно к числовым значениям в 1С.

  1. Типы параметров Формат(): Функция Формат() принимает два основных аргумента: само форматируемое значение (в нашем случае, числовое поле) и строку формата. Строка формата представляет собой набор параметров, разделенных точкой с запятой. Каждый параметр имеет вид "ИМЯ=ЗНАЧЕНИЕ", что позволяет очень гибко настраивать вывод.
  2. Параметр ЧРД= (Число, Разделитель Дробной части): Мы уже использовали этот параметр в нашем примере. Он определяет символ, который будет использоваться для отделения целой части числа от дробной. Наиболее распространенные значения: . (точка) или , (запятая). Выбор конкретного символа разделителя зависит от требований к CSV-файлу и специфики целевой системы, в которую будет производиться импорт. В нашем решении мы используем точку, что является общепринятым для многих CSV-файлов.
  3. Параметр ЧГ= (Число, Группировка): Это самый ключевой параметр для решения нашей задачи. Он предназначен для задания символа, который будет использоваться для разделения групп разрядов (тысяч, миллионов и так далее).
    • Если параметр отсутствует в строке формата (как было изначально в вашем коде), 1С использует региональные настройки операционной системы или настройки конфигурации по умолчанию. Для русскоязычной локали это, как правило, приводит к появлению неразрывного пробела (символ Символы.НПП).
    • Если мы указываем ЧГ="" (пустая строка), мы *явно предписываем* 1С не применять никакую группировку разрядов. Это и есть наш желаемый результат – получить числовое значение без каких-либо разделителей групп разрядов.
    • Также можно указать другой символ, например, ЧГ=',', если по каким-то причинам требуется группировка с запятой. Однако для выгрузки в CSV без пробелов и лишних символов, пустая строка является оптимальным решением.
  4. Другие полезные параметры: Для чисел также существуют другие полезные параметры, которые могут дать еще больший контроль над форматированием. Например:
    • ЧДЦ= (Число, Десятичных Знаков): позволяет задать точное количество знаков после запятой. Например, "ЧДЦ=2" выведет ровно два знака после запятой, при необходимости добавляя нули.
    • ЧН= (Число, Нули): управляет выводом незначащих нулей. "ЧН=0" может убрать незначащие нули.
    • ЧВ= (Число, Вывод): определяет дополнительные параметры вывода, например, для отрицательных чисел.
    Комбинируя эти параметры, мы получаем практически полный контроль над строковым представлением чисел, что позволяет адаптировать вывод под любые, даже самые специфические требования заказчика.

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

Альтернативные, но менее предпочтительные подходы

Хотя решение с функцией Формат() является наиболее чистым, эффективным и рекомендованным, давайте коротко рассмотрим другие варианты, которые иногда упоминаются или приходят в голову при решении подобных задач.

  1. Преобразование в запросе 1С: Изначально автор темы интересовался возможностью преобразования числовых значений непосредственно в запросе. Однако, в типовых запросах 1С нет прямого аналога функции Формат(), который бы предоставлял такой же гибкий и детальный контроль над форматированием чисел. Функции типа СТРОКА() в запросе преобразуют число в строку, но они также могут использовать региональные настройки с неразрывными пробелами по умолчанию, если не указано иное. Кроме того, преобразование числовых полей в строковые на этапе запроса может значительно усложнить дальнейшие вычисления, если они требуются в этом же запросе или в последующих временных таблицах. Это может привести к потере возможности выполнять агрегатные функции над полями, которые уже стали строками.
  2. Постобработка текстового файла: Теоретически, можно было бы сформировать CSV-файл как есть, с неразрывными пробелами, а затем прочитать его содержимое в текстовую переменную и выполнить замену всех вхождений неразрывного пробела на обычный пустой символ с помощью функции СтрЗаменить().

    Пример концепции:

    
    ТекстCSV = СоздатьДанныеCSV(ТЗ, СимволРазделителя); // Исходное создание текста CSV
    ТекстCSV = СтрЗаменить(ТекстCSV, Символы.НПП, ""); // Заменяем все неразрывные пробелы на пустую строку
    // Далее текст записывается в файл
    

    Этот подход является менее предпочтительным по нескольким причинам:

    • Это дополнительная операция над уже сформированной, зачастую очень большой, строкой. Такая операция может быть менее производительной по сравнению с корректным форматированием на этапе создания строки, особенно если данных много.
    • Существует небольшой риск того, что неразрывный пробел может случайно встретиться в текстовых полях, где он должен быть сохранен как часть осмысленного текста. Хотя для CSV это маловероятно, поскольку текстовые поля обычно заключаются в кавычки, этот риск все же существует.
    • Главное, что проблема решается на этапе *постобработки вывода*, а не на этапе *формирования корректных данных*. Всегда лучше устранять проблему в её источнике, чем "чистить" результат.

Заключение

Мы выяснили, что наиболее правильный, эффективный и надежный способ убрать неразрывные пробелы из чисел при выгрузке данных в формат CSV в 1С — это использовать функцию Формат() с параметром ЧГ="". Это изменение необходимо внести в код, который отвечает за построчное формирование CSV-данных, в тот момент, когда числовые значения преобразуются в строки.

Этот подход обеспечивает высокую чистоту данных, полное соответствие стандартам CSV и минимизирует необходимость в дополнительных шагах по постобработке файла. Следуя этим рекомендациям, мы гарантируем, что ваш CSV-файл будет готов к беспроблемному импорту в любую целевую информационную систему, без ошибок, вызванных некорректным форматированием числовых значений. Применяйте эти знания для создания надежных и эффективных механизмов обмена данными в ваших решениях на платформе 1С:Предприятие.

← На главную