Как правильно разобрать CSV-файл в 1С, если в строках встречаются запятые

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

Работа с текстовыми файлами формата CSV — одна из самых частых задач при интеграции 1С с внешними системами. На первый взгляд кажется, что достаточно использовать простую функцию СтрРазделить() или РазложитьВМассивПодстрок(), выбрав запятую в качестве разделителя. Однако на практике мы часто сталкиваемся с ситуацией, когда внутри текстового поля (заключенного в кавычки) также содержатся запятые. В этом случае стандартное разделение по символу «сломает» структуру данных, так как одна колонка будет ошибочно разбита на несколько частей. Чтобы решить задачу без написания собственного парсера, можно использовать обработку для импорта данных из CSV и других форматов в 1С.

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

Способ 1. Использование встроенного объекта ЧтениеCSV

Начиная с версии платформы 8.3.6, в 1С появился специализированный объект ЧтениеCSV. Это наиболее правильный и эффективный метод, так как он изначально спроектирован с учетом международного стандарта RFC 4180. Этот объект автоматически умеет игнорировать разделители, если они находятся внутри кавычек, и корректно обрабатывает удвоенные кавычки внутри текста.

Рассмотрим пример кода для чтения такого файла:


// Создаем объект для чтения CSV
Чтение = Новый ЧтениеCSV;
// Указываем параметры: путь к файлу, кодировка и разделитель
Чтение.ОткрытьФайл(ПутьКФайлу, "UTF-8");

// Создаем настройки парсера
Настройки = Новый ПараметрыЧтенияCSV;
Настройки.РазделительПолей = ",";
Настройки.СимволЦитаты = """";

// Читаем файл построчно в цикле
Пока Истина Цикл
    МассивРезультат = Чтение.Прочитать();
    Если МассивРезультат = Неопределено Тогда
        Прервать; // Конец файла
    КонецЕсли;
    
    // В МассивРезультат уже лежат корректно разделенные параметры
    // Запятые внутри кавычек не привели к разрыву строки
    Число1 = МассивРезультат[0];
    Текст1  = МассивРезультат[1];
КонецЦикла;
Чтение.Закрыть();

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

Способ 2. Посимвольный разбор строки (Алгоритм конечного автомата)

Если вы работаете на старой версии платформы или вам необходимо разобрать строку «на лету» без обращения к файловой системе, можно реализовать алгоритм посимвольного сканирования. Основная идея заключается в использовании флага «режим кавычек».

Проанализируем логику этого процесса: мы перебираем строку символ за символом. Если мы встречаем кавычку, мы «входим» в текстовый блок (флаг устанавливается в Истина). Пока мы находимся внутри блока, все запятые считаются обычным текстом. Как только мы встречаем вторую кавычку — мы «выходим» из блока.

Рассмотрим пример реализации функции на языке 1С:


Функция РазобратьСтрокуCSV(Знач ИсходнаяСтрока)
    Результат = Новый Массив;
    ТекущееЗначение = "";
    ВнутриКавычек = Ложь;
    
    Для Позиция = 1 По СтрДлина(ИсходнаяСтрока) Цикл
        Символ = Сред(ИсходнаяСтрока, Позиция, 1);
        
        Если Символ = """" Тогда
            // Переключаем флаг при встрече кавычки
            ВнутриКавычек = Не ВнутриКавычек;
            // Саму кавычку в итоговое значение обычно не добавляем, 
            // если она используется как ограничитель
            Продолжить;
        ИначеЕсли Символ = "," И Не ВнутриКавычек Тогда
            // Если запятая вне кавычек — это разделитель полей
            Результат.Добавить(СокрЛП(ТекущееЗначение));
            ТекущееЗначение = "";
        Иначе
            // В остальных случаях просто накапливаем символы
            ТекущееЗначение = ТекущееЗначение + Символ;
        КонецЕсли;
    КонецЦикла;
    
    // Добавляем последнее значение после последней запятой
    Результат.Добавить(СокрЛП(ТекущееЗначение));
    
    Возврат Результат;
КонецФункции

Этот метод надежен и позволяет полностью контролировать процесс парсинга. Однако стоит помнить, что в реальных CSV кавычки внутри текста могут экранироваться (удваиваться). В таком случае алгоритм потребует небольшого усложнения для проверки следующего символа.

Способ 3. Использование регулярных выражений (RegExp)

Для тех, кто предпочитает лаконичный код, хорошим вариантом станет использование COM-объекта VBScript.RegExp. Регулярное выражение позволяет найти запятые, которые **не** окружены кавычками.

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


// Пример логики использования RegExp
RegExp = Новый COMОбъект("VBScript.RegExp");
RegExp.Global = Истина;
RegExp.MultiLine = Ложь;
// Сложный паттерн, учитывающий кавычки
RegExp.Pattern = ",(?=(?:[^""]*""[^""]*"")*[^""]*$)";

// Заменяем запятые-разделители на уникальный символ, например, тильду
Результат = RegExp.Replace(ИсходнаяСтрока, "|");
МассивПолей = СтрРазделить(Результат, "|");

Внимание: Использование COM-объектов привязывает ваше решение к операционной системе Windows и может работать медленнее при инициализации объекта в цикле. Рекомендуется создавать объект RegExp один раз перед началом обработки файла.

Способ 4. Внешние источники данных и ADO

Если CSV-файл имеет огромный размер (сотни мегабайт), эффективнее всего работать с ним как с таблицей базы данных. С помощью технологии ADO можно выполнить SQL-запрос к текстовому файлу. Драйвер Microsoft Text Driver автоматически берет на себя все сложности с разбором кавычек, запятых и кодировок.

Разберем основные шаги:

  1. Создаем файл schema.ini в папке с файлом, где описываем структуру (разделитель, форматы дат и чисел).
  2. Подключаемся через ADODB.Connection.
  3. Выполняем запрос SELECT * FROM [file.csv].

Этот путь сложнее в настройке, но незаменим при обработке сверхбольших объемов данных, так как позволяет использовать фильтрацию (WHERE) и сортировку еще до загрузки данных в память 1С.

Общие рекомендации при работе с CSV

Проанализируем типичные ошибки, которые могут возникнуть вне зависимости от выбранного метода:

  1. Кодировка файла: CSV-файлы часто приходят в кодировке UTF-8 с BOM-символом или в Windows-1251. Всегда явно указывайте кодировку при открытии файла в 1С (объекты ЧтениеТекста или ЧтениеCSV), иначе вместо русских букв вы получите «кракозябры».
  2. Пробелы вокруг разделителей: Некоторые системы выгружают данные в формате 123 , "Текст". Обратите внимание, что пробел перед кавычкой может сбить с толку простой парсер. Всегда используйте функцию СокрЛП() для очистки полученных значений.
  3. Дробные числа: Если в системе-источнике десятичный разделитель — запятая, и она не заключена в кавычки, такой файл перестает соответствовать формату CSV и превращается в «дичь», которую невозможно разобрать автоматически. В таких случаях необходимо договариваться с поставщиком данных о смене разделителя (например, на точку с запятой или табуляцию).

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

← На главную