Работа с данными выбора

Программирование - Практика программирования

Форма выбора динамический список управляемая форма список выбора

26
В управляемом интерфейсе заложена мощная возможность описывать связи реквизитов формы через параметры. Установка параметров связей позволяет ограничить выбор данных так, чтобы целостность данных была обеспечена на этапе ввода. Однако без дополнительного программирования задать можно только самые простые связи. Такие условия связи, как зависимость от реквизита через точку или зависимость через дополнительное отношение, заданное в регистре сведений - уже задать без программирования не получится.

ОГЛАВЛЕНИЕ

Введение

Связи параметров выбора

Параметры выбора

Обход ограничений параметров выбора

Практика

Решение

Подсистема "Работа с данными выбора"

Обработка параметров, функция ПолучитьТекстЗапроса

Динамический список формы выбора

Список данных выбора

Проверка на соответствие условиям параметров выбора. Заполнение по-умолчанию

Поставка

Развертывание

Демонстрация

Рабочая версия


ВВЕДЕНИЕ

Заполняя форму ввода, мы работаем со связанными данными. Так, выбирая договор контрагента, мы ожидаем увидеть в форме выбора список договоров конкретного контрагента. Пользуясь текстовым поиском в поле реквизита формы, мы также должны увидеть список, удовлетворяющий как критериям введенного поиска, так и ограничениям связей. Так, введя часть номера договора, мы ожидаем увидеть список договоров конкретного контрагента, элементы которого содержат в номере набранный образец поиска. Аналогично система должна контролировать уже введенное значение в поле реквизита формы: значение должно удовлетворять ограничениям связей.

СВЯЗИ ПАРАМЕТРОВ ВЫБОРА

Платформа 1С позволяет описывать связи параметров выбора. По этим связям форма выбора автоматически настраивает фиксированные настройки отбора. Пользователь в форме выбора получает список элементов, соответствующих наложенным ограничениям связей. Аналогично платформа обрабатывает отбор элементов при формировании списка выбора. Когда пользователь вводит в реквизит формы текстовый образец строки поиска, платформа выполняет поиск элементов, соответствующих введенному значению по полям поиска, а также по условиям отбора, соответствующих связям параметров выбора.

Описанное поведение системы вполне нас могло устроить. Однако если, например, нужно настроить отбор по полю реквизита через точку, то такое мы сделать стандартно не сможем. Так же, если ограничение подразумевает использование критериев отбора через поля дополнительных таблиц, соединенных с основной таблицей выбираемого типа, то такой вариант также не предусмотрен платформой. И последнее, в платформе нет средств проверки выбранного значения на соответствие связям параметров выбора.

Однако, об этом мало кто знает, в качестве параметра выбора можно установить фиксированный массив, и тогда отбор будет не на равенство, а на вхождение значения поля основной таблицы в список значений установленного массива. И это полезно знать в рамках представленного решения, чтобы не реализовывать то, что и так поддерживается платформой.

Поясню на конкретных примерах. Представим себе форму, в которой есть два реквизита типа Контрагент. Скажем нужно указать первого контрагента, а потом выбрать второго. Однако второго контрагента можно выбрать только из той же группы контрагентов, в которой находится первый. Здесь условие связи параметров выбора могло бы быть таким: Отбор.Родитель = Контрагент.Родитель. Однако правое выражение через точку не поддерживается платформой и потому такое условие связи ввести нельзя.

Для второго примера представим себе форму, в которой в шапке есть реквизит типа Договор, а в табличной части - реквизит Статья. При этом выбор статей ограничен списком из регистра соответствия статей договору. Такое условие связей могло бы выглядеть так: Отбор.Ссылка = РС.Статья И РС.Договор = ДоговорКонтрагента. Однако в этом случае в условии задействована дополнительная таблица и такое условие также задать стандартно нельзя.

Предлагаемое решение как раз снимает указанные ограничения и позволяет использовать связи параметров как с реквизитами основной таблицы, так и с реквизитами связанных таблиц. Данное решение распространяется на все обозначенные сценарии ввода значения реквизита формы:

  • ввод через форму выбора;
  • ввод из списка выбора;
  • определение однозначного значения выбора (предсказание выбора);
  • проверка соответствия значения ограничениям по связям параметров выбора.

