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