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