ПАРАМЕТРЫ ВЫБОРА

При вызове формы выбора или при подборе из списка платформа передает параметры, определенные по связям. Используя переданные параметры можно сформировать свой собственный запрос к данным и подменить выборку данных. Это нам необходимо для того, чтобы обойти ограничения описания условий связей. Перед рассмотрением указанного способа получения выборки давайте ознакомимся с существующими ограничениями платформы при описании связей.

Платформа накладывает следующие ограничения на создание выражений условий связей параметров. Имя параметра должно удовлетворять условиям написания имен (не содержать пробелов, начинаться может с буквы или символа подчеркивание); в имени можно использовать только одну точку или не использовать точку вообще. Значение параметра должно быть значением реквизита формы без использования подчиненных реквизитов, однако можно указать реквизит табличной части в специальном формате через элементы формы: Элементы.Список.ТекущиеДанные.ИмяРеквизита.

ОБХОД ОГРАНИЧЕНИЙ ПАРАМЕТРОВ ВЫБОРА

Практика

На практике мне попадались следующие решения:

  • Передача в параметры формы выбора подготовленного списка ссылок для выбираемого типа данных
  • Использование специализированной формы выбора с предопределенным запросом динамического списка
  • Выбор из подготовленного списка значений

Недостатками этих решений являются:

  • Не универсальность (необходимо разрабатывать специализированные формы выбора)
  • Невозможность переиспользования данного подхода для формирования списка выбора
  • Невозможность переиспользования для проверки введенного значения

В рамках наложенных ограничений платформы, недостающие параметры можно передать косвенно через указание реквизита формы. Так, если по приведенному примеру выше, нам нужно указать связь по родителю реквизита Контрагент, то условие связи параметров может быть таким: Отбор.КонтрагентРодителя = Контрагент. Тогда в форму выбора или же в предопределенную процедуру обработки выбора будет передан параметр с именем КонтрагентРодителя и значением реквизита формы Контрагент. Далее нам достаточно отработать условие по этому параметру, а именно использовать этот параметр для получения значения через точку Контрагент.Родитель и уже это, полученное косвенно, значение параметра использовать для установки необходимого отбора по родителю.

Аналогично для второго примера условие связи будет: Отбор.Договор = Договор. Несмотря на то, что условие накладывается на справочник Статьи, в котором отсутствует поле Договор, такое условие в рамках платформы вполне допустимо использовать. В этом случае в форму выбора будет передан параметр Договор со значением из реквизита формы Договор. Далее нам необходимо построить запрос через соединение основной таблицы Статьи с таблицей РегистрСведений.СтатьиДоговора и уже на поле регистра сведений наложить условие отбора по переданному значению договора.

Таким образом можно обойти ограничения платформы и передать в форму выбора необходимые параметры. Далее необходимо исходя из переданных параметров построить текст запроса. Полученный текст запроса можно использовать как в форме выбора, так и в предопределенной процедуре получения данных выбора для формирования списка.

ПОДСИСТЕМА РАБОТА С ДАННЫМИ ВЫБОРА

Рисунок 1. Диаграмма последовательности

Предлагаемая подсистема реализует интерфейс для работы следующих сценариев:

  1. Быстрый выбор из списка - поддерживается поиск по началу или по вхождению по полям поиска, реализована подсветка найденных фрагментов вхождения текста
  2. Выбор из формы выбора - поддерживается нестандартная реализация отборов с возможностью вывода иерархии (для иерархических справочников)

Подключение к подсистеме производится через вставку вызова в форме выбора и добавление предопределенной процедуры менеджера объекта ОбработкаПолученияДанныхВыбора.

Обработка параметров, функция ПолучитьТекстЗапроса

В предлагаемое решение строится вокруг реализации функции ПолучитьТекстЗапроса. Реализация данной функции не является обязательной и нужна только для тех типов данных, выборка которых ограничивается не только по реквизитам основной таблицы.

