В типовых конфигурациях 1С (особенно в старых редакциях «Управление торговлей» или «Бухгалтерия предприятия») часто встречается ситуация, когда в печатных формах или при выгрузке данных наименование товара, номер ГТД и страна происхождения «склеиваются» в одну строку. Обычно это выглядит так: «Наименование товара (Номер ГТД, Страна)». Перед программистом встает задача: корректно разделить эту строку на три составляющие, сохранив чистое наименование и выделив реквизиты для дальнейшего учета.
В этой статье мы разберем несколько подходов к решению задачи — от классических строковых функций до использования регулярных выражений, а также проанализируем структуру номера ГТД и возможные «подводные камни» при парсинге.
Прежде чем приступать к написанию кода, проанализируем типичные примеры строк, с которыми приходится работать:
Корпус системного блока ПК ZALMAN Z1 NEO (10702070/130618/0078002/1, КИТАЙ)Акустическая система MICROLAB М-109 (10W RMS) (10702070/010618/0072070/7, КИТАЙ)Обратим внимание на второй пример: наименование может само по себе содержать скобки. Это означает, что простой поиск первой открывающей скобки слева не сработает. Нам нужно ориентироваться на последний блок скобок, который 1С традиционно добавляет в конец строки.
Этот метод является наиболее универсальным для старых версий платформы и не требует использования внешних библиотек. Рассмотрим поэтапно решение трех задач: получение названия, ГТД и страны.
Задача А: Получение чистого наименования
Логика проста: нам нужно найти позицию последней открывающей скобки и отсечь всё, что идет после неё. Разберем код:
// Исходная строка из накладной
ИсходнаяСтрока = "Корпус системного блока ПК ZALMAN Z1 (10702070/130618/0078002/1, КИТАЙ)";
// Ищем открывающую скобку именно С КОНЦА строки
ПозицияСкобки = СтрНайти(ИсходнаяСтрока, "(", НаправлениеПоиска.СКонца);
Если ПозицияСкобки > 0 Тогда
// Отсекаем хвост и удаляем лишние пробелы по краям
ЧистоеНаименование = СокрЛП(Лев(ИсходнаяСтрока, ПозицияСкобки - 1));
Иначе
ЧистоеНаименование = ИсходнаяСтрока;
КонецЕсли;
Задача Б: Извлечение ГТД и страны
После того как мы определили положение последней скобки, мы можем извлечь содержимое внутри скобок и разделить его по запятой. Рассмотрим, как это сделать элегантно:
// Получаем содержимое внутри скобок
ДлинаХвоста = СтрДлина(ИсходнаяСтрока) - ПозицияСкобки;
СодержимоеСкобок = Сред(ИсходнаяСтрока, ПозицияСкобки + 1, ДлинаХвоста - 1); // Убираем закрывающую скобку
// Разделяем по запятой
МассивЧастей = СтрРазделить(СодержимоеСкобок, ",");
Если МассивЧастей.Количество() >= 2 Тогда
НомерГТД = СокрЛП(МассивЧастей[0]);
СтранаПроисхождения = СокрЛП(МассивЧастей[1]);
КонецЕсли;
Этот метод удобен, если формат строки строго фиксирован и в конце всегда идет «(ГТД, СТРАНА)». Мы можем разбить всю строку на массив слов, используя пробел как разделитель, и манипулировать последними элементами. Однако, как мы выяснили выше, это менее надежно, если в наименовании есть запятые или специфические символы.
Рассмотрим пример очистки наименования через удаление последних элементов массива:
МассивВсехСлов = СтрРазделить(ИсходнаяСтрока, " ");
// Предполагаем, что ГТД и Страна — это последние "слова" в скобках
Если МассивВсехСлов.Количество() > 2 Тогда
МассивВсехСлов.Удалить(МассивВсехСлов.Количество() - 1); // Удаляем страну
МассивВсехСлов.Удалить(МассивВсехСлов.Количество() - 1); // Удаляем ГТД
Результат = СтрСоединить(МассивВсехСлов, " ");
КонецЕсли;
Важно: Этот метод крайне хрупок. Если в названии страны есть пробел (например, «ЮЖНАЯ АФРИКА»), алгоритм даст сбой. Поэтому рекомендуется использовать Способ 1.
Если ваша платформа 1С версии 8.3.24 и выше, вам доступна нативная поддержка регулярных выражений. Это самый «красивый» и профессиональный способ решения задачи. Выясним, как составить паттерн для поиска.
Для поиска ГТД и страны в конце строки подойдет паттерн: \((.*),\s*(.*)\)$
Разберем, как применить это в коде 1С:
// Пример для платформы 8.3.24+
ТекстДляПоиска = "Активная акустическая система (10W RMS) (10702070/010618/0078002/1, КИТАЙ)";
Шаблон = "\(([^,]+),\s*([^)]+)\)$";
РегВыр = Новый РегулярноеВыражение(Шаблон);
Результат = РегВыр.Найти(ТекстДляПоиска);
Если Результат.Количество() > 0 Тогда
ГруппаГТД = Результат[0].Группы[1]; // Первая захваченная группа
ГруппаСтрана = Результат[0].Группы[2]; // Вторая захваченная группа
НомерГТД = ГруппаГТД.Значение;
Страна = ГруппаСтрана.Значение;
// Очистка наименования - удаляем всё найденное выражение из исходной строки
ЧистоеНаименование = СокрЛП(СтрЗаменить(ТекстДляПоиска, Результат[0].Значение, ""));
КонецЕсли;
Проанализируем структуру ГТД (декларации на товары), чтобы ваша проверка была максимально точной. Настоящий номер ГТД состоит из трех (иногда четырех) блоков, разделенных косой чертой (слешем): XXXXXXXX/XXXXXX/XXXXXXX/XX
При распознавании стоит учитывать, что некоторые поставщики могут ошибаться в количестве знаков или использовать разделители, отличные от слеша, хотя это и является нарушением правил заполнения счетов-фактур.
Выделение страны — задача не менее ответственная. Проанализируем возможные проблемы:
КлассификаторСтранМира.СтрЗаменить(Страна, Символ(160), " ").Для реализации максимально надежного алгоритма мы рекомендуем придерживаться следующей последовательности действий:
??/??/??. Если маска не совпадает, возможно, в скобках указана только страна или иная информация (например, серийный номер), и такие случаи нужно обрабатывать отдельно или выводить пользователю для ручного уточнения.Такой подход обеспечит чистоту вашей базы данных и корректное формирование отчетности по импортным товарам и прослеживаемости.