Добрый день, коллеги!
Сегодня наше радио ведет репортаж из зоны, не входящей в зону комфорта многих жителей местного галактического скопления. Чтобы внести ясность и убрать сумятицу, я решил еще раз коснуться давно известной продвинутым бомбардирам 1С методики асинхронного открытия формы для подбора нужных и полезных данных из различных внешних формочек.
Навела меня на мысль рассказать об этом еще раз некая Анна, создавшая эту вот тему, в которой в очередной раз встречаю я богомерзкие слова "Результат = Форма.ОткрытьМодально()", а нервы то уже не те!!! )))
Итак, приступим к тому, чтобы внести ясность.
СУТЬ ЗАДАЧИ
Есть форма документа, есть справочник, данные из которого нужно поместить в таблицу формы документа (или в реквизит формы, или еще куда - тут это вопрос второй).
Некоторые "программисты" (ну да, назовем так), которые еще не вкусили прелестей нового мира и нового мирового порядка, все еще для подобных действий не находят ничего лучше, чем использовать старый и проверенный "Элементик = ОткрытьФормуМодально(ИмяФормы, ...);", а кое-кто сначала форму получает в переменную и только потом открывает (как в том самом вопросе на форуме, с которого все началось). Ну не на олимпиаде он - за дополнительную переменную балл не снижают (зряплату не понижают).
СУТЬ ВЕЩЕЙ
До сих пор многие матерые кулхацкеры плюются в сторону асинхронности и запрета модальности, но, по-сути, в плане подбора ничего не изменилось. Как была некая асинхронность (т.е. отдельная процедура обработки выбора), так она и осталась. Просто и форму можно открывать теперь асинхронно, выделяя процедуру обработки результата в отдельную процедуру и таким образом объединять все обработчики в одной функции, а не раскидывать их по всему модулю формы. Также никто не мешает вынести обработчики вообще в отдельный модуль.
Давайте ответим на главный вопрос статьи: "как организовать подбор в управляемой форме?" Для этого откроем форму с признаком "ЗакрыватьПриВыборе = ложь" и "РежимВыбора = истина":
&НаКлиенте
Процедура Подбор(Команда)
ОткрытьФорму(
"Справочник.Справочник1.ФормаВыбора",
Новый Структура("ЗакрыватьПриВыборе, РежимВыбора",
Ложь, Истина),
ЭтаФорма
, , , ,
Новый ОписаниеОповещения(
"ПриЗакрытииФормыПодбора",
ЭтаФорма,
"Подбор"),
РежимОткрытияОкнаФормы.БлокироватьОкноВладельца
);
КонецПроцедуры
В приведенном коде открывается форма выбора справочника "Справочник1", также предполагается, что у нас есть экспортная клиентская процедура "ПриЗакрытииФормыПодбора", которая будет вызваться при закрытии формы выбора.
Т.к. у нас параметр "ЗакрыватьПриВыборе" установлен в "ложь", то форма справочника при двойном клике или нажатии клавиши "Энтер" на элементе закрываться не будет. При этом т.к. параметр "РежимВыбора" установлен в "Истина", то каждый даблклик и "Энтер" будет генерировать событие "ОбработкаВыбора" во владельце. Таким образом, если у нас, например, каждый раз, когда выбирают элемент в форме выбора, должна добавиться строка табличной части, код дополнится вот такой процедурой:
&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
Объект.ТабличнаяЧасть1.Добавить().ФИО = ВыбранноеЗначение;
КонецПроцедуры
Нужно иметь ввиду, что обработка выбора - это не просто функция, а событие формы, соответственно создавать ее лучше через выбор соответствующего события в списке процедур и функций (энтузиасты этого дела могут создать процедуру, а потом выбрать ее в спсике над кодом формы или вообще в событиях формы).
Код, приведенный выше, всего-то добавляет новую строку в табличную часть "ТабличнаяЧасть1" и устанавливает там в реквизит "ФИО" выбранный в форме подбора элемент справочника.
Для красочности картины давайте дополним код процедурой, обрабатывающей закрытие формы выбора:
&НаКлиенте
Процедура ПриЗакрытииФормыПодбора(Рез, Доп) Экспорт
Сообщить("Ура, форма подбора закрыта!");
КонецПроцедуры
В данном случае при закрытии формы владельца просто вывалится сообщение: "Ура, форма подбора закрыта!".
РАЗВИТИЕ НАСТУПЛЕНИЯ
Мы можем, конечно, вообще не использовать обработку выбора при выборе единичного значения. Для этого достаточно переписать открытие формы выбора таким образом, чтобы параметр "ЗакрыватьПриВыборе" устанавливался в "Истина". Но и обработку выбора значения нужно будет реализовать в асинхронной процедуре, указанной в описании оповещения:
&НаКлиенте
Процедура ПриЗакрытииФормыПодбора(Рез, Доп) Экспорт
// если ничего не выбрали, то в рез будет пусто...
Если НЕ Рез = Неопределено Тогда
Объект.ТабличнаяЧасть1.Добавить().ФИО = Рез;
КонецЕсли;
//Сообщить("Ура, форма подбора закрыта!");
КонецПроцедуры
//&НаКлиенте
//Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
// Объект.ТабличнаяЧасть1.Добавить().ФИО = ВыбранноеЗначение;
//КонецПроцедуры
В этом коде мы убрали процедуру обработки выбора, т.к. если бы мы ее оставили, то у нас создались бы две строки. Почему? Над этим вопросом рекомендую подумать факультативно (в качестве домашнего задания, если кто хочет).
Также в обработке асинхронного оповещения необходимо контролировать возвращенный результат. Если результат пустой, то это говорит о том, что форму просто закрыли, не выбрав никакого значения. Для этого в коде добавлена проверка на "Рез = Неопределено".
Давайте окончательно разберемся с темой и добавим возможность ввода, например, количества "ФИО" в документе. Для этого пропишем еще одну асинхронную процедуру, которая будет обрабатывать ввод числового значения. Для этого вернем "ложь" для параметра формы "ЗакрыватьПриВыборе", раскомментируем процедуру "ОбработкаВыбора" и убурем из процедуры асинхронного оповещения добавление строки:
&НаКлиенте
Процедура ПриЗакрытииФормыПодбора(Рез, Доп) Экспорт
//если ничего не выбрали, то в рез будет пусто...
//Если НЕ Рез = Неопределено Тогда
// Объект.ТабличнаяЧасть1.Добавить().ФИО = Рез;
//КонецЕсли;
// снова "Уга, товагищи!"
Сообщить("Ура, форма подбора закрыта!");
КонецПроцедуры
&НаКлиенте
Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора)
ПоказатьВводЧисла(
Новый ОписаниеОповещения("ПриВводеЧисла",
ЭтаФорма,
ВыбранноеЗначение), , // вот тут у нас как раз появился доппараметр
"Введите количество ФИО",
10,
0
);
КонецПроцедуры
&НаКлиенте
Процедура ПриВводеЧисла(Рез, Доп) Экспорт
// найдем строки с этим "ФИО"
НайденныеСтроки = Объект.ТабличнаяЧасть1.НайтиСтроки(Новый Структура("ФИО", Доп));
// если не нащли - добавим
Если НайденныеСтроки.Количество() = 0 Тогда
Ст = Объект.ТабличнаяЧасть1.Добавить();
Ст.ФИО = Доп;
Ст.Колво = рез;
Иначе
// если нашли - увеличим колчество
НайденныеСтроки[0].Колво = НайденныеСтроки[0].Колво + рез;
КонецЕсли;
КонецПроцедуры
Итак, тут мы помимо прочего не просто добавляем новую строку, а, если такое "ФИО" уже есть, добавляем выбранное количество в него (увеличиваем поле "Колво"). И тут нам как раз пригождается второй аргумент процедуры обработки оповещения - "ДополнительныеПараметры" (для друзей управляемых форм просто "доп"). В этот аргумент мы можем засунуть что угодно, когда создаем описание оповещения - очень, на мой взгляд, удобно. Тут как раз мы сохраняем выбранный элемент (чтобы не плодить никому не нужные переменные).
ЗАКЛЮЧЕНИЕ
В действительности у управляемых форм есть масса преимуществ перед формами обычными. И асинхронность - это еще не самый интересный механизм. Вот, например, статья о том, как передавать параметры отбора (фильтр) в форму выбора, чтобы показывать пользователю не весь справочник, а только нужную его часть (даже если эта часть определяется значением строки табличной части).