Основное назначение функции - в получении текста запроса по переданным параметрам. В отличии от стандартного поведения платформы, когда в форму выбора передаются параметры, эта функция не имеет ограничений: в ней можно реализовать любые условия выбора. Однако и здесь есть ограничение платформы: результирующий запрос не должен содержать объединений ни в одном из пакетов запроса. Это ограничение накладывается реализацией динамического списка, в котором на текущий момент объединения не поддерживаются (однако объединение можно использовать во вложенном запросе!).

В следующем листинге демонстрируется пример-заготовка реализации такой функции. Данная реализация основана на использовании объектной модели запроса. Работа с объектной моделью осуществляется с использованием подсистемы "Работа со схемой запроса". С шаблонами построения текста запроса при использовании подсистемы можно подробнее ознакомиться в одноименной статье.

Листинг 1. Общая структура функции ПолучитьТекстЗапроса на примере справочника _ДемоНоменклатура

//  Подсистема РаботаСДаннымиВыбора НАЧАЛО
Функция ПолучитьТекстЗапроса(ПараметрыЗапроса = Неопределено, Параметры, Поля = "", ТекстЗапроса = Неопределено) Экспорт
	Если ПараметрыЗапроса = Неопределено Тогда
		ПараметрыЗапроса = Новый Структура;
	КонецЕсли;
	СхемаЗапроса 		= РаботаСДаннымиВыбора.ПолучитьСхемуЗапросаПоИсточнику("Справочник._ДемоНоменклатура",, Поля, ТекстЗапроса);
	ЗапросИсточника		= СхемаЗапроса.ПакетЗапросов[СхемаЗапроса.ПакетЗапросов.Количество()-1];
	ОператорИсточника	= ЗапросИсточника.Операторы[0];
	Источник			= ОператорИсточника.Источники.НайтиПоПсевдониму("Источник");
	//  Обработка отбора
	Если Параметры.Свойство("Отбор") Тогда
	// Ваш код по построению текста запроса по параметрам отбора
	// (рекомендую использовать шаблон "Построение текста запроса по параметрам отбора")
	КонецЕсли;
	//  Обработка отбора по характеристикам (дополнительные реквизиты и свойства)
	// (шаблон "Работа с характеристиками")
	Если Параметры.Свойство("Характеристики") Тогда
	// Ваш код по построению текста запроса по параметрам характеристик
	КонецЕсли;
	Возврат СхемаЗапроса.ПолучитьТекстЗапроса();
КонецФункции
//  Подсистема РаботаСДаннымиВыбора КОНЕЦ

Динамический список формы выбора

После того, как мы разобрались с механизмом получения текста запроса по переданным параметрам, давайте рассмотрим, как его использовать для формирования динамического списка формы выбора.

Подготовка динамического списка может быть осуществлена в предопределенной процедуре модуля формы: ПриСозданииНаСервере. В этой процедуре доступны параметры выбора, которые необходимо передать в функцию формирования текста запроса. Полученный текст запроса необходимо установить в динамическом списке. Для того, чтобы динамический список работал, необходимо также установить параметры отбора динамического списка (это те параметры, которые нельзя установить в условиях отбора данных основной таблицы, но можно использовать в тексте запроса).

Для работа подсистемы необходимо настроить динамический список формы выбора: установить произвольный запрос и изменить псевдоним основной таблицы на имя "Источник".

Разберемся подробнее с параметрами отбора и установкой отбора в динамическом списке. Стандартным образом отбор в динамическом списке платформа устанавливает по параметрам структуры переданного отбора. В нашем случае в этой структуре могут быть как поля основной таблицы, так и параметры, используемые для получения значения отбора косвенно. Параметры второй категории необходимо установить в процедуре ПриСозданииНаСервере и они же должны быть указаны в тексте запроса, а параметры первой категории оставить в структуре отбора. Тогда платформа получит в качестве отбора поля основной таблицы и стандартным образом настроит элементы фиксированного отбора по переданным значениям после открытия формы выбора.

Таким образом, для работы формы выбора с динамическим списком необходимо разделить переданные параметры на отбор по реквизитам основной таблицы и параметры запроса. Первые должны остаться и будут стандартным образом обработаны системой, а вторые необходимо использовать в тексте запроса динамического списка и установить программно в параметрах динамического списка.

