Как разобрать строку текстового документа с запятыми внутри кавычек в 1С?

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

При загрузке данных из внешних текстовых файлов (например, в формате CSV или выгрузок из сторонних учетных систем) часто возникает задача разбить строку на массив значений. Обычно элементы разделяются запятыми. Однако если среди полей есть наименования номенклатуры с техническими характеристиками (например, "Цепь рывковая двойная 2,5ммх60см"), запятая внутри строки воспринимается механизмом разбора как разделитель колонок. В результате целостность строки нарушается, а данные смещаются по колонкам.

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

Способ 1. Алгоритм посимвольного разбора строки

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

Рассмотрим пример процедуры, которая считывает элементы поочередно, корректно выделяя строки в кавычках и обычные значения (включая числа и пустые поля):


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

Проанализируем работу этого алгоритма. Если очередное поле начинается с символа кавычки """", код ищет следующую кавычку и извлекает содержимое между ними целиком, игнорируя любые запятые внутри. Если элемент начинается без кавычки, поиск выполняется до ближайшей запятой.

Способ 2. Объединение элементов после первичного разбиения

Рассмотрим альтернативный способ: сначала разбить строку базовым методом или регулярным выражением по разделителю, а затем в цикле склеить те части, которые были ошибочно разделены внутри текста номенклатуры.

Сформулируем алгоритм склейки фрагментов:

  1. Разбиваем исходную строку по запятым на базовый массив.
  2. Проходим по элементам массива. Если очередной элемент начинается с кавычки, но не заканчивается ею, значит, текстовое поле было разорвано.
  3. Во вложенном цикле объединяем текущий элемент со следующими частями через запятую до тех пор, пока не встретим закрывающую кавычку.

Посмотрим на реализацию этого подхода:


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

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

Для систем, работающих под управлением ОС Windows, разбор текстовой строки можно выполнить с использованием COM-объекта VBScript.RegExp.

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


Функция РазложитьСтрокуRegExp(Знач СтрокаТекста, Разделитель = ",") Экспорт
    RegExp = Новый COMОбъект("VBScript.RegExp");
    RegExp.MultiLine = Ложь;
    RegExp.Global = Истина;
    RegExp.IgnoreCase = Ложь;
    
    // Маска: ищет текст в кавычках ИЛИ последовательность символов без разделителя
    RegExp.Pattern = """(.*?)""|([^\" + Разделитель + "]+)";
    
    Matches = RegExp.Execute(СтрокаТекста);
    Массив = Новый Массив;
    
    Для Сч = 0 По Matches.Count - 1 Цикл
        ЗначениеЭлемента = Matches.Item(Сч).Value;
        // Очищаем значение от внешних кавычек
        ЗначениеЭлемента = СтрЗаменить(ЗначениеЭлемента, """", "");
        Массив.Добавить(ЗначениеЭлемента);
    КонецЦикла;
    
    Возврат Массив;
КонецФункции

Выясним преимущества и недостатки данного метода:

Особенности и практические нюансы разбора CSV-файлов

При организации загрузки данных из сторонних текстовых документов необходимо учитывать следующие важные моменты:

  1. Пустые значения между разделителями: При посимвольном анализе обязательно проверяйте корректность обработки ситуаций вида "Товар",0,,"4606949031820", где присутствуют две запятые подряд без значений между ними.
  2. Экранирование кавычек внутри строк: Согласно стандарту CSV (RFC 4180), если внутри текстового поля встречается сам символ кавычки, он экранируется удвоением (""). При финальной очистке элементов массива заменяйте двойные кавычки "" на одиночные ".
  3. Удаление лишних символов: Заполняя реквизиты документов (наименование, артикул, цена, сумма), предварительно очищайте полученные значения функции СокрЛП и удаляйте обрамляющие кавычки.
← На главную