При решении задач интеграции 1С с внешними системами, особенно с банковскими шлюзами, разработчики часто сталкиваются с необходимостью изменения формата выгрузки данных. Распространенный сценарий — переход от сложного структурированного формата XML к более простому текстовому формату CSV (Comma-Separated Values). У начинающих специалистов иногда возникает иллюзия: достаточно ли просто изменить расширение файла в коде с .xml на .csv, чтобы система приняла файл?
В этой статье мы подробно разберем, почему простое переименование файлов в коде никогда не сработает, детально проанализируем разницу между структурами данных, а также рассмотрим практические способы реализации полноценной выгрузки в формат CSV на платформе «1С:Предприятие 8.3».
Для начала выясним причину, почему физическая замена расширения файла в коде (например, указание имени "выгрузка.csv" вместо "выгрузка.xml") не превращает данные в формат CSV.
Расширение файла — это всего лишь маска, подсказка для операционной системы, указывающая, какое приложение по умолчанию должно открывать этот файл. Сам же файл внутри остается неизменным. Если мы запишем XML-структуру (с тегами, пространствами имен и иерархией) и сохраним ее с расширением .csv, текстовый редактор или банковский терминал все равно увидят внутри типичный XML-код. Банковская система выдаст ошибку формата при первой же попытке парсинга, поскольку ожидает плоскую таблицу, где данные разделены строго определенными символами (например, точкой с запятой или запятой).
Давайте наглядно сопоставим структуру представления одних и тех же данных в этих двух форматах.
Представим, что нам необходимо выгрузить простую таблицу со сведениями о платежах: Номер документа, Дата, Контрагент и Сумма. Посмотрим, как это выглядит в разных системах разметки.
Так выглядит структура в формате XML:
<?xml version="1.0" encoding="UTF-8"?>
<Платежи>
<Строка>
<Номер>0001</Номер>
<Дата>2023-10-27</Дата>
<Контрагент>ООО "Ромашка"</Контрагент>
<Сумма>150000.00</Сумма>
</Строка>
<Строка>
<Номер>0002</Номер>
<Дата>2023-10-28</Дата>
<Контрагент>ИП Иванов И.И.</Контрагент>
<Сумма>45000.50</Сумма>
</Строка>
</Платежи>
А вот так те же самые данные должны выглядеть в формате CSV (в качестве разделителя используется точка с запятой):
Номер;Дата;Контрагент;Сумма
"0001";"2023-10-27";"ООО ""Ромашка""";150000.00
"0002";"2023-10-28";"ИП Иванов И.И.";45000.50
Проанализировав эти два примера, мы увидим ключевые отличия:
<Сумма>...</Сумма>). В CSV границы определяются специальным символом-разделителем (запятой, точкой с запятой или знаком табуляции)."ООО ""Ромашка""").Теперь перейдем к практической части и рассмотрим, какими инструментами платформы 1С мы можем воспользоваться для создания корректного CSV-файла.
Поскольку CSV — это обычный текстовый файл, самым гибким, надежным и контролируемым методом его формирования является последовательная запись строк с помощью объекта ЗаписьТекста. Этот способ позволяет разработчику полностью контролировать кодировку, разделители, переводы строк и правила экранирования символов.
Разберем по шагам готовый алгоритм выгрузки таблицы значений в файл CSV:
&НаСервере
Процедура ВыгрузитьТаблицуВCSV(ТаблицаДанных, ПутьКФайлу)
// Инициализируем объект для записи текстового файла.
// Для банков чаще всего критично использование кодировки Windows-1251 (ANSI).
ЗаписьТекста = Новый ЗаписьТекста(ПутьКФайлу, КодировкаТекста.ANSI);
Разделитель = ";"; // Указываем разделитель колонок
// Шаг 1. Формируем и записываем строку заголовков (шапку таблицы)
МассивЗаголовков = Новый Массив;
Для Каждого Колонка Из ТаблицаДанных.Колонки Цикл
МассивЗаголовков.Добавить(Колонка.Имя);
КонецЦикла;
СтрокаЗаголовков = СтрСоединить(МассивЗаголовков, Разделитель);
ЗаписьТекста.ЗаписатьСтроку(СтрокаЗаголовков);
// Шаг 2. Обходим строки таблицы данных и записываем их в файл
Для Каждого СтрокаДанных Из ТаблицаДанных Цикл
МассивЗначенийСтроки = Новый Массив;
Для Каждого Колонка Из ТаблицаДанных.Колонки Цикл
ТекущееЗначение = СтрокаДанных[Колонка.Имя];
// Приводим любое значение к строковому типу и экранируем его
ПодготовленноеЗначение = ПодготовитьЗначениеДляCSV(ТекущееЗначение, Разделитель);
МассивЗначенийСтроки.Добавить(ПодготовленноеЗначение);
КонецЦикла;
СтрокаДляЗаписи = СтрСоединить(МассивЗначенийСтроки, Разделитель);
ЗаписьТекста.ЗаписатьСтроку(СтрокаДляЗаписи);
КонецЦикла;
// Обязательно закрываем файл после завершения операции, чтобы освободить ресурсы системы
ЗаписьТекста.Закрыть();
КонецПроцедуры
Особое внимание уделим функции экранирования данных. Если в текстовом поле встретится символ разделителя (например, точка с запятой в назначении платежа) или символ переноса строки, то без специальной обработки структура результирующего файла CSV будет безвозвратно сломана (колонки "съедут").
Напишем вспомогательную функцию для подготовки значений:
&НаСервере
Функция ПодготовитьЗначениеДляCSV(Значение, Разделитель)
ТекстЗначения = Строка(Значение);
// Если тип значения - Булево, приведем к удобному для аналитики формату
Если ТипЗнч(Значение) = Тип("Булево") Тогда
Возврат ?(Значение, "1", "0");
КонецЕсли;
// Если тип значения - Число, уберем неразрывные пробелы, разделяющие разряды
Если ТипЗнч(Значение) = Тип("Число") Тогда
Возврат Формат(Значение, "ЧГ=0");
КонецЕсли;
// Если тип значения - Дата, запишем в стандартном формате ISO
Если ТипЗнч(Значение) = Тип("Дата") Тогда
Возврат Формат(Значение, "ДФ=yyyy-MM-dd");
КонецЕсли;
// Для текстовых полей проверяем необходимость экранирования
НужноЭкранировать = Ложь;
Если Найти(ТекстЗначения, Разделитель) > 0
Или Найти(ТекстЗначения, """") > 0
Или Найти(ТекстЗначения, Символы.ПС) > 0
Или Найти(ТекстЗначения, Символы.ВК) > 0 Тогда
НужноЭкранировать = Истина;
КонецЕсли;
// Если поле требует экранирования, удваиваем внутренние кавычки и оборачиваем строку в кавычки
Если НужноЭкранировать Тогда
ТекстЗначения = СтрЗаменить(ТекстЗначения, """", """""");
ТекстЗначения = """" + ТекстЗначения + """";
КонецЕсли;
Возврат ТекстЗначения;
КонецФункции
Рассмотрим альтернативный способ, который часто применяется для быстрого экспорта печатных форм. Платформа 1С позволяет сохранить любой объект типа ТабличныйДокумент в текстовый файл.
Проанализируем этот сценарий программно:
&НаСервере
Процедура СохранитьТабДокВТекст(ТабличныйДокумент, ИмяФайла)
// Платформа запишет табличный документ как текстовый файл с разделителями-табуляциями
ТабличныйДокумент.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.TXT);
// Если принимающей стороне (банку) строго необходим другой разделитель (например, ";"),
// мы можем прочитать полученный файл как текст и выполнить пакетную замену символов.
ТекстФайла = Новый ТекстовыйДокумент;
ТекстФайла.Прочитать(ИмяФайла, КодировкаТекста.ANSI);
ПолныйТекст = ТекстФайла.ПолучитьТекст();
// Символ Табуляции заменяем на Точку с запятой
МодифицированныйТекст = СтрЗаменить(ПолныйТекст, Символы.Таб, ";");
ТекстФайла.УстановитьТекст(МодифицированныйТекст);
ТекстФайла.Записать(ИмяФайла, КодировкаТекста.ANSI);
КонецПроцедуры
Преимущество метода: Минимум написания кода для простых отчетов, которые уже выводятся на экран в виде табличных документов.
Недостаток метода: Этот метод плохо подходит для сложных выгрузок реестров. Он не учитывает правила экранирования кавычек внутри самих ячеек, из-за чего в результирующем файле могут возникнуть логические сдвиги колонок, если в текстовых реквизитах окажутся символы табуляции или точки с запятой.
Если в вашей конфигурации внедрена БСП, мы можем существенно упростить обработку строковых данных. Обратите внимание на полезные методы общего модуля СтроковыеФункцииКлиентСервер. Например, функция СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок() поможет быстро разобрать CSV-строку обратно на составляющие при чтении файла.
Начиная с версии платформы 1С 8.3.6, в языке появились встроенные быстрые функции для работы со строками, работающие на уровне ядра:
СтрРазделить(Строка, Разделитель, ВключатьПустые) — разбивает строку в массив по указанному разделителю.СтрСоединить(Массив, Разделитель) — собирает строку из массива элементов, разделяя их указанным символом.Использование этих функций значительно ускоряет работу алгоритмов экспорта и импорта по сравнению со старыми посимвольными циклами разбора строк.
Интеграционные шлюзы банковских систем предъявляют жесткие требования к передаваемым текстовым файлам. При разработке выгрузки в формате CSV обязательно обратите внимание на следующие параметры спецификации:
Windows-1251 (в 1С это КодировкаТекста.ANSI). Если выгрузить файл в кодировке по умолчанию (которая на серверах под Linux часто является UTF-8), банк вернет ошибку из-за искажения кириллических символов (появятся "кракозябры"). Если же требуется кодировка UTF-8, уточните, нужен ли маркер последовательности байтов (BOM).CRLF (в коде 1С: Символы.ВК + Символы.ПС). На операционных системах семейства Linux используется только перевод строки — LF (Символы.ПС). Если сервер 1С работает под управлением ОС Linux, а принимающий сервер банка ожидает строго формат Windows, может потребоваться принудительное добавление символов Символы.ВК перед переходом на новую строку.ЗаписатьСтроку() всегда добавляет символ перевода строки в конце записи. Если банк выдает ошибку парсинга последней строки, используйте метод Записать() вместо ЗаписатьСтроку() для вывода последнего элемента файла, чтобы не плодить финальный пустой перевод строки.Подведем итог: Переход от формата XML к формату CSV требует полного переписывания алгоритма генерации файла в кодовой базе обработки. Простое переименование файлов приведет к неработоспособности интеграции. Используя гибкий объект ЗаписьТекста и встроенные функции работы со строками платформы 1С, вы сможете написать надежный, быстрый и легко поддерживаемый программный код выгрузки, полностью соответствующий требованиям принимающей стороны.