Листинг 2. Демонстрация разделения параметров в функции ПолучитьТекстЗапроса

	//  Обработка отбора
	Если Параметры.Свойство("Отбор") Тогда
		ОбщийКлиентСервер.ПереместитьЗначенияСвойств(Параметры.Отбор, ПараметрыЗапроса, "Организация,Контрагент,ДоговорКонтрагента");
		Если ОбщийКлиентСервер.СтруктураСодержитСвойства(ПараметрыЗапроса, "Организация,Контрагент") Тогда
			// код формирования текста запроса с отбором по организации и контрагенту
		КонецЕсли;
		Если ПараметрыЗапроса.Свойство("ДоговорКонтрагента") Тогда
			// код формирования текста запроса с отбором по договору контрагента
		КонецЕсли;
	КонецЕсли;

Листинг 3. Подключение формы выбора к подсистеме

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	//  Подсистема РаботаСДаннымиВыбора НАЧАЛО
	РаботаСДаннымиВыбора.ЗаполнитьТекстЗапросаДинамическогоСписка(Список, Параметры);
	//  Подсистема РаботаСДаннымиВыбора КОНЕЦ
КонецПроцедуры

Примечание: подключаемая форма выбора должна содержать произвольный текст запроса основной таблицы, при этом псевдоним основной таблицы должен быть предопределенным «Источник». Этот же псевдоним используется в подсистеме для построения текста запроса путем добавления условия и соединений.

Список данных выбора

Рисунок 2. Список выбора

Механизм получения списка данных выбора аналогичен описанному для динамического списка формы выбора.

Как и для формы выбора здесь при вызове предопределенной процедуры ОбработкаДанныхВыбора будут переданы параметры, в том числе и параметры связей выбора. Далее необходимо получить текст запроса и установить значения переданных параметров в запрос программно. К полученному запросу необходимо применить отбор по условию вхождения переданного образца в строке поиска в значения по полям поиска.

После выполнения полученного запроса в процедуре формируется список, который используется платформой для вывода на экран списка выбора.

Листинг 4. Подключение процедуры к подсистеме

Процедура ОбработкаПолученияДанныхВыбора(ДанныеВыбора, Параметры, СтандартнаяОбработка)
	//  Подсистема РаботаСДаннымиВыбора НАЧАЛО
	СтандартнаяОбработка = Ложь;
	РаботаСДаннымиВыбора.ЗаполнитьДанныеВыбора("Справочник._ДемоНоменклатура", ДанныеВыбора, Параметры);
	//  Подсистема РаботаСДаннымиВыбора КОНЕЦ
КонецПроцедуры

Проверка на соответствие условиям параметров выбора. Заполнение по-умолчанию.

Теперь, когда мы умеем формировать текст запроса по условиям связей, мы можем также проверить текущее значение реквизита на соответствие условиям связей. Это может быть полезным, когда меняются связи (топология), либо меняются значения связей, либо производится выбор значения из истории списка.

Если в выборке по условиям связей мы получим единственное значение, то его можно использовать для заполнения реквизита по-умолчанию. В этом случае пользователя не обязательно заставлять сделать выбор, когда выбора то и нет.

Листинг 5. Проверка соответствия переменной СсылкаНаЗначение переданным параметрам выбора из структуры Параметры

Запрос 			= Новый Запрос;
ТекстЗапроса 	= РаботаСДаннымиВыбора.НастроитьЗапросОбработкиПолученияДанныхВыбора(Запрос, ОбщегоНазначения.ИмяТаблицыПоСсылке(СсылкаНаЗначение),, Параметры, 2);
СхемаЗапроса 	= Новый СхемаЗапроса;
//  Проверка соответствия значения структуре параметров
Если ЗначениеЗаполнено(СсылкаНаЗначение) Тогда
	СхемаЗапроса.УстановитьТекстЗапроса(ТекстЗапроса);
	Запрос.УстановитьПараметр("ЗначениеПоСсылке", СсылкаНаЗначение);
	//  Схема запроса на соответствие ссылке условиям запроса
	Оператор		 = СхемаЗапроса.ПакетЗапросов[СхемаЗапроса.ПакетЗапросов.Количество()-1].Операторы[0];
	Оператор.Отбор.Добавить(Новый ВыражениеСхемыЗапроса("Источник.Ссылка = &ЗначениеПоСсылке"));
	Запрос.Текст	 = СхемаЗапроса.ПолучитьТекстЗапроса();
	РезультатЗапроса = Запрос.Выполнить();
	Если РезультатЗапроса.Пустой() Тогда
		СсылкаНаЗначение = ОбщийКлиентСервер.ПустаяСсылкаПоТипу(ТипЗнч(СсылкаНаЗначение));
	КонецЕсли;
