Как в 1С убрать последние два символа или скрыть цифры в конце наименования номенклатуры?

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

В практике разработки на платформе 1С:Предприятие часто возникает задача предварительной обработки текстовых данных. Типичный пример — необходимость обрезать технические суффиксы, лишние знаки или числовые коды в конце наименования товаров при выводе их в печатные формы (макеты) или при выгрузке во внешние системы. Например, когда в справочнике хранится наименование "Продукция 21", а в макете необходимо вывести просто "Продукция".

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

Способ 1. Использование классических функций Лев() и СтрДлина()

Это самый популярный и простой способ, который работает на абсолютно любой версии платформы 1С:Предприятие (включая старые релизы 7.7 и 8.0). Он идеально подходит, если вам нужно строго отсечь ровно два последних символа от строки.

Рассмотрим пример реализации этого алгоритма:


// Очищаем строку от случайных пробелов на концах
НаименованиеОчищенное = СокрЛП(Номенклатура.Наименование);
ДлинаСтроки = СтрДлина(НаименованиеОчищенное);

Если ДлинаСтроки > 2 Тогда
    Результат = Лев(НаименованиеОчищенное, ДлинаСтроки - 2);
Иначе
    Результат = ""; // Если строка изначально была слишком короткой
КонецЕсли;

Разберем по шагам, как работает данный код:

  1. Сначала мы применяем функцию СокрЛП(). Это критически важно! Если в конце строки будут находиться невидимые символы пробела (например, "Товар "), функция без предварительной очистки отрежет именно эти пробелы, оставив значащие символы нетронутыми.
  2. Затем с помощью функции СтрДлина() мы вычисляем общее количество символов в строке.
  3. Перед вырезанием подстроки мы обязательно добавляем проверку Если ДлинаСтроки > 2. Если этого не сделать, и в функцию Лев() передать отрицательное число в качестве второго параметра, система вызовет ошибку времени выполнения (Run-time error).
  4. Функция Лев() возвращает указанное количество символов с левой стороны строки.

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

Альтернативный классический вариант — использование встроенной функции Сред(). По своей логике он аналогичен первому методу, но некоторым разработчикам такой синтаксис кажется более лаконичным:


НаименованиеОчищенное = СокрЛП(Номенклатура.Наименование);
ДлинаСтроки = СтрДлина(НаименованиеОчищенное);

Если ДлинаСтроки > 2 Тогда
    Результат = Сред(НаименованиеОчищенное, 1, ДлинаСтроки - 2);
Иначе
    Результат = "";
КонецЕсли;

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

Опасные ловушки: почему СтрЗаменить() использовать нельзя?

Начинающие программисты часто пытаются применить функцию СтрЗаменить() для удаления символов с конца строки. Рассмотрим пример опасного кода, который часто предлагают на форумах:


// ВНИМАНИЕ: Опасный код с багом!
Результат = СтрЗаменить(Наименование, Прав(Наименование, 2), "");

Проанализируем ситуацию и выясним, почему этот код категорически нельзя использовать в реальных базах данных. Функция Прав(Наименование, 2) действительно возвращает последние два символа. Однако функция СтрЗаменить() заменяет все вхождения этой подстроки во всей строке, а не только в конце!

Рассмотрим живой пример:

Еще одна грубая ошибка — последовательная замена цифр (попытка удалить числовой суффикс через массовую замену символов от "0" до "9"):


// ВНИМАНИЕ: Крайне неэффективный и опасный код!
Результат = СтрЗаменить(Наименование, "1", "");
Результат = СтрЗаменить(Результат, "2", ""); // и так далее до 0...

Этот подход полностью разрушит наименования, содержащие важные цифры внутри текста. Например, номенклатура "Кабель 3х1.5 мм 21" превратится в бесполезную строку "Кабель х. мм ". Кроме того, совершать 10 тяжелых вызовов строковых функций для обработки одной записи — это крайне неоптимально с точки зрения производительности.

Способ 3. Удаление произвольных числовых суффиксов и пробелов в цикле

Вернемся к задаче автора: убрать цифры и возможные пробелы только в конце наименования (например, преобразовать "Продукция 21" или "Продукция 21 " в "Продукция"). Если вы работаете на платформе ниже версии 8.3.23, наиболее надежным решением будет обход строки с конца в цикле.

