При разработке и доработке форм подбора номенклатуры в типовых конфигурациях (например, в «1С:Управление торговлей 11», «1С:Комплексная автоматизация» или «1С:ERP») разработчики часто сталкиваются с задачей организации быстрого поиска товаров по наименованиям их характеристик прямо в основном динамическом списке номенклатуры.
Пользователю удобно ввести часть названия характеристики (например, цвет краски или размер обуви) в единую строку поиска и сразу увидеть все подходящие позиции номенклатуры. Разберем, с какими платформенными ограничениями мы сталкиваемся и как правильно реализовать такое решение.
Прежде чем перейти к архитектурным вариантам решения, рассмотрим, почему стандартные подходы не работают напрямую:
STRING_AGG или GROUP_CONCAT. Мы не можем одним запросом сгруппировать строки подчиненного справочника ХарактеристикиНоменклатуры и объединить их в одну текстовую строку через запятую.ПриПолученииДанныхНаСервере: Обработчик динамического списка позволяет заполнить ячейку для отображения на клиенте, однако платформа не строит индексы по таким виртуальным колонкам и не может применить к ним условие ГДЕ. Соответственно, штатный поиск по такой вычисляемой колонке работать не будет.зелен*) не найдет совпадений.Разберем наиболее производительный и надежный способ — хранение предварительно подготовленной строки всех характеристик номенклатуры в отдельном регистре сведений с последующим соединением в запросе динамического списка.
Шаг 1. Создание структуры регистра сведений
Создадим непериодический независимый регистр сведений, например, ХарактеристикиНоменклатурыСтрокой:
Номенклатура (Тип: СправочникСсылка.Номенклатура, Ведущее: Истина).СписокХарактеристик (Тип: Строка неограниченной длины или фиксированной, например, 1000 символов).Шаг 2. Обновление данных через подписки на события
Чтобы не блокировать и не перезаписывать сам элемент справочника Номенклатура, используем подписки на события справочника ХарактеристикиНоменклатуры — ПриЗаписи и ПередУдалением. При изменении любой характеристики формируется актуальная строка со всеми характеристиками товара и записывается в регистр.
Посмотрим на пример процедуры обновления данных в регистре:
Процедура ОбновитьСписокХарактеристикНоменклатуры(СсылкаНаНоменклатуру) Экспорт
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Характеристики.Наименование КАК Наименование
|ИЗ
| Справочник.ХарактеристикиНоменклатуры КАК Характеристики
|ГДЕ
| Характеристики.Владелец = &Номенклатура
| И НЕ Характеристики.ПометкаУдаления";
Запрос.УстановитьПараметр("Номенклатура", СсылкаНаНоменклатуру);
Выборка = Запрос.Выполнить().Выбрать();
МассивИмен = Новый Массив;
Пока Выборка.Следующий() Цикл
МассивИмен.Добавить(СокрЛП(Выборка.Наименование));
КонецЦикла;
СтрокаХарактеристик = СтрСоединить(МассивИмен, ", ");
МенеджерЗаписи = РегистрыСведений.ХарактеристикиНоменклатурыСтрокой.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Номенклатура = СсылкаНаНоменклатуру;
Если ЗначениеЗаполнено(СтрокаХарактеристик) Тогда
МенеджерЗаписи.СписокХарактеристик = СтрокаХарактеристик;
МенеджерЗаписи.Записать(Истина);
Иначе
// Если характеристик больше нет, удаляем запись
МенеджерЗаписи.Прочитать();
Если МенеджерЗаписи.Выбран() Тогда
МенеджерЗаписи.Удалить();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Важный нюанс для УТ 11, КА и ERP: В типовых конфигурациях характеристики могут быть привязаны не только к конкретной номенклатуре, но и к объекту ВидНоменклатуры (общие характеристики). Если в базе используются общие характеристики, алгоритм при изменении характеристики должен обновлять записи регистра для всех позиций номенклатуры соответствующего вида.
Шаг 3. Доработка запроса динамического списка
В тексте запроса динамического списка связываем основную таблицу номенклатуры с созданным регистром сведений через ЛЕВОЕ СОЕДИНЕНИЕ:
ВЫБРАТЬ
СпрНоменклатура.Ссылка КАК Ссылка,
СпрНоменклатура.Наименование КАК Наименование,
СпрНоменклатура.Артикул КАК Артикул,
ЕСТЬNULL(РегХарактеристики.СписокХарактеристик, "") КАК ХарактеристикиСтрокой
ИЗ
Справочник.Номенклатура КАК СпрНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ХарактеристикиНоменклатурыСтрокой КАК РегХарактеристики
ПО СпрНоменклатура.Ссылка = РегХарактеристики.Номенклатура
Поле ХарактеристикиСтрокой добавляется в пользовательские поля или на форму (при необходимости его можно сделать невидимым, но включенным в состав данных), после чего стандартная строка поиска и отборы динамического списка смогут полноценно искать номенклатуру по тексту характеристик.
Если нет возможности изменять структуру конфигурации и добавлять новые объекты метаданных, рассмотрим способ с динамической фильтрацией списка через код формы:
ХарактеристикиНоменклатуры с условием Наименование ПОДОБНО &СтрокаПоиска.Ссылка В (&МассивСсылок) или объединяем отбор по номенклатуре с отбором по ее собственному наименованию.Если используется механизм полнотекстового поиска, пользователям часто неудобно вводить спецсимволы масок (*, !). Чтобы решить эту проблему, перехватим строку перед отправкой в поиск и модифицируем её программно:
// Разбиваем введенный пользователем текст на отдельные слова
МассивСлов = СтрРазделить(ВведенныйТекст, " ", Ложь);
Для Индекс = 0 По МассивСлов.ВГраница() Цикл
МассивСлов[Индекс] = МассивСлов[Индекс] + "*";
КонецЦикла;
// Получаем строку вида: "крас* И зелен*"
РезультирующаяСтрокаПоиска = СтрСоединить(МассивСлов, " И ");
Такой прием позволяет пользователям искать совпадения по неполным словам без необходимости изучения синтаксиса поисковых запросов 1С.