КонецЕсли;

СТЕНД "РАБОТА С ДАННЫМИ ВЫБОРА"

Рисунок 3. Форма обработки стенда

Для демонстрации работы подсистемы выбран справочник _ДемоНоменклатура из демо-конфигурации БСП. С помощью расширения конфигурации в справочнике доработан менеджер объекта и форма выбора. В модуль менеджера добавлена функция ПолучитьТекстЗапроса и предопределенная процедура ОбработкаДанныхВыбора. В форме выбора добавлен вызов процедуры ЗаполнитьТекстЗапросаДинамическогоСписка.

В функции ПолучитьТекстЗапроса реализована обработка дополнительных параметров:

  1. Организация и Контрагент - формируется список номенклатуры, которая использовалась в документах реализации
  2. Договор контрагента - формируется список номенклатуры, определенный в регистре сведений НоменклатураДоговора
  3. Дополнительные реквизиты - отбор по реквизитам из табличной части номенклатуры
  4. Дополнительные свойства - отбор по свойствам, определенным в регистре сведений СвойстваОбъектов

 

В процедуре используются приемы по формированию текста запроса в объектной модели с использованием подсистемы РаботаСоСхемойЗапроса. Более подробно читайте здесь.

 

 
 Листинг 5. Функция ПолучитьТекстЗапроса

ПОСТАВКА

Метаданные Наименование Назначение Требования
ОбщийМодуль РаботаСДаннымиВыбора Основной модуль Использует общие функции БСП, а также подсистему РаботаСоСхемойЗапроса (в поставку не входит, скачать здесь)
  ОбщийКлиентСервер Вспомогательный модуль  
Расширение РаботаСДаннымиВыбора Подготавливает метаданные демо-базы БСП для работы с подсистемой.  
Обработка СтендРаботаСДаннымиВыбора Демонстрация работы выбора Требуется подключить расширение РаботаСДаннымиВыбора


РАЗВЕРТЫВАНИЕ

Демонстрация

  1. Развернуть демо-базу БСП
  2. Объединить с конфигурацией поставки по подсистеме «РаботаСДаннымиВыбора». При объединении сбросить флаг Свойства
  3. Установить расширение
  4. Открыть обработку Стенд

Рабочая версия

  1. Объединить с конфигурацией поставки по подсистеме «РаботаСДаннымиВыбора». При объединении сбросить флаг Свойства.
26

Скачать файлы

Наименование Файл Версия Размер
Конфигурация+ДемоРасширение+ДемоОбработкаСтенд
.zip 35,05Kb
27.07.18
6
.zip 1.01 35,05Kb 6 Скачать

См. также

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. bulpi 137 17.07.18 15:47 Сейчас в теме
Толково написано. Стиль строгий. Наукой автор занимался ?
3. kalyaka 410 17.07.18 19:55 Сейчас в теме
(1) Ну так это ж профессиональный ресурс и статьи я пишу для профессионалов.

Наукой не занимался, но по мне так написание таких статей вполне себе научный труд :)
2. SlavaKron 17.07.18 19:36 Сейчас в теме
Знаете, вы где-то говорили про увеличение уровня абстракции кода, но это уже перебор. Я тоже стремлюсь к красоте, но ведь это 1с, какая к черту красота!
4. kalyaka 410 17.07.18 20:47 Сейчас в теме
(2) В чем же перебор? Или Вам понравилось и это было восхищение? :)

