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

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

Часто в практике программирования мы сталкиваемся с задачей загрузки данных из файлов формата CSV. Обычно для разделения ячеек используется запятая или точка с запятой. Но что делать, если сам разделитель встречается внутри текста ячейки? Стандартная функция СтрРазделить в таких случаях отрабатывает некорректно, разбивая одну колонку на несколько. Разберем по шагам, как правильно решать эту задачу в 1С.

Проанализируем стандарт формата CSV

Прежде чем писать код, давайте выясним причину такого поведения и посмотрим на общепринятые стандарты. Формат CSV имеет четкие правила описания данных:

  1. По умолчанию, для упрощения разбора, все строковые значения обрамляются в двойные кавычки, а числовые — нет.
  2. Значения, содержащие зарезервированные служебные символы (двойная кавычка, запятая, точка с запятой, новая строка), обязательно обрамляются двойными кавычками.
  3. Если в самом значении встречается двойная кавычка, она представляется в файле в виде двух кавычек подряд (экранирование).

Таким образом, если значение содержит точку с запятой, в файле это будет выглядеть примерно так: "текст; продолжение текста", 123, "описание". Стандартный метод 1С ТабличныйДокумент.Прочитать() на сложных файлах часто дает сбои, поэтому рассмотрим надежные альтернативные методы.

Решение 1. Разработаем конечный автомат

Правильный разбор сложных файлов CSV — это не простое использование функции СтрРазделить, а построение алгоритма, известного как конечный автомат. Разберем подробнее, как это работает.

Суть конечного автомата заключается в посимвольном чтении строки. Автомат может находиться в нескольких состояниях (например: «чтение обычного текста», «чтение текста внутри кавычек»). Мы читаем каждый символ и на основе текущего состояния принимаем решение:

  1. Если встречаем открывающую кавычку — переключаем состояние в «внутри кавычек».
  2. Если встречаем разделитель (точку с запятой) и мы не внутри кавычек — значит, это конец текущей колонки, записываем значение в массив и переходим к следующей ячейке.
  3. Если встречаем разделитель и мы внутри кавычек — игнорируем его как разделитель и просто добавляем как текст в значение текущей ячейки.
  4. Если встречаем закрывающую кавычку — проверяем следующий символ. Если это снова кавычка, значит она экранирована (заменяем "" на "), если нет — выходим из состояния «внутри кавычек».

Также конечный автомат позволяет решить проблему многострочных значений. Если открывающая кавычка не была закрыта до конца строки, мы продолжаем чтение следующих строк из файла с помощью ЧтениеТекста.ПрочитатьСтроку(), пока не встретим закрывающую кавычку.

Решение 2. Использование технологии ADODB

Если файл большого объема (более 10 Мб) или мы не хотим писать сложный алгоритм конечного автомата, рассмотрим использование COM-объектов. В среде Windows мы можем прочитать CSV-файл как обычную базу данных через провайдер Microsoft Access Text Driver.

Создадим подключение с помощью COMОбъект("ADODB.Connection"). При таком подходе драйвер операционной системы берет на себя всю тяжелую работу: он сам понимает стандарты RFC 4180, корректно распознает кавычки, переводы строк и разделители внутри текста. Это работает быстрее посимвольного чтения, хотя и привязывает наше решение к платформе Windows.

Решение 3. Регулярные выражения (RegExp)

Проанализируем еще один элегантный способ — использование регулярных выражений через COMОбъект("VBScript.RegExp"). Вместо циклов и множества проверок, мы можем составить паттерн, который за одну операцию разобьет строку правильно.

Регулярное выражение можно настроить так, чтобы оно искало точку с запятой, за которой следует четное количество кавычек (что означает, что мы находимся вне строкового литерала). Это позволяет быстро получить нужный массив значений без сложных алгоритмов на внутреннем языке 1С.

Решение 4. Предварительная подготовка данных

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


// 1. Читаем строку из файла
СтрокаФайла = ЧтениеТекста.ПрочитатьСтроку();

// 2. Ищем экранированные разделители (например, точку с запятой внутри кавычек)
// и временно меняем их на уникальный набор символов, которого точно нет в тексте
СтрокаФайла = СтрЗаменить(СтрокаФайла, """;""", "#$&^");

// 3. Теперь можно безопасно разделить строку стандартным методом
МассивКолонок = СтрРазделить(СтрокаФайла, ";");

// 4. Проходим по массиву и возвращаем символы обратно, заодно убирая служебные кавычки
Для Индекс = 0 По МассивКолонок.ВГраница() Цикл
    ТекущееЗначение = МассивКолонок[Индекс];
    ТекущееЗначение = СтрЗаменить(ТекущееЗначение, "#$&^", ";");
    // Дальнейшая обработка и очистка кавычек
КонецЦикла;

Этот метод работает быстрее, чем посимвольный конечный автомат, если нужно быстро разделить строку на подстроки по ;, а затем проанализировать только те фрагменты, которые были излишне разбиты или содержали кавычки.

Подведем итоги

Мы выяснили причину ошибок при чтении CSV и рассмотрели несколько рабочих подходов. Выбор метода зависит от ваших задач: для максимальной кроссплатформенности и надежности используйте конечный автомат, для скорости и файлов огромного размера — ADODB, а для быстрых доработок — предварительную замену символов или RegExp. Применяйте эти решения на практике, и ваши интеграции будут работать стабильно!

← На главную