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