Как реализовать ввод на основании с вопросом пользователю в 1С 8.3

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

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

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

Причина ограничения: почему нельзя просто вызвать «Вопрос»

Для начала проанализируем ситуацию с технической точки зрения. Когда пользователь нажимает кнопку «Создать на основании», платформа выполняет следующий цикл действий:

  1. На сервере создается новый экземпляр (объект) подчиненного документа.
  2. Вызывается событие ОбработкаЗаполнения в модуле этого объекта.
  3. После завершения серверного кода данные передаются на клиент, и открывается форма нового документа.

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

Способ 1. Использование подключаемых команд БСП 3.0 (Рекомендуемый)

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

Рассмотрим по шагам, как это реализовать:

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


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

2. Теперь нам необходимо прописать сам обработчик в модуле формы или в общем модуле (в зависимости от настроек БСП). Проанализируем пример клиентской логики, где мы задаем вопрос:


&НаКлиенте
Процедура ОбработчикКоманды(ПараметрыКоманды, ДополнительныеПараметры) Экспорт
	
	ТекстВопроса = "Выберите режим заполнения документа: Заполнять цены из основания?";
	Оповещение = Новый ОписаниеОповещения("ПослеВопросаОЗаполнении", ЭтотОбъект, ПараметрыКоманды);
	
	ПоказатьВопрос(Оповещение, ТекстВопроса, РежимДиалогаВопрос.ДаНет);
	
КонецПроцедуры

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

3. На заключительном этапе перейдем в модуль объекта подчиненного документа и обработаем переданную структуру в событии ОбработкаЗаполнения.


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

Способ 2. Использование события «ОбработкаПолученияФормы»

Если вы не используете БСП или хотите оставить стандартную кнопку «Создать на основании», можно применить метод перехвата события получения формы в модуле менеджера подчиненного документа. Выясним причину выбора этого метода: он позволяет вмешаться в процесс открытия формы до того, как будет создан объект.

Рассмотрим алгоритм действий:

  1. В модуле менеджера подчиненного документа используем процедуру ОбработкаПолученияФормы.
  2. Проверяем, содержит ли параметр Параметры ключ Основание.
  3. Если основание найдено и мы еще не задавали вопрос, устанавливаем СтандартнаяОбработка = Ложь.
  4. Открываем вспомогательную форму-диалог или общую форму с вопросом.

Пример кода в модуле менеджера:


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

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

Способ 3. Интерактивное заполнение при открытии формы

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

В модуле формы подчиненного документа в событии ПриОткрытии (на клиенте) выполняем проверку:


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

&НаКлиенте
Процедура ЗаполнитьПослеВопроса(Результат, ДополнительныеПараметры) Экспорт
	Если Результат = КодВозвратаДиалога.Да Тогда
		// Вызываем серверную процедуру для заполнения объекта
		ЗаполнитьДокументНаСервере();
	КонецЕсли;
КонецПроцедуры

Подведение итогов

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

Помните основные правила:

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

← На главную