При выгрузке данных из 1С в формат CSV (или любой другой текстовый формат) разработчики часто сталкиваются с проблемой появления лишних пустых строк в конце файла. Это может стать критической ошибкой, если принимающая сторона (например, банковский терминал, веб-сервис или складская система) ожидает строго структурированные данные и не умеет игнорировать пустые строки. Рассмотрим подробно причины возникновения этой проблемы и разберем несколько эффективных способов её решения.
Проанализируем ситуацию, описанную в теме. Разработчик формирует текстовую строку внутри цикла, добавляя Символы.ПС (перевод строки) после каждой записи. В конце формирования используется объект ЗаписьТекста и его метод ЗаписатьСтроку(). Выясним, почему в итоге в конце файла появляются два перевода строки.
Во-первых, метод ЗаписатьСтроку(Текст) в 1С работает следующим образом: он записывает переданную строку в файл и автоматически добавляет к ней системный символ перевода строки (CRLF или LF). Если переменная Текст уже содержит в конце символ Символы.ПС, добавленный вручную в цикле, то в итоговом файле мы получим два идущих подряд переноса.
Во-вторых, логика условий внутри цикла часто дает сбои при определении "последней итерации", особенно если в выборке присутствуют условия Продолжить, которые нарушают ожидаемый счетчик записей.
Это самый простой и быстрый способ исправить ситуацию, если вы уже сформировали строку целиком. Метод Записать() записывает данные в файл "как есть", не добавляя ничего от себя. Рассмотрим пример корректировки кода:
Кодировка = КодировкаТекста.UTF8;
ТекстовыйФайлЗапись = Новый ЗаписьТекста(ИмяФайла, Кодировка);
// Вместо ТекстовыйФайлЗапись.ЗаписатьСтроку(Текст);
// Используем:
ТекстовыйФайлЗапись.Записать(Текст);
ТекстовыйФайлЗапись.Закрыть();
При таком подходе, если вы контролируете добавление Символы.ПС внутри своего алгоритма формирования переменной Текст, в конце файла будет ровно столько переносов, сколько вы добавили сами. Чтобы убрать последний перенос, можно воспользоваться функцией СокрП(), которая удалит все пробелы и символы перевода строки в конце текста.
Рассмотрим более профессиональный и производительный метод. Сложение строк через оператор "+" (конкатенация) в цикле — это плохая практика для 1С. При каждом сложении создается новая копия всей строки в памяти, что на больших объемах данных (тысячи строк) приводит к существенному замедлению системы.
Вместо этого мы рекомендуем использовать массив строк и метод СтрСоединить(). Этот метод автоматически вставляет разделитель между элементами массива, но не добавляет его после последнего элемента. Проанализируем пример кода:
МассивРезультат = Новый Массив;
Пока Выборка.Следующий() Цикл
// Проверки данных
Если Выборка.Количество <= 0 Или ПустаяСтрока(Выборка.Номенклатура.Артикул) Тогда
Продолжить;
КонецЕсли;
// Формируем строку одной записи
ТекущаяСтрока = СокрЛП(Выборка.Номенклатура.Артикул) + ";" + Выборка.Количество;
МассивРезультат.Добавить(ТекущаяСтрока);
КонецЦикла;
// Соединяем все строки через перевод строки
ИтоговыйТекст = СтрСоединить(МассивРезультат, Символы.ПС);
// Записываем файл без лишних переносов
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
Запись.Записать(ИтоговыйТекст);
Запись.Закрыть();
Преимущества этого метода:
Если вы работаете на платформе 8.3.6 и выше, самым правильным решением будет использование встроенного объекта ЗаписьCSV. Этот объект берет на себя все сложности форматирования, включая экранирование кавычек и управление разделителями строк.
Разберем, как это работает:
ПараметрыЗаписи = Новый ПараметрыЗаписиCSV(Символы.ПС, ";", """");
ЗаписьCSV = Новый ЗаписьCSV;
ЗаписьCSV.Открыть(ИмяФайла, КодировкаТекста.UTF8, ПараметрыЗаписи);
// Записываем заголовок
ЗаписьCSV.ЗаписатьСтроку("Артикул;Свободный остаток");
Пока Выборка.Следующий() Цикл
// Логика фильтрации...
// Объект сам сформирует строку и добавит нужные разделители
МассивДанных = Новый Массив;
МассивДанных.Добавить(СокрЛП(Выборка.Номенклатура.Артикул));
МассивДанных.Добавить(Выборка.Количество);
ЗаписьCSV.ЗаписатьСтроку(МассивДанных);
КонецЦикла;
ЗаписьCSV.Закрыть();
Использование ЗаписьCSV не только решает проблему с переносами строк, но и защищает ваш файл от "развала" структуры, если, например, в артикуле случайно окажется точка с запятой или кавычка. Платформа автоматически заключит такие поля в кавычки согласно стандарту RFC 4180.
Проанализируем еще один скрытый фактор. При использовании кодировки КодировкаТекста.UTF8 1С может добавлять в начало файла метку BOM (Byte Order Mark). Некоторые системы загрузки воспринимают эти три байта в начале первой строки как мусор или некорректный артикул.
Если ваша принимающая система жалуется на первую строку, попробуйте явно указать использование UTF-8 без BOM. В современных версиях платформы это делается при создании объекта ЗаписьТекста или ЗаписьCSV путем выбора соответствующего уточнения в параметрах кодировки.
Подведем итог. Чтобы избежать появления лишних пустых строк в конце файла, следуйте трем правилам:
ЗаписьТекста, применяйте метод Записать() вместо ЗаписатьСтроку().Массив и СтрСоединить() — это быстрее и надежнее.ЗаписьCSV, так как он соответствует международным стандартам обмена данными.