При разработке обработок для массового изменения данных программисты часто сталкиваются с ситуацией, когда запрос отказывается работать или выдает ошибки при попытке отфильтровать данные. Одной из самых распространенных задач является поиск элементов справочника по части наименования с последующей заменой этой части на другой текст. Рассмотрим подробно, как правильно составить запрос, передать в него параметры и оптимизировать процесс записи объектов.
Проанализируем ситуацию, с которой столкнулся автор темы. При выполнении кода возникала ошибка: «Не задано значение параметра "ЗаменяемыйТекст"». Выясним причину этого поведения. В языке запросов 1С символом & обозначается параметр, значение которого должно быть обязательно передано в объект Запрос перед его выполнением. Если в тексте запроса указано ГДЕ Наименование ПОДОБНО &ЗаменяемыйТекст, но в коде отсутствует метод УстановитьПараметр("ЗаменяемыйТекст", Значение), система выдаст исключение.
Посмотрим на исправленный вариант инициализации запроса:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Родитель,
| Номенклатура.Наименование,
| Номенклатура.НаименованиеПолное,
| Номенклатура.Ссылка
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Наименование ПОДОБНО &ЗаменяемыйТекст
| И Номенклатура.Родитель = &ВыборРодитель
| И НЕ Номенклатура.ЭтоГруппа";
Обратим внимание на важный нюанс, упомянутый в обсуждении: в секции ВЫБРАТЬ обязательно должно присутствовать поле Ссылка. Если мы планируем в дальнейшем изменять объект, нам необходимо получить его ссылку из выборки запроса. Без этого обращение Выборка.Ссылка.ПолучитьОбъект() будет невозможным.
Оператор ПОДОБНО требует особого подхода к формированию параметров. Чтобы найти подстроку в любом месте наименования, значение параметра должно быть обрамлено символами процента %. Разберем по шагам, как правильно подготовить строку поиска:
% означает последовательность любых символов произвольной длины._ (подчеркивание) означает один произвольный символ."%Текст%".Рассмотрим правильный пример установки параметров в коде 1С:
// Правильная подготовка строки для поиска подстроки
ЗначениеПараметра = "%" + ЗаменяемыйТекст + "%";
Запрос.УстановитьПараметр("ЗаменяемыйТекст", ЗначениеПараметра);
Запрос.УстановитьПараметр("ВыборРодитель", Родитель);
Важный совет: Если пользователь введет в поле поиска сам спецсимвол (например, знак процента), запрос может отработать некорректно. Для обработки таких случаев в языке запросов используется ключевое слово СПЕЦСИМВОЛ. Например: ПОДОБНО &Текст СПЕЦСИМВОЛ "~". Это позволит экранировать служебные знаки.
После того как мы получили выборку подходящих элементов, необходимо программно изменить их реквизиты. Разберем процесс трансформации данных. Для изменения объекта мы используем метод ПолучитьОбъект(), выполняем замену текста функцией СтрЗаменить() и фиксируем изменения методом Записать().
Проанализируем полный цикл обработки:
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Получаем объект для редактирования
ОбъектНоменклатура = Выборка.Ссылка.ПолучитьОбъект();
// Выполняем замену в кратком и полном наименовании
НовоеНаименование = СтрЗаменить(ОбъектНоменклатура.Наименование, ЗаменяемыйТекст, ТекстЗамены);
// Проверим, действительно ли наименование изменилось, чтобы не перезаписывать лишний раз
Если ОбъектНоменклатура.Наименование <> НовоеНаименование Тогда
ОбъектНоменклатура.Наименование = НовоеНаименование;
ОбъектНоменклатура.НаименованиеПолное = НовоеНаименование;
Попытка
ОбъектНоменклатура.Записать();
Исключение
Сообщить("Не удалось записать объект: " + ОбъектНоменклатура.Ссылка + " Ошибка: " + ОписаниеОшибки());
КонецПопытки;
КонецЕсли;
КонецЦикла;
Когда в справочнике «Номенклатура» десятки тысяч позиций, обычный цикл записи может работать крайне медленно. Проанализируем способы ускорения этой операции, которые помогут сэкономить время и ресурсы сервера.
Родитель = &ВыборРодитель. Это найдет элементы только в корне выбранной папки. Если вам нужно обработать все вложенные подпапки, замените условие в запросе на В ИЕРАРХИИ (&ВыборРодитель).ОбменДанными.Загрузка = Истина перед записью объекта отключает тяжелые проверки в модуле объекта и подписках на события. Это значительно ускоряет процесс, но требует осторожности, так как бизнес-логика (например, контроль уникальности) не будет выполнена.Рассмотрим пример оптимизированного кода с транзакцией и режимом загрузки:
НачатьТранзакцию();
Пока Выборка.Следующий() Цикл
Объект = Выборка.Ссылка.ПолучитьОбъект();
Объект.Наименование = СтрЗаменить(Объект.Наименование, ЗаменяемыйТекст, Замена);
// Отключаем лишние проверки для скорости
Объект.ОбменДанными.Загрузка = Истина;
Попытка
Объект.Записать();
Исключение
ОтменитьТранзакцию();
Сообщить("Критическая ошибка при записи, транзакция отменена!");
Возврат;
КонецПопытки;
КонецЦикла;
ЗафиксироватьТранзакцию();
Подводя итог, отметим основные моменты, которые обеспечивают успех при работе с отборами в запросах 1С. Всегда следите за соответствием имен параметров в тексте запроса и в методе УстановитьПараметр. Помните, что оператор ПОДОБНО чувствителен к регистру в некоторых СУБД, а поиск с процентом в начале строки ("%Текст") не позволяет использовать индексы, что может замедлить работу базы.
Для небольших баз данных предложенный метод замены через ПолучитьОбъект() является оптимальным. Однако для высоконагруженных систем рекомендуется также внедрять механизмы блокировок данных, чтобы избежать конфликтов между пользователями в момент массовой модификации справочников.