При выгрузке данных в текстовые форматы или файлы обмена CSV в платформе 1С:Предприятие 7.7 разработчики нередко сталкиваются с ситуацией: при формировании одной строки с разделителями и добавлении её через объект Текст в результирующем файле одна запись неожиданно разрывается на две, три или более строк. В результате нарушается структура файла, и принимающая система (например, АРМ кассира, сайт или внешняя база) выдает ошибку парсинга.
Разберем детально, почему это происходит, как обнаружить проблемные данные в информационной базе и какими способами можно исключить разрывы строк при формировании файла.
Проанализируем исходный код формирования строки:
_текстКлиенты = СоздатьОбъект("Текст");
_текстКлиенты.КодоваяСтраница(0);
_текстКлиенты.ДобавитьСтроку(_стрКлиенты);
_текстКлиенты.Записать(мПутьВыгрузки + "clients.csv");
Метод ДобавитьСтроку() объекта Текст помещает переданную строковую переменную в буфер без дополнительной обработки. Если внутри строковых реквизитов (например, Наименование, ПолноеНаименование или Адрес) уже содержатся невидимые управляющие символы перевода строки — Симв(10) (Line Feed, LF) или Симв(13) (Carriage Return, CR), метод Записать() воспринимает их как физическое окончание строки и переносит оставшуюся часть текста на новую позицию.
Такие символы обычно попадают в базу данных следующими путями:
Если в реквизите содержатся скрытые переносы, платформа 1С 7.7 позволяет легко определить их количество с помощью системных функций работы с многострочным текстом. Разберем алгоритм очистки переменной с использованием функций СтрЧислоСтрок() и СтрПолучитьСтроку():
Функция ОчиститьПереносыСтрок(Знач ИсходныйТекст)
Перем Результат, Ном, СтрПодстрока;
Результат = "";
Для Ном = 1 По СтрЧислоСтрок(ИсходныйТекст) Цикл
СтрПодстрока = СокрЛП(СтрПолучитьСтроку(ИсходныйТекст, Ном));
Если ПустаяСтрока(СтрПодстрока) = 0 Тогда
Если ПустаяСтрока(Результат) = 0 Тогда
Результат = Результат + " " + СтрПодстрока;
Иначе
Результат = СтрПодстрока;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Используем данную функцию перед объединением реквизитов в строку выгрузки:
ИмяОчищенное = ОчиститьПереносыСтрок(СпрКлиенты.Наименование);
АдресОчищенный = ОчиститьПереносыСтрок(СпрКлиенты.ЮрАдрес);
_стрКлиенты = Строка(СпрКлиенты.Код) + ";" + ИмяОчищенное + ";" + АдресОчищенный;
_текстКлиенты.ДобавитьСтроку(_стрКлиенты);
Поскольку в синтаксисе встроенного языка 1С 7.7 отсутствует встроенная функция глобального контекста для автозамены строк, напишем собственную процедуру замены недопустимых байтов Симв(10) и Симв(13) на пробелы:
Функция ЗаменитьСимвол(СтрокаТекста, ИскомыйСимвол, СимволЗамены)
Перем Поз, ТекСтрока;
ТекСтрока = СтрокаТекста;
Поз = Найти(ТекСтрока, ИскомыйСимвол);
Пока Поз > 0 Цикл
ТекСтрока = Лев(ТекСтрока, Поз - 1) + СимволЗамены + Сред(ТекСтрока, Поз + 1);
Поз = Найти(ТекСтрока, ИскомыйСимвол);
КонецЦикла;
Возврат ТекСтрока;
КонецФункции
Функция ПодготовитьСтрокуДляCSV(ИсходнаяСтрока)
Перем Рез;
Рез = ЗаменитьСимвол(ИсходнаяСтрока, Симв(13), " ");
Рез = ЗаменитьСимвол(Рез, Симв(10), " ");
Возврат СокрЛП(Рез);
КонецФункции
Для предотвращения подобных ошибок в будущем рекомендуется выполнить проверку и исправление записей непосредственно в справочниках конфигурации. Посмотрим на пример сервисной обработки, которая сканирует значения реквизитов и находит позиции с непечатными символами:
Процедура ПроверитьСправочник()
Перем Спр, Сч, ИскСимв, ДлинаСтр, ТекНаименование;
Спр = СоздатьОбъект("Справочник.Контрагенты");
Спр.ВыбратьЭлементы(0);
Пока Спр.ПолучитьЭлемент() = 1 Цикл
Если Спр.ЭтоГруппа() = 1 Тогда
Продолжить;
КонецЕсли;
ТекНаименование = Спр.Наименование;
ДлинаСтр = СтрДлина(ТекНаименование);
Для Сч = 1 По ДлинаСтр Цикл
ИскСимв = Сред(ТекНаименование, Сч, 1);
Если (КодСимв(ИскСимв) = 10) Или (КодСимв(ИскСимв) = 13) Тогда
Сообщить("Найден перевод строки в элементе: " + Спр.ТекущийЭлемент() + " (Код: " + Спр.Код + ")");
Прервать;
КонецЕсли;
КонецЦикла;
КонецЦикла;
КонецПроцедуры
;). Если он присутствует, значение поля необходимо обрамлять двойными кавычками.", по спецификации формата CSV их следует заменять на парные двойные кавычки "".КодоваяСтраница(0) сохраняет файл в кодировке Windows (ANSI, CP1251). Если внешняя система требует кодировку DOS (CP866), используйте параметр КодоваяСтраница(1).