Как передать результат из открытой управляемой формы в процедуру ОбработатьРезультатФормы в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

В этой статье мы подробно разберем, как правильно передать введенное количество из открытой формы в вызывающую процедуру-обработчик, рассмотрим работу с контекстом и изучим альтернативные эффективные методы ввода данных.

Способ 1. Использование метода Закрыть() с передачей параметра (Стандартный способ)

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

Давайте пошагово настроим этот механизм.

Шаг 1. Код в вызываемой форме (Форма ввода количества)

В форме, где пользователь указывает количество (в вашем случае это форма обработки подбора), создадим команду и кнопку подтверждения ввода (например, "ОК"). При нажатии на эту кнопку мы должны вызвать метод Закрыть, передав в него значение реквизита, в котором хранится количество.


&НаКлиенте
Процедура КомандаОК(Команда)
    
    // Получаем значение реквизита формы, куда пользователь ввел число
    РезультатВыбора = КоличествоШТ; 
    
    // Закрываем форму и передаем значение обратно в вызывающую форму
    Закрыть(РезультатВыбора);
    
КонецПроцедуры

Если пользователь передумал и просто закрыл форму крестиком или нажал кнопку "Отмена", то метод Закрыть() вызовется без параметров (или вернет значение Неопределено), что мы обязательно обработаем далее.

Шаг 2. Код в форме документа (Вызывающая форма)

Теперь проанализируем, как правильно инициализировать открытие этой формы и как обработать возвращенный результат в процедуре ОбработатьРезультатФормы.


&НаКлиенте
Процедура НачатьПодбор(Команда)

    // Создаем описание оповещения, указывая имя экспортной процедуры-обработчика и контекст (ЭтаФорма)
    ОписаниеОповещ = Новый ОписаниеОповещения("ОбработатьРезультатФормы", ЭтаФорма);
    
    // Открываем форму ввода количества асинхронно
    ОткрытьФорму("Обработка.ПодборУФ.Форма.Форма", , , , , , ОписаниеОповещ);

КонецПроцедуры

&НаКлиенте
Процедура ОбработатьРезультатФормы(Результат, Параметры) Экспорт
    
    // Если результат равен Неопределено, значит пользователь закрыл форму без ввода данных (отмена)
    Если Результат = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // В переменной "Результат" теперь находится наше "КоличествоШТ"
    ПоказатьПредупреждение(, "Пользователь ввел количество: " + Результат);
    
КонецПроцедуры

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

Способ 2. Передача контекста через дополнительные параметры ОписанияОповещения

Представим ситуацию: в табличной части документа Товары у нас выбрано несколько строк. Пользователь активизирует строку, нажимает кнопку ввода количества, открывается форма, он вводит число, форма закрывается. Как процедуре ОбработатьРезультатФормы узнать, какую именно строку нужно обновить?

Для решения этой проблемы используется третий параметр конструктора ОписаниеОповещения — Дополнительные параметры. Сюда мы можем передать любую структуру данных (например, идентификатор строки или ссылку на номенклатуру), которая вернется обратно в неизменном виде.

Давайте усложним наш пример и реализуем этот надежный подход:

Код в форме документа при открытии формы ввода:


&НаКлиенте
Процедура УказатьКоличествоДляСтроки()
    
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    
    Если ТекущаяСтрока <> Неопределено Тогда
        
        // Создаем структуру для сохранения контекста
        ДопПараметры = Новый Структура;
        // Запоминаем уникальный идентификатор текущей строки ТЧ
        ДопПараметры.Вставить("ИдентификаторСтроки", ТекущаяСтрока.ПолучитьИдентификатор());
        
        // Передаем структуру третьим параметром в ОписаниеОповещения
        ОписаниеОповещ = Новый ОписаниеОповещения("ОбработатьРезультатФормы", ЭтаФорма, ДопПараметры);
        
        ОткрытьФорму("Обработка.ПодборУФ.Форма.Форма", , , , , , ОписаниеОповещ);
        
    КонецЕсли;
    
КонецПроцедуры

Код в форме документа при обработке результата:


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

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

Способ 3. Альтернатива без создания формы: Использование ПоказатьВводЧисла()

Иногда создание отдельной формы в обработке ради ввода одного числового значения является избыточным. Платформа 1С:Предприятие предоставляет разработчикам удобные асинхронные методы для быстрого ввода простых типов данных без проектирования интерфейса. Для ввода чисел предназначен метод ПоказатьВводЧисла().

Давайте посмотрим, как лаконично можно переписать нашу задачу с помощью этого встроенного инструмента:


