Как перехватить выбор значения из журнала или формы в модальном режиме 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

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

В чем причина сбоя штатного механизма выбора?

Проанализируем логику платформы 1С 7.7:

  1. Штатная процедура ОбработкаВыбораЗначения спроектирована платформой исключительно для немодального, асинхронного выбора. Когда пользователь нажимает кнопку с многоточием у поля ввода, вызывается процедура ПриНачалеВыбораЗначения, после чего открывается окно выбора. По завершении выбора платформа отправляет специальное оповещение родительской форме и вызывает ОбработкаВыбораЗначения.
  2. Если исходная форма сама запущена модально, цикл обработки оконных сообщений кардинально меняется. Модальный режим жестко блокирует контекст и не позволяет дочерним окнам свободно взаимодействовать с родителем через асинхронный механизм оповещений.
  3. Если же из модального окна попытаться открыть немодальный журнал или список, то родительское модальное окно перехватывает управление, из-за чего системное событие возврата выбора попросту не доходит до исходной формы.

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

Решение 1. Модальное открытие журнала и обработка результата в ПриНачалеВыбораЗначения

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

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


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

А в модуле формы открываемого журнала документов в процедуре выбора строки необходимо вернуть выбранный документ в переданный контекст:


Процедура ПриВыбореСтроки()
    Форма.Параметр = ТекущийДокумент;
    Форма.Закрыть();
КонецПроцедуры

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

Решение 2. Использование штатного метода Документ.Выбрать()

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

Разберем этот вариант по шагам:


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

Этот способ более лаконичен, не требует модификации самого журнала документов и корректно позиционирует объект на выбранном значении.

Решение 3. Передача через экспортную глобальную переменную

Иногда открывать модальный журнал неудобно из-за фиксированного размера окна или ограничений интерфейса. Некоторые разработчики используют обходной путь с глобальной переменной модуля Глобальный модуль (объявленной как Перем глВыбранноеЗначение Экспорт;).

В открываемой форме при выборе строки значение помещается в глобальную переменную:


Процедура ПриВыбореСтроки()
    глВыбранноеЗначение = ТекущийДокумент;
КонецПроцедуры

Затем в основной форме документа в процедуре-формуле поля проверяется наличие данных:


Процедура ДокОснованиеФормула()
    Если ПустоеЗначение(глВыбранноеЗначение) = 0 Тогда
        ДокОснование = глВыбранноеЗначение;
        глВыбранноеЗначение = "";
        Форма.Обновить();
    КонецЕсли;
КонецПроцедуры

Важно понимать: данный метод является костыльным и имеет существенный недостаток. Пользователю после выбора в журнале придется дополнительно кликнуть по полю в документе или нажать Enter, чтобы формула отработала и подтянула значение из глобальной переменной. Поэтому для надежной работы рекомендуется использовать Решение 1 или Решение 2, где поток выполнения полностью контролируется кодом.

← На главную