Разберем по шагам готовую функцию, которая решает эту задачу:


Функция ПолучитьНаименованиеБезЧисловогоСуффикса(Знач ИсходноеНаименование) Экспорт
    
    Длина = СтрДлина(ИсходноеНаименование);
    НоваяДлина = Длина;
    
    // Перебираем строку с конца к началу
    Для НомерСимвола = -Длина По -1 Цикл
        
        ИндексСимвола = -НомерСимвола;
        КодТекущегоСимвола = КодСимвола(Сред(ИсходноеНаименование, ИндексСимвола, 1));
        
        // КодСимвола = 32 (пробел)
        // КодыСимволов от 48 до 57 (цифры от 0 до 9)
        Если КодТекущегоСимвола = 32 Или (КодТекущегоСимвола >= 48 И КодТекущегоСимвола <= 57) Тогда
            НоваяДлина = НоваяДлина - 1;
        Иначе
            Прервать; // Как только встретили букву, останавливаемся
        КонецЕсли;
        
    КонецЦикла;
    
    Возврат Лев(ИсходноеНаименование, НоваяДлина);
    
КонецФункции

Этот алгоритм гарантирует полную безопасность данных: любые цифры, находящиеся внутри названия товара, останутся нетронутыми, а все лишние символы (пробелы и цифры) на конце будут аккуратно отсечены.

Способ 4. Современное решение: Регулярные выражения в 1С (Платформа 8.3.23+)

Начиная с версии платформы 8.3.23, в 1С появилась встроенная нативная поддержка регулярных выражений (RegExp). Теперь сложные циклы и посимвольный анализ больше не нужны. Регулярные выражения работают на уровне ядра платформы, выполняются мгновенно и кроссплатформенно (как на Windows, так и на Linux-серверах).

Для нашей задачи регулярные выражения подходят идеально.

Вариант А: Отрезать ровно 2 последних символа


// Шаблон "..$" означает любые два символа в самом конце строки
Результат = СтрЗаменитьПоРегулярномуВыражению(Номенклатура.Наименование, "..$", "");

Вариант Б: Удалить любые цифры и пробелы строго в конце строки


// Шаблон "[\s\d]+$" находит любые комбинации цифр (\d) и пробелов (\s) в конце строки ($)
Результат = СтрЗаменитьПоРегулярномуВыражению(Номенклатура.Наименование, "[\s\d]+$", "");

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

Способ 5. Использование готовых функций БСП

Если вы разрабатываете решение в среде типовой конфигурации (например, 1С:Управление торговлей, 1С:ERP, Бухгалтерия предприятия), то в вашем распоряжении по умолчанию есть Библиотека Стандартных Подсистем (БСП). Писать "велосипеды" в таком случае не нужно.

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


Наименование = Номенклатура.Наименование;
// Функция безопасно удалит 2 последних символа
Результат = СтроковыеФункцииКлиентСервер.УдалитьПоследнийСимволВСтроке(Наименование, 2);

Применение готовых функций БСП снижает количество потенциальных ошибок в коде и упрощает последующую поддержку и обновление конфигурации.

Почему не стоит решать эту задачу в запросе?

В рамках обсуждения на форуме прозвучало предложение использовать конструкцию ВЫРАЗИТЬ() в запросе (Сообщение 5) для усечения длины. Выясним, почему этот подход ошибочен:

  1. Конструкция ВЫРАЗИТЬ(Номенклатура.Наименование КАК СТРОКА(98)) не обрезает строку переменной длины на 2 символа. Если длина строки меньше 98 символов, СУБД вернет ее без изменений. Если же строка приводится к фиксированной длине, СУБД просто дополнит результат пробелами справа.
  2. В языке запросов 1С отсутствует функция получения длины строки (аналог СтрДлина()). Из-за этого динамически вычислить позицию обрезки на уровне СУБД стандартными средствами невозможно.

Форматирование строк и изменение их структуры — это классическая задача программного кода (на клиенте или сервере приложений), а не СУБД. Оставьте запросам выборку данных, а обработку строк выполняйте с помощью рассмотренных выше методов.

← На главную