Как правильно выполнить поиск и замену текста в наименованиях номенклатуры через запрос 1С

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

При разработке обработок для массового изменения данных программисты часто сталкиваются с ситуацией, когда запрос отказывается работать или выдает ошибки при попытке отфильтровать данные. Одной из самых распространенных задач является поиск элементов справочника по части наименования с последующей заменой этой части на другой текст. Рассмотрим подробно, как правильно составить запрос, передать в него параметры и оптимизировать процесс записи объектов.

Разбор типичной ошибки: Не задано значение параметра

Проанализируем ситуацию, с которой столкнулся автор темы. При выполнении кода возникала ошибка: «Не задано значение параметра "ЗаменяемыйТекст"». Выясним причину этого поведения. В языке запросов 1С символом & обозначается параметр, значение которого должно быть обязательно передано в объект Запрос перед его выполнением. Если в тексте запроса указано ГДЕ Наименование ПОДОБНО &ЗаменяемыйТекст, но в коде отсутствует метод УстановитьПараметр("ЗаменяемыйТекст", Значение), система выдаст исключение.

Посмотрим на исправленный вариант инициализации запроса:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Родитель,
    |	Номенклатура.Наименование,
    |	Номенклатура.НаименованиеПолное,
    |	Номенклатура.Ссылка
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.Наименование ПОДОБНО &ЗаменяемыйТекст
    |	И Номенклатура.Родитель = &ВыборРодитель
    |	И НЕ Номенклатура.ЭтоГруппа";

Обратим внимание на важный нюанс, упомянутый в обсуждении: в секции ВЫБРАТЬ обязательно должно присутствовать поле Ссылка. Если мы планируем в дальнейшем изменять объект, нам необходимо получить его ссылку из выборки запроса. Без этого обращение Выборка.Ссылка.ПолучитьОбъект() будет невозможным.

Работа с оператором ПОДОБНО и спецсимволами

Оператор ПОДОБНО требует особого подхода к формированию параметров. Чтобы найти подстроку в любом месте наименования, значение параметра должно быть обрамлено символами процента %. Разберем по шагам, как правильно подготовить строку поиска:

  1. Символ % означает последовательность любых символов произвольной длины.
  2. Символ _ (подчеркивание) означает один произвольный символ.
  3. Если нам нужно найти вхождение текста в середине строки, мы должны передать параметр в виде "%Текст%".

Рассмотрим правильный пример установки параметров в коде 1С:


// Правильная подготовка строки для поиска подстроки
ЗначениеПараметра = "%" + ЗаменяемыйТекст + "%";
Запрос.УстановитьПараметр("ЗаменяемыйТекст", ЗначениеПараметра);
Запрос.УстановитьПараметр("ВыборРодитель", Родитель);

Важный совет: Если пользователь введет в поле поиска сам спецсимвол (например, знак процента), запрос может отработать некорректно. Для обработки таких случаев в языке запросов используется ключевое слово СПЕЦСИМВОЛ. Например: ПОДОБНО &Текст СПЕЦСИМВОЛ "~". Это позволит экранировать служебные знаки.

Алгоритм циклической замены и записи объектов

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

Проанализируем полный цикл обработки:


Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    // Получаем объект для редактирования
    ОбъектНоменклатура = Выборка.Ссылка.ПолучитьОбъект();
    
    // Выполняем замену в кратком и полном наименовании
    НовоеНаименование = СтрЗаменить(ОбъектНоменклатура.Наименование, ЗаменяемыйТекст, ТекстЗамены);
    
    // Проверим, действительно ли наименование изменилось, чтобы не перезаписывать лишний раз
    Если ОбъектНоменклатура.Наименование <> НовоеНаименование Тогда
        ОбъектНоменклатура.Наименование = НовоеНаименование;
        ОбъектНоменклатура.НаименованиеПолное = НовоеНаименование;
        
        Попытка
            ОбъектНоменклатура.Записать();
        Исключение
            Сообщить("Не удалось записать объект: " + ОбъектНоменклатура.Ссылка + " Ошибка: " + ОписаниеОшибки());
        КонецПопытки;
    КонецЕсли;
КонецЦикла;

Оптимизация производительности при массовых изменениях

Когда в справочнике «Номенклатура» десятки тысяч позиций, обычный цикл записи может работать крайне медленно. Проанализируем способы ускорения этой операции, которые помогут сэкономить время и ресурсы сервера.

  1. Использование иерархии: В исходном примере использовалось условие Родитель = &ВыборРодитель. Это найдет элементы только в корне выбранной папки. Если вам нужно обработать все вложенные подпапки, замените условие в запросе на В ИЕРАРХИИ (&ВыборРодитель).
  2. Режим загрузки данных: Установка свойства ОбменДанными.Загрузка = Истина перед записью объекта отключает тяжелые проверки в модуле объекта и подписках на события. Это значительно ускоряет процесс, но требует осторожности, так как бизнес-логика (например, контроль уникальности) не будет выполнена.
  3. Транзакции: Оберните весь цикл обработки в одну транзакцию. Это позволит СУБД записать данные в лог одним блоком, что в разы ускоряет работу на серверных базах данных.

Рассмотрим пример оптимизированного кода с транзакцией и режимом загрузки:


НачатьТранзакцию();

Пока Выборка.Следующий() Цикл
    Объект = Выборка.Ссылка.ПолучитьОбъект();
    Объект.Наименование = СтрЗаменить(Объект.Наименование, ЗаменяемыйТекст, Замена);
    
    // Отключаем лишние проверки для скорости
    Объект.ОбменДанными.Загрузка = Истина;
    
    Попытка
        Объект.Записать();
    Исключение
        ОтменитьТранзакцию();
        Сообщить("Критическая ошибка при записи, транзакция отменена!");
        Возврат;
    КонецПопытки;
КонецЦикла;

ЗафиксироватьТранзакцию();

Заключение и рекомендации

Подводя итог, отметим основные моменты, которые обеспечивают успех при работе с отборами в запросах 1С. Всегда следите за соответствием имен параметров в тексте запроса и в методе УстановитьПараметр. Помните, что оператор ПОДОБНО чувствителен к регистру в некоторых СУБД, а поиск с процентом в начале строки ("%Текст") не позволяет использовать индексы, что может замедлить работу базы.

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

← На главную