Как распарсить строку с наименованием, количеством, ценой и суммой в 1С

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

При интеграции 1С с внешними системами или при обработке текстовых данных часто возникает задача разбора (парсинга) сложных строк. Типичный пример — строка, в которой перемешаны текстовые и числовые данные, например: "Ветчина Мраморная вар. ПГН 400.00 x 0.83 = 332.00". Нам необходимо разложить эту информацию на четыре составляющие: Наименование, Цена, Количество и Сумма.

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

Метод 1: Разбор строки через массив с конца (универсальный способ)

Проанализируем структуру нашей строки. Мы видим, что в конце всегда идут числовые показатели, разделенные пробелами и символами «x» и «=». Если мы разделим строку по пробелам в массив, то нужные нам данные (сумма, количество, цена) всегда будут находиться на определенных позициях относительно конца массива. Это самый надежный способ, если формат «Цена x Кол-во = Сумма» строго соблюдается.

Разберем алгоритм по шагам:

  1. Разбиваем входную строку в массив, используя пробел в качестве разделителя.
  2. Извлекаем последние элементы: последний элемент — это сумма, третий с конца — количество, пятый с конца — цена.
  3. Удаляем эти элементы и символы-разделители («x», «=») из массива.
  4. Все элементы, оставшиеся в массиве, объединяем обратно в одну строку — это и будет наше полное наименование.

Реализуем этот алгоритм на языке 1С:


Функция РазобратьСтрокуЧерезМассив(ВхСтрока)
    // Разделяем строку по пробелам
    МассивСлов = СтрРазделить(ВхСтрока, " ", Ложь);
    МаксИндекс = МассивСлов.ВГраница();
    
    // Проверяем, достаточно ли элементов для разбора
    Если МаксИндекс < 5 Тогда
        Возврат Неопределено;
    КонецЕсли;

    // Извлекаем данные с конца массива
    Сумма = МассивСлов.Получить(МаксИндекс);
    Количество = МассивСлов.Получить(МаксИндекс - 2);
    Цена = МассивСлов.Получить(МаксИндекс - 4);
    
    // Удаляем из массива цену, "x", количество, "=" и сумму
    // Удаляем 5 раз элемент на позиции (МаксИндекс - 4)
    Для К = 1 По 5 Цикл
        МассивСлов.Удалить(МаксИндекс - 4);
    КонецЦикла;
    
    // Оставшиеся части соединяем в наименование
    Наименование = СтрСоединить(МассивСлов, " ");
    
    // Формируем результат
    Результат = Новый Структура;
    Результат.Вставить("Наименование", Наименование);
    Результат.Вставить("Цена", Цена);
    Результат.Вставить("Количество", Количество);
    Результат.Вставить("Сумма", Сумма);
    
    Возврат Результат;
КонецФункции

Метод 2: Использование регулярных выражений (RegExp)

Если в наименовании товара встречаются сложные символы или мы хотим добиться максимальной гибкости, стоит рассмотреть использование регулярных выражений. В 1С это реализуется через COM-объект VBScript.RegExp. Регулярное выражение позволяет описать шаблон строки целиком.

Рассмотрим шаблон: (^.+?) (\d+\.\d{2}) x (\d+\.\d{2,3}) = (\d+\.\d{2})$

Пример реализации с использованием регулярных выражений:


Функция РазобратьСтрокуRegExp(ВхСтрока)
    RegExp = Новый COMОбъект("VBScript.RegExp");
    RegExp.IgnoreCase = Истина;
    RegExp.Global = Ложь;
    // Шаблон учитывает возможную разную раскладку буквы х
    RegExp.Pattern = "(^.+?)\s+(\d+\.\d+)\s+[xх]\s+(\d+\.\d+)\s+=\s+(\d+\.\d+)";
    
    Matches = RegExp.Execute(ВхСтрока);
    
    Если Matches.Count > 0 Тогда
        Match = Matches.Item(0);
        Результат = Новый Структура;
        Результат.Вставить("Наименование", Match.SubMatches.Item(0));
        Результат.Вставить("Цена", Match.SubMatches.Item(1));
        Результат.Вставить("Количество", Match.SubMatches.Item(2));
        Результат.Вставить("Сумма", Match.SubMatches.Item(3));
        Возврат Результат;
    КонецЕсли;
    
    Возврат Неопределено;
КонецФункции

Метод 3: Поиск разделителей с конца строки

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

Выясним логику поиска: 1. Находим позицию последнего знака "=". Всё, что правее — Сумма. 2. Находим позицию символа "x" (или "х"), который стоит левее знака "=". Всё, что между ними — Количество. 3. Находим пробел перед символом "x". Всё, что между этим пробелом и "x" — Цена. 4. Всё, что левее цены — Наименование.

Важные нюансы при парсинге данных

При работе с реальными данными мы часто сталкиваемся с «грязными» строками. Разберем основные проблемы и способы их решения:

  1. Неразрывные пробелы. Часто при копировании из Excel или веб-страниц вместо обычного пробела (код 32) используется неразрывный пробел (код 160). Функция СтрРазделить с обычным пробелом его не увидит. Перед обработкой всегда делайте замену: Стр = СтрЗаменить(Стр, Символы.НПП, " ");
  2. Разделители дробной части. В строке может быть точка, а функция Число() в 1С может ожидать запятую в зависимости от региональных настроек сервера или клиента. Рекомендуется принудительно заменять точки на запятые перед преобразованием типа: ТекЦена = Число(СтрЗаменить(ЦенаИзСтроки, ".", ","));
  3. Математическая проверка. После завершения парсинга обязательно проверьте результат формулой Цена * Количество = Сумма. Это позволит отсечь строки, где парсер сработал некорректно из-за специфических названий товаров (например, если в названии товара есть конструкция типа "Винт 3x15").

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

← На главную