При разработке конфигураций на платформе 1С:Предприятие 7.7 разработчики нередко сталкиваются с ситуацией, когда стандартная связка предопределенных процедур ПриНачалеВыбораЗначения и ОбработкаВыбораЗначения перестает работать так, как ожидалось. Особенно ярко это проявляется в тех случаях, когда основная форма документа или обработки открывается в модальном режиме.
Разберем детально, почему так происходит, какие ограничения накладывает платформа 1С 7.7 на модальные окна и как правильно организовать выбор значения с гарантированным возвратом результата в форму.
Проанализируем логику платформы 1С 7.7:
ОбработкаВыбораЗначения спроектирована платформой исключительно для немодального, асинхронного выбора. Когда пользователь нажимает кнопку с многоточием у поля ввода, вызывается процедура ПриНачалеВыбораЗначения, после чего открывается окно выбора. По завершении выбора платформа отправляет специальное оповещение родительской форме и вызывает ОбработкаВыбораЗначения.Таким образом, попытка обработать результат в процедуре ОбработкаВыбораЗначения при модальной форме родителя обречена на неудачу — платформа в нее просто не заходит.
Рассмотрим основной и самый надежный способ решения. Раз модальное окно приостанавливает выполнение программного кода родительской формы до момента своего закрытия, мы можем полностью отказаться от использования ОбработкаВыбораЗначения и получить выбранное значение синхронно прямо в теле ПриНачалеВыбораЗначения.
Посмотрим на пример реализации в форме вызывающего документа:
Процедура ПриНачалеВыбораЗначения(ИдентЭлемДиалога, ФлагСтандОбр)
Если ИдентЭлемДиалога = "ДокОснование" Тогда
// Отключаем стандартный диалог выбора 1С
ФлагСтандОбр = 0;
Конт = "";
// Открываем модально форму журнала или списка
ОткрытьФормуМодально("Журнал.Общий", Конт);
// Код ниже выполнится только ПОСЛЕ закрытия модального окна журнала
Если ПустоеЗначение(Конт) = 0 Тогда
ДокОснование = Конт;
Форма.Обновить();
// Если на реквизите висела формула пересчета, вызываем ее явно
ДокОснованиеФормула();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
А в модуле формы открываемого журнала документов в процедуре выбора строки необходимо вернуть выбранный документ в переданный контекст:
Процедура ПриВыбореСтроки()
Форма.Параметр = ТекущийДокумент;
Форма.Закрыть();
КонецПроцедуры
Обратим внимание на важный нюанс: после программной подстановки значения в реквизит диалога (ДокОснование = Конт;) формула, привязанная к реквизиту в свойствах элемента формы, автоматически не срабатывает. Формулы элементов управления вызываются платформой только при интерактивном вводе и нажатии клавиши Enter или смене фокуса. Поэтому мы явно вызываем процедуру формулы (ДокОснованиеФормула()) и обновляем форму с помощью Форма.Обновить().
Если нам необходимо выбрать документ определенного вида или документ из общего журнала, не обязательно вручную возиться с открытием формы журнала и передачей параметров. Платформа 1С 7.7 предоставляет штатный модальный метод выбора у агрегатного типа данных Документ.
Разберем этот вариант по шагам:
Процедура ПриНачалеВыбораЗначения(ИдентЭлемДиалога, ФлагСтандОбр)
Если ИдентЭлемДиалога = "ДокОснование" Тогда
ФлагСтандОбр = 0;
Док = СоздатьОбъект("Документ"); // Либо СоздатьОбъект("Документ.РасходнаяНакладная")
// Метод Выбрать открывает модальный диалог и возвращает 1 при успехе, 0 при отмене
Если Док.Выбрать("Выберите документ-основание", "Журнал.Общий") = 1 Тогда
ДокОснование = Док.ТекущийДокумент();
Форма.Обновить();
ДокОснованиеФормула();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Этот способ более лаконичен, не требует модификации самого журнала документов и корректно позиционирует объект на выбранном значении.
Иногда открывать модальный журнал неудобно из-за фиксированного размера окна или ограничений интерфейса. Некоторые разработчики используют обходной путь с глобальной переменной модуля Глобальный модуль (объявленной как Перем глВыбранноеЗначение Экспорт;).
В открываемой форме при выборе строки значение помещается в глобальную переменную:
Процедура ПриВыбореСтроки()
глВыбранноеЗначение = ТекущийДокумент;
КонецПроцедуры
Затем в основной форме документа в процедуре-формуле поля проверяется наличие данных:
Процедура ДокОснованиеФормула()
Если ПустоеЗначение(глВыбранноеЗначение) = 0 Тогда
ДокОснование = глВыбранноеЗначение;
глВыбранноеЗначение = "";
Форма.Обновить();
КонецЕсли;
КонецПроцедуры
Важно понимать: данный метод является костыльным и имеет существенный недостаток. Пользователю после выбора в журнале придется дополнительно кликнуть по полю в документе или нажать Enter, чтобы формула отработала и подтянула значение из глобальной переменной. Поэтому для надежной работы рекомендуется использовать Решение 1 или Решение 2, где поток выполнения полностью контролируется кодом.