При разработке универсальных обработок, выгрузок данных и аналитических инструментов часто возникает задача предоставить пользователю возможность выбрать справочник конфигурации, а затем указать конкретный реквизит этого справочника для дальнейшей обработки. Разберем по шагам, как извлечь структуру метаданных справочника и корректно организовать выбор полей на управляемой форме.
Прежде чем приступать к коду, проанализируем, как платформа 1С:Предприятие 8.3 хранит информацию о реквизитах объектов. Часто начинающие разработчики обращаются только к коллекции Реквизиты, упуская базовые поля справочника.
В объекте метаданных справочника реквизиты разделены на несколько категорий:
СтандартныеРеквизиты. В неё входят предопределенные платформой поля: Ссылка, Код, Наименование, ПометкаУдаления, Родитель, Владелец и другие системные свойства.Реквизиты. Содержит реквизиты шапки справочника, добавленные разработчиком.ТабличныеЧасти, внутри которой каждая табличная часть содержит собственную вложенную коллекцию Реквизиты.Для корректного взаимодействия с пользователем важно разделять техническое имя (Имя) и человекочитаемое название (Синоним). В коде и запросах используется свойство Имя, а пользователю отображается Синоним или стандартное представление.
Рассмотрим реализацию через два поля ввода на управляемой форме. Первое поле служит для выбора справочника конфигурации, а второе — для выбора реквизита. Список выбора второго поля будет динамически переформировываться при изменении первого.
Разберем по шагам создание реквизитов и элементов формы:
ИмяСправочника (тип Строка) и ИмяРеквизита (тип Строка).ИмяСправочника установим режим выбора из списка (свойство РежимВыбораИзСписка = Истина).ИмяРеквизита также включим РежимВыбораИзСписка = Истина и свойство КнопкаВыпадающегоСписка = Истина.Посмотрим на пример заполнения списка справочников при инициализации формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Заполняем список выбора доступных справочников
СписокСправочников = Элементы.ИмяСправочника.СписокВыбора;
СписокСправочников.Очистить();
Для Каждого МетаданныеСправочника Из Метаданные.Справочники Цикл
// Значение — имя объекта метаданных, представление — синоним
Представление = МетаданныеСправочника.Синоним;
Если ПустаяСтрока(Представление) Тогда
Представление = МетаданныеСправочника.Имя;
КонецЕсли;
СписокСправочников.Добавить(МетаданныеСправочника.Имя, Представление);
КонецЦикла;
// Сортируем список по представлению для удобства пользователя
СписокСправочников.СортироватьПоПредставлению();
КонецПроцедуры
Теперь создадим обработчик события ПриИзменении для элемента ИмяСправочника. При смене справочника необходимо очистить ранее выбранный реквизит и заново заполнить выпадающий список:
&НаКлиенте
Процедура ИмяСправочникаПриИзменении(Элемент)
ОбновитьСписокРеквизитовНаСервере();
КонецПроцедуры
&НаСервере
Процедура ОбновитьСписокРеквизитовНаСервере()
// Очищаем текущий выбор реквизита
ИмяРеквизита = "";
СписокРеквизитов = Элементы.ИмяРеквизита.СписокВыбора;
СписокРеквизитов.Очистить();
Если ПустаяСтрока(ИмяСправочника) Тогда
Возврат;
КонецЕсли;
МетаданныеОбъекта = Метаданные.Справочники.Найти(ИмяСправочника);
Если МетаданныеОбъекта = Неопределено Тогда
Возврат;
КонецЕсли;
// 1. Обходим стандартные реквизиты
Для Каждого СтандартныйРеквизит Из МетаданныеОбъекта.СтандартныеРеквизиты Цикл
Представление = СтандартныйРеквизит.Синоним;
Если ПустаяСтрока(Представление) Тогда
Представление = СтандартныйРеквизит.Имя;
КонецЕсли;
СписокРеквизитов.Добавить(СтандартныйРеквизит.Имя, Представление + " (стандартный)");
КонецЦикла;
// 2. Обходим пользовательские реквизиты
Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
Представление = Реквизит.Синоним;
Если ПустаяСтрока(Представление) Тогда
Представление = Реквизит.Имя;
КонецЕсли;
СписокРеквизитов.Добавить(Реквизит.Имя, Представление);
КонецЦикла;
СписокРеквизитов.СортироватьПоПредставлению();
КонецПроцедуры
Если справочник содержит большое количество полей или требуется отображать расширенную информацию (например, тип данных реквизита), выпадающий список может быть неудобен. В этом случае целесообразно использовать модальный диалог выбора из сформированного СписокЗначений или отдельную форму выбора.
Рассмотрим, как реализовать вызов диалога выбора через обработчик НачалоВыбора:
&НаКлиенте
Процедура ИмяРеквизитаНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Если ПустаяСтрока(ИмяСправочника) Тогда
Предупреждение("Сначала выберите справочник!");
Возврат;
КонецЕсли;
// Получаем заполненный список значений на сервере
СписокДляВыбора = ПолучитьСписокРеквизитовСправочника(ИмяСправочника);
// Открываем диалог выбора из списка
Оповещение = Новый ОписаниеОповещения("ПослеВыбораРеквизита", ЭтотОбъект);
ПоказатьВыборИзСписка(Оповещение, СписокДляВыбора, Элемент);
КонецПроцедуры
&НаКлиенте
Процедура ПослеВыбораРеквизита(ВыбранныйЭлемент, Параметры) Экспорт
Если ВыбранныйЭлемент <> Неопределено Тогда
ИмяРеквизита = ВыбранныйЭлемент.Значение;
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьСписокРеквизитовСправочника(ИмяСправочника)
Результат = Новый СписокЗначений;
МетаданныеОбъекта = Метаданные.Справочники.Найти(ИмяСправочника);
Если МетаданныеОбъекта = Неопределено Тогда
Возврат Результат;
КонецЕсли;
Для Каждого СтандартныйРеквизит Из МетаданныеОбъекта.СтандартныеРеквизиты Цикл
Результат.Добавить(СтандартныйРеквизит.Имя, СтандартныйРеквизит.Синоним);
КонецЦикла;
Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
Результат.Добавить(Реквизит.Имя, Реквизит.Синоним);
КонецЦикла;
Результат.СортироватьПоПредставлению();
Возврат Результат;
КонецФункции
Когда требуется предоставить возможность выбирать не только реквизиты шапки, но и реквизиты табличных частей справочника, наиболее удобным интерфейсным решением является элемент формы типа Таблица с источником данных ДеревоЗначений.
Дерево строится со следующей иерархией:
Пользователь выполняет выбор строки дерева двойным кликом или стандартной кнопкой выбора, после чего выбранное имя реквизита передается в целевое поле обработки.