Под абстракцией я имел в виду обобщенное решение, для которого применение не ограничено только одним, рассматриваемым в статье случаем. Нужно проделать большую работу, прежде чем на основе массива конкретных решений будет получено одно общее. И это решение уже будет иметь ценность благодаря тому, что множество велосипедов больше не потребует своего изобретения.
Brawler; MSK_Step; +2 Ответить
15. SlavaKron 21.07.18 09:51 Сейчас в теме
(4) Мне понравился ваш подход, но рассматриваемая задача, думаю, не требует таких усилий. Есть 2 крайности - хардкодинг и гипертрофированная универсализация. Оптимальное решение где-то посередине.
16. kalyaka 410 21.07.18 20:18 Сейчас в теме
(15)
рассматриваемая задача, думаю, не требует таких усилий

Наверное соглашусь с Вами отчасти. Задача выбора из списка слишком уж мелкая и вполне поддерживается платформой, а где нет - варианты тоже найдутся (приведены в статье).

С другой стороны, данное решение есть часть решения более широкого класса задач: формальное описание выбора, проверка выбранного значения, поддержка выбора интерактивно из списка или формы выбора, поддержка не интерактивного режима работы в модели данных.

Иными словами данная задача была решена в рамках другой задачи - реализации полноценной модели MVC и качества данных ввода. И это уже совсем другая история.

На данный момент у меня уже есть полноценное решение этой задачи. Представить его широкой публике я планирую где-то в сентябре-октябре этого года. А пока я готовлю серию публикаций (Шаблон MVC, Управление состоянием формы, Работа с данными выбора, Работа с данными заполнения), в которых представлены отдельные решения из этой подсистемы.
5. Leon75 18.07.18 11:12 Сейчас в теме
Четкая статья. Но когда сталкиваешься с пушистотью логики пользователей, то и ограничение их выбора четкой логикой и не ограничение с надеждой на профессионализм пользователя не ставит точку в решении. "Мне нужно выбрать именно такую статью расхода, а программа не дает". И почти одновременно: "А почему мне программа дала выбрать это значение? Она же должна проверять." И дифференцированный подход не помогает, потому что мнения меняются как положение флюгера. В итоге рождаются монструозные решения, изобилуюшие ошибками. Тормозящие, перегруженные и неудобные.
Я понимаю, жизнь должна продолжаться, но безуспешные попытки закрыть один вопрос на 100% и перейти к следующему напоминают сизифов труд.
t.v.s.; Rustig; Brawler; +3 Ответить
6. kalyaka 410 18.07.18 20:10 Сейчас в теме
(5) Возможно пользователи в чем то все-таки правы :)

Дело в том, что условия выбора не всегда один раз заданы и не изменяются. Вполне можно допустить, что при определенных условиях действуют одни ограничения, а при других - другие.

Например, в документе «Списание с расчетного счета» Счет контрагента для внешних платежей подчинен Контрагенту, однако для внутренних операций это уже не так: реквизит Контрагент должен быть пустым, а Счет контрагента заполняется счетом Организации.

Проблему связей я исследовал в своей работе ранее Шаблон MVC. У меня есть уже обновленное решение, версию которого я представлю в последующих публикациях (планирую обновить старые публикации и представить новое общее решение).

Если Вы поделитесь своими примерами из жизни, когда противоречивые требования не позволяют настроить правильные отборы для выбора данных, то я бы их разобрал в рамках представленного мной решения.
7. triviumfan 7 18.07.18 20:42 Сейчас в теме
Я, пожалуй, воспользуюсь православной "обработкой выбора" :)
Статья понравилась только манерой изложения.
8. kalyaka 410 18.07.18 21:15 Сейчас в теме
10. triviumfan 7 19.07.18 15:26 Сейчас в теме
(9) За такое можно и"банан поймать". Субординацию держите.
11. the1 321 19.07.18 19:58 Сейчас в теме
(10) Извините, не хотел обидеть, шутка не удалась 😐
12. dabu-dabu 7 20.07.18 10:54 Сейчас в теме
Это конечно здорово и интересно, но без реализации аналогичных функций для подбора при вводе текста бессмысленно
13. kalyaka 410 20.07.18 12:02 Сейчас в теме
(12) Ну это можно :)
Реализацию смотрите в параграфе Список данных выбора
14. dabu-dabu 7 20.07.18 15:41 Сейчас в теме
(13) Да, пропустил. Извиняюсь.
Оставьте свое сообщение