Как в 1С удалить текст после запятой или другого разделителя?

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

При выгрузке данных, обмене с внешними системами или формировании печатных форм разработчики часто сталкиваются с необходимостью обработать строковые данные. Типичный пример — когда в реквизите или представлении хранится объединенная информация (например, серия номенклатуры и срок годности через запятую: "010818, 31.08.2021"), а для выгрузки в XML требуется получить только первую часть строки до запятой.

В этой статье мы подробно разберем несколько способов решения этой задачи на платформе «1С:Предприятие 8», проанализируем их плюсы и минусы, оценим производительность и рассмотрим архитектурно правильный подход к получению таких данных.

Способ 1. Использование функций Лев() и СтрНайти() (Самый быстрый и надежный метод)

Этот способ основан на базовых функциях работы со строками. Мы находим позицию символа-разделителя в строке, а затем берем левую часть строки до этой позиции. Рассмотрим базовую реализацию:


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

Важные нюансы реализации:

  1. Проверка на наличие разделителя. В коде обязательно нужно использовать конструкцию Если ПозицияЗапятой > 0. Если в строке не окажется запятой, функция СтрНайти() вернет значение 0. Если передать его напрямую в функцию обрезки строк (как в выражении ПозицияЗапятой - 1), мы получим отрицательный индекс -1, что вызовет ошибку выполнения в старых версиях платформы или вернет пустую строку.
  2. Удаление лишних пробелов. После разделения строки по запятой в конце первой части или в начале второй могут остаться нежелательные пробелы. Чтобы результат был чистым, рекомендуется всегда использовать функцию СокрЛП() (сокращение незначащих левых и правых пробелов).

Для компактности этот алгоритм можно записать с использованием тернарного оператора:


СтрокаСерии = Строка(Выборка.Серия);
Позиция = СтрНайти(СтрокаСерии, ",");
СерияДляВыгрузки = СокрЛП(?(Позиция = 0, СтрокаСерии, Лев(СтрокаСерии, Позиция - 1)));

Способ 2. Использование платформенной функции СтрРазделить()

Начиная с версии платформы 8.3.6, в 1С доступна удобная встроенная функция СтрРазделить(), которая разбивает исходную строку на массив подстрок по указанному разделителю.

Рассмотрим, как применить ее для нашей задачи:


СтрокаСерии = Строка(Выборка.Серия);
ЧастиСтроки = СтрРазделить(СтрокаСерии, ",");
Если ЧастиСтроки.Количество() > 0 Тогда
    СерияДляВыгрузки = СокрЛП(ЧастиСтроки[0]);
Иначе
    СерияДляВыгрузки = "";
КонецЕсли;

Подводные камни функции СтрРазделить():

Способ 3. Использование функций БСП для сложных разделителей

Если вам требуется корректно разделить строку по многосимвольному разделителю (например, строго по комбинации «запятая + пробел» ", "), стандартная функция СтрРазделить() не подойдет. В этом случае на помощь приходит Библиотека Стандартных Подсистем (БСП), которая интегрирована практически во все типовые конфигурации 1С.

Мы можем использовать функцию из общего модуля СтроковыеФункцииКлиентСервер:


СтрокаСерии = Строка(Выборка.Серия);
МассивЧастей = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(СтрокаСерии, ", ");
Если МассивЧастей.Количество() > 0 Тогда
    СерияДляВыгрузки = МассивЧастей[0];
Иначе
    СерияДляВыгрузки = "";
КонецЕсли;

Этот метод полностью безопасен, корректно обрабатывает многосимвольные разделители целиком и работает на любых версиях платформы 1С.

Способ 4. Метод замены символов (Перевод в многострочную строку)

Еще один интересный и лаконичный способ — временное превращение обычной строки в многострочную путем замены разделителя на символ перевода строки (Символы.ПС). После этого мы можем легко прочитать первую строку.


СтрокаСерии = Строка(Выборка.Серия);
МногострочныйТекст = СтрЗаменить(СтрокаСерии, ",", Символы.ПС);
СерияДляВыгрузки = СокрЛП(СтрПолучитьСтроку(МногострочныйТекст, 1));

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

Сравнение производительности методов

Если вы обрабатываете небольшой объем данных (например, при сохранении одной формы), разница в скорости работы алгоритмов будет незаметна. Однако, если выполняется выгрузка сотен тысяч позиций номенклатуры в XML-файл, производительность строковых функций становится критически важной.

Проанализируем работу механизмов платформы при больших нагрузках:

Вывод: Для оптимизации производительности в высоконагруженных циклах обмена данными всегда выбирайте связку Лев() и СтрНайти() с проверкой на вхождение символа.

Архитектурная альтернатива: Решение проблемы на уровне запроса

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

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

Вместо того чтобы парсить готовую строку в коде выгрузки, правильнее изменить сам запрос и получить чистое значение номера серии напрямую из реквизита объекта:


ВЫБРАТЬ
    ТаблицаТовары.Номенклатура КАК Номенклатура,
    ТаблицаТовары.Серия.Номер КАК НомерСерии, // Получаем чистый номер серии
    ТаблицаТовары.Серия.СрокГодности КАК СрокГодности
ИЗ
    Документ.РеализацияТоваровУслуг.Товары КАК ТаблицаТовары
ГДЕ
    Ссылка = &Ссылка

При таком подходе в выборку запроса попадет чистое значение серии. В коде выгрузки XML вам больше не понадобятся функции обработки строк, а код станет максимально простым, быстрым и устойчивым к изменениям:


ЗаписьXML.ЗаписатьНачалоЭлемента("SERIES");
ЗаписьXML.ЗаписатьТекст(СокрЛП(Выборка.НомерСерии));
ЗаписьXML.ЗаписатьКонецЭлемента();
← На главную