&НаКлиенте
Процедура БыстрыйВводКоличества(Команда)
    
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;
    Если ТекущаяСтрока = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Подготавливаем контекст строки
    Контекст = Новый Структура("ИдентификаторСтроки", ТекущаяСтрока.ПолучитьИдентификатор());
    ОписаниеОповещ = Новый ОписаниеОповещения("ОбработатьБыстрыйВводЧисла", ЭтаФорма, Контекст);
    
    // Настройки диалога ввода числа
    Подсказка = "Укажите количество поставляемого товара (шт.):";
    Длина = 10;
    Точность = 0; // Нам нужны целые штуки
    
    // Вызываем стандартное немодальное диалоговое окно
    ПоказатьВводЧисла(ОписаниеОповещ, ТекущаяСтрока.Количество, Подсказка, Длина, Точность);
    
КонецПроцедуры

&НаКлиенте
Процедура ОбработатьБыстрыйВводЧисла(Результат, Параметры) Экспорт
    
    // Если пользователь нажал Отмену в стандартном диалоге, Результат будет равен Неопределено
    Если Результат <> Неопределено Тогда
        
        СтрокаТЧ = Товары.НайтиПоИдентификатору(Параметры.ИдентификаторСтроки);
        Если СтрокаТЧ <> Неопределено Тогда
            СтрокаТЧ.Количество = Результат;
            РассчитатьСуммуСтроки(СтрокаТЧ);
        КонецЕсли;
        
    КонецЕсли;
    
КонецПроцедуры

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

Способ 4. Использование ОповеститьОВыборе() (Классический множественный подбор)

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

Для таких интерактивных сценариев предназначен метод ОповеститьОВыборе(). Давайте разберем этот механизм.

Шаг 1. Открытие формы подбора

В форме документа мы открываем форму подбора, но обязательно указываем владельца формы (это позволит платформе перенаправлять события выбора).


&НаКлиенте
Процедура ОткрытьФормуПодбора(Команда)
    
    // Открываем форму, передавая в качестве владельца "ЭтаФорма"
    ПараметрыФормы = Новый Структура;
    ОткрытьФорму("Обработка.ПодборУФ.Форма.Форма", ПараметрыФормы, Элементы.Товары);
    
КонецПроцедуры

Шаг 2. Отправка данных из формы подбора

В форме подбора при совершении выбора (например, при двойном клике на строку товара или по кнопке подтверждения ввода количества) мы вызываем метод ОповеститьОВыборе. Форма при этом остается открытой!


&НаКлиенте
Процедура ВыбратьТоварИКоличество()
    
    // Формируем структуру с данными выбора
    ДанныеВыбора = Новый Структура;
    ДанныеВыбора.Вставить("Номенклатура", ТекущийТовар);
    ДанныеВыбора.Вставить("Количество", КоличествоШТ);
    
    // Оповещаем владельца о выборе (форма документа поймает это событие)
    ОповеститьОВыборе(ДанныеВыбора);
    
КонецПроцедуры

Шаг 3. Обработка выбора в документе

В форме документа нам необходимо переопределить стандартный обработчик события формы ОбработкаВыбора.


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

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

Способ 5. Продвинутый сценарий: Отмена открытия формы с возвратом результата

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

Если мы просто установим Отказ = Истина в обработчике открытия, то форма закроется, но процедура-обработчик оповещения получит значение Неопределено. Чтобы передать реальное значение в такой ситуации, используется свойство формы ОписаниеОповещенияОЗакрытии.

Рассмотрим, как это запрограммировать в модуле открываемой вспомогательной формы:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    
    Если ДоступноАвтозаполнение Тогда
        
        // Отменяем стандартное визуальное открытие окна формы
        Отказ = Истина; 
        
        // Подготавливаем результат для возврата
        АвтоЗначениеКоличества = 1;
        
        // Напрямую выполняем обработку оповещения, передавая результат в форму-владелец
        ВыполнитьОбработкуОповещения(ОписаниеОповещенияОЗакрытии, АвтоЗначениеКоличества);
        
    КонецЕсли;
    
КонецПроцедуры

Благодаря этому приему, ваша логика в документе (процедура ОбработатьРезультатФормы) отработает абсолютно прозрачно и получит результат 1, даже несмотря на то, что сама форма фактически так и не появилась на экране пользователя.

Мы подробно разобрали пять основных сценариев взаимодействия управляемых форм. Выберите подходящий под ваши бизнес-требования вариант и примените его в своей конфигурации 1С!

← На главную