В процессе работы с платформой 1С:Предприятие часто возникает задача выгрузки различных данных в формат CSV (Comma Separated Values). Этот формат является универсальным и широко используется для обмена информацией между разными системами благодаря своей простоте и текстовому представлению. Однако, пользователи регулярно сталкиваются с проблемой, когда числовые данные, которые ожидаются в формате "1000", отображаются в результирующем CSV-файле как "1 000" или "1 000". Причиной такого отображения являются неразрывные пробелы, которые 1С использует по умолчанию для повышения читаемости больших числовых значений, особенно в соответствии с региональными стандартами (например, для русского языка). При последующем импорте такого файла в другие программы, эти "числа" могут быть восприняты как текст, или некорректно обработаны, что неизбежно приводит к ошибкам и потере данных.
Мы рассмотрим, как можно эффективно решить эту проблему, обеспечив корректное форматирование числовых значений непосредственно перед их записью в CSV-файл. Наша цель – минимизировать необходимость в трудоемкой постобработке файла и гарантировать чистоту данных.
Прежде чем приступить к непосредственному решению, давайте проанализируем, почему вообще появляются неразрывные пробелы. В системе 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С.
Формат(): Функция Формат() принимает два основных аргумента: само форматируемое значение (в нашем случае, числовое поле) и строку формата. Строка формата представляет собой набор параметров, разделенных точкой с запятой. Каждый параметр имеет вид "ИМЯ=ЗНАЧЕНИЕ", что позволяет очень гибко настраивать вывод.ЧРД= (Число, Разделитель Дробной части): Мы уже использовали этот параметр в нашем примере. Он определяет символ, который будет использоваться для отделения целой части числа от дробной. Наиболее распространенные значения: . (точка) или , (запятая). Выбор конкретного символа разделителя зависит от требований к CSV-файлу и специфики целевой системы, в которую будет производиться импорт. В нашем решении мы используем точку, что является общепринятым для многих CSV-файлов.ЧГ= (Число, Группировка): Это самый ключевой параметр для решения нашей задачи. Он предназначен для задания символа, который будет использоваться для разделения групп разрядов (тысяч, миллионов и так далее).
Символы.НПП).ЧГ="" (пустая строка), мы *явно предписываем* 1С не применять никакую группировку разрядов. Это и есть наш желаемый результат – получить числовое значение без каких-либо разделителей групп разрядов.ЧГ=',', если по каким-то причинам требуется группировка с запятой. Однако для выгрузки в CSV без пробелов и лишних символов, пустая строка является оптимальным решением.ЧДЦ= (Число, Десятичных Знаков): позволяет задать точное количество знаков после запятой. Например, "ЧДЦ=2" выведет ровно два знака после запятой, при необходимости добавляя нули.ЧН= (Число, Нули): управляет выводом незначащих нулей. "ЧН=0" может убрать незначащие нули.ЧВ= (Число, Вывод): определяет дополнительные параметры вывода, например, для отрицательных чисел.Применяя комбинацию этих параметров, мы получаем полный контроль над строковым представлением чисел, что является необходимым условием для корректной выгрузки данных в формате CSV.
Хотя решение с функцией Формат() является наиболее чистым, эффективным и рекомендованным, давайте коротко рассмотрим другие варианты, которые иногда упоминаются или приходят в голову при решении подобных задач.
Формат(), который бы предоставлял такой же гибкий и детальный контроль над форматированием чисел. Функции типа СТРОКА() в запросе преобразуют число в строку, но они также могут использовать региональные настройки с неразрывными пробелами по умолчанию, если не указано иное. Кроме того, преобразование числовых полей в строковые на этапе запроса может значительно усложнить дальнейшие вычисления, если они требуются в этом же запросе или в последующих временных таблицах. Это может привести к потере возможности выполнять агрегатные функции над полями, которые уже стали строками.СтрЗаменить().
Пример концепции:
ТекстCSV = СоздатьДанныеCSV(ТЗ, СимволРазделителя); // Исходное создание текста CSV
ТекстCSV = СтрЗаменить(ТекстCSV, Символы.НПП, ""); // Заменяем все неразрывные пробелы на пустую строку
// Далее текст записывается в файл
Этот подход является менее предпочтительным по нескольким причинам:
Мы выяснили, что наиболее правильный, эффективный и надежный способ убрать неразрывные пробелы из чисел при выгрузке данных в формат CSV в 1С — это использовать функцию Формат() с параметром ЧГ="". Это изменение необходимо внести в код, который отвечает за построчное формирование CSV-данных, в тот момент, когда числовые значения преобразуются в строки.
Этот подход обеспечивает высокую чистоту данных, полное соответствие стандартам CSV и минимизирует необходимость в дополнительных шагах по постобработке файла. Следуя этим рекомендациям, мы гарантируем, что ваш CSV-файл будет готов к беспроблемному импорту в любую целевую информационную систему, без ошибок, вызванных некорректным форматированием числовых значений. Применяйте эти знания для создания надежных и эффективных механизмов обмена данными в ваших решениях на платформе 1С:Предприятие.