При загрузке номенклатуры из файлов поставщиков в 1С:Предприятие 7.7 часто приходится извлекать характеристики товаров (размеры, рост, линейные габариты) непосредственно из текстовых описаний или наименований. Когда в номенклатурный ряд добавляются новые категории товаров — например, домашний текстиль (одеяла, пледы) вместо одежды — существующие алгоритмы разбора могут давать сбой.
Разберем типичные ошибки, возникающие при обработке строковых данных, и рассмотрим правильные варианты реализации поиска с помощью регулярных выражений и встроенных строковых функций.
Проанализируем типовой фрагмент кода, предназначенный для разбора размеров одежды:
Таблица.Размер = СтрЗаменить(УбратьНечисловые(Поиск(Значение1, "(\рост\s*)\d{1,}[\S]\d{1,}")), "-", ",") + "-" + УбратьНечисловые(Поиск(Значение1, "(размер\s*)\d{2,3}"));
При обработке позиций вида «Одеяло 205х148» в такой логике возникают следующие проблемы:
0 или пустую строку, в результирующее поле попадает некорректное значение (например, 0-205).УбратьНечисловые удаляют символ умножения (*, х, x), превращая габариты 205*148 в слитное число 205148.В платформе 1С 7.7 нет встроенного механизма регулярных выражений, поэтому для парсинга традиционно используется COM-объект VBScript.RegExp. Чтобы не зачищать найденные подстроки дополнительными функциями, правильнее сразу извлекать нужные компоненты с помощью групп захвата (круглые скобки () и свойство SubMatches).
Разберем по шагам алгоритм универсального разбора строки:
Рег = СоздатьОбъект("VBScript.RegExp");
Рег.IgnoreCase = 1;
Рег.Global = 0;
СтрДляПоиска = СокрЛП(Значение1);
// 1. Проверяем наличие линейных габаритов (текстиль, одеяла: 205х148, 205*148)
Рег.Pattern = "(\d{2,4})\s*[*xхXХ×]\s*(\d{2,4})";
Коллекция = Рег.Execute(СтрДляПоиска);
Если Коллекция.Count > 0 Тогда
Матч = Коллекция.Item(0);
// Формируем размер в формате Длина*Ширина
Таблица.Размер = Матч.SubMatches(0) + "*" + Матч.SubMatches(1);
Иначе
// 2. Если габариты не найдены, выполняем поиск характеристик одежды (рост и размер)
Рег.Pattern = "(?:рост\s*)(\d{2,3}(?:[-,]\d{2,3})?)";
КоллекцияРост = Рег.Execute(СтрДляПоиска);
ЗначРост = "";
Если КоллекцияРост.Count > 0 Тогда
ЗначРост = СтрЗаменить(КоллекцияРост.Item(0).SubMatches(0), "-", ",");
КонецЕсли;
Рег.Pattern = "(?:размер\s*)(\d{2,3})";
КоллекцияРазм = Рег.Execute(СтрДляПоиска);
ЗначРазм = "";
Если КоллекцияРазм.Count > 0 Тогда
ЗначРазм = КоллекцияРазм.Item(0).SubMatches(0);
КонецЕсли;
// 3. Формируем итоговую строку размера
Если (ПустаяСтрока(ЗначРост) = 0) И (ПустаяСтрока(ЗначРазм) = 0) Тогда
Таблица.Размер = ЗначРост + "-" + ЗначРазм;
Иначе
Таблица.Размер = СокрЛП(ЗначРост + ЗначРазм);
КонецЕсли;
КонецЕсли;
Посмотрим на особенности этого шаблона:
(\d{2,4})\s*[*xхXХ×]\s*(\d{2,4}) захватывает от 2 до 4 цифр первого измерения, учитывает возможные пробелы, распознает русскую «х», латинскую «x», знак «*» и символ «×», после чего захватывает второе измерение.(?:...) выполняет сопоставление без создания группы захвата, что позволяет извлекать через SubMatches(0) только само числовое значение без ключевых слов «рост» или «размер».Если в файле Excel разделители и регистр символов сильно различаются, перед запуском поиска целесообразно выполнить предварительную подготовку строки стандартными функциями 1С 7.7:
Стр = НРег(СокрЛП(Значение1));
// Заменяем латинскую 'x' и типографский знак на русскую 'х'
Стр = СтрЗаменить(Стр, "x", "х");
Стр = СтрЗаменить(Стр, "*", "х");
После такой нормализации в регулярных выражениях можно использовать единый символ-разделитель, что упрощает и ускоряет разбор.
Если по соображениям переносимости или стабильности требуется отказаться от внешнего объекта VBScript.RegExp, можно реализовать разбор габаритов через позиционный поиск символов разделителя:
Функция ИзвлечьГабариты(Знач ИсходнаяСтрока)
ИсходнаяСтрока = НРег(ИсходнаяСтрока);
ИсходнаяСтрока = СтрЗаменить(ИсходнаяСтрока, "x", "х");
ИсходнаяСтрока = СтрЗаменить(ИсходнаяСтрока, "*", "х");
Поз = Найти(ИсходнаяСтрока, "х");
Если Поз = 0 Тогда
Возврат "";
КонецЕсли;
// Выделяем числа слева и справа от разделителя
СтрСлева = СокрЛП(Лев(ИсходнаяСтрока, Поз - 1));
СтрСправа = СокрЛП(Сред(ИсходнаяСтрока, Поз + 1));
// Получаем последние цифры из левой части
Числ1 = "";
Для Индекс = 1 По СтрДлина(СтрСлева) Цикл
Симв = Сред(СтрСлева, СтрДлина(СтрСлева) - Индекс + 1, 1);
Если (Симв >= "0") И (Симв <= "9") Тогда
Числ1 = Симв + Числ1;
Иначе
Если ПустаяСтрока(Числ1) = 0 Тогда
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
// Получаем первые цифры из правой части
Числ2 = "";
Для Индекс = 1 По СтрДлина(СтрСправа) Цикл
Симв = Сред(СтрСправа, Индекс, 1);
Если (Симв >= "0") И (Симв <= "9") Тогда
Числ2 = Числ2 + Симв;
Иначе
Прервать;
КонецЕсли;
КонецЦикла;
Если (ПустаяСтрока(Числ1) = 0) И (ПустаяСтрока(Числ2) = 0) Тогда
Возврат Числ1 + "*" + Числ2;
КонецЕсли;
Возврат "";
КонецФункции
Такой подход полностью автономен, не зависит от сторонних библиотек операционной системы и корректно формирует размеры вида 205*148 для текстильных изделий.