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