При разработке внешних обработок для платформы 1С:Предприятие 8.3 с использованием управляемых форм часто возникает необходимость передать контекст текущего документа, из которого вызывается обработка. Мы рассмотрим, как избежать ручного выбора документа в форме обработки и автоматически получать ссылку на него, используя стандартные механизмы платформы.
В управляемых формах существует несколько способов передачи данных между формами. Для внешних обработок, интегрированных через подсистему "Дополнительные отчеты и обработки", платформа предоставляет удобные механизмы автоматической передачи контекста. Это позволяет нам сосредоточиться на логике обработки, а не на механизмах выбора исходного документа.
Рассмотрим основной сценарий, когда команда внешней обработки добавляется к документу, и при ее выполнении открывается форма обработки. В этом случае система 1С автоматически может передать контекст текущего документа в параметры открываемой формы.
Прежде всего, нам необходимо убедиться, что внешняя обработка правильно зарегистрирована в модуле объекта. Мы определяем команду, которая будет открывать форму обработки. Важно установить свойство Использование команды в ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы, а также указать ИмяФормы, которую нужно открыть.
Посмотрим на пример кода модуля объекта обработки, основанный на дискуссии:
Функция СведенияОВнешнейОбработке Экспорт
ИмяОбработки = Метаданные.Представление;
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительныйОтчет; // Или любой другой вид, не обязательно ЗаполнениеОбъекта
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.Назначение.Добавить("Документ.Отпуск");
// Определяем команду, которая будет открывать форму
НоваяКоманда = ПараметрыРегистрации.Команды.Добавить;
НоваяКоманда.Представление = НСтр("ru = 'Изменение периода за который предоставляется отпуск'");
НоваяКоманда.Идентификатор = "ИзменитьПериод";
НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы; // Важно: команда открывает форму
НоваяКоманда.ИмяФормы = "Форма"; // Имя формы обработки, которую нужно открыть
НоваяКоманда.ПоказыватьОповещение = Ложь;
Возврат ПараметрыРегистрации;
КонецФункции
Процедура ПриОпределенииНастроек(Настройки) Экспорт
// Дополнительные настройки размещения команды
Настройки.Размещение.Добавить(Метаданные.Документы.Отпуск);
КонецПроцедуры
В этом примере мы регистрируем команду "ИзменитьПериод", которая при вызове открывает указанную форму обработки.
Когда форма обработки открывается через команду с типом ТипКомандыОткрытиеФормы, система 1С автоматически передает ссылку на текущий объект (документ, из которого была вызвана команда) в параметры формы. Мы можем получить эту ссылку в обработчике события ПриСозданииНаСервере формы обработки. Для удобства дальнейшей работы с документом, сохраним эту ссылку в реквизит формы.
Для этого в модуле формы внешней обработки:
ДокументОтпуска и типом ДокументСсылка.Отпуск (или соответствующим типом для вашего документа).ПриСозданииНаСервере:
// В форме обработки, в разделе "Реквизиты", добавьте реквизит:
// Имя: ДокументОтпуска
// Тип: ДокументСсылка.Отпуск (или другой тип вашего документа)
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Проверяем, передан ли параметр "Объект"
Если Параметры.Свойство("Объект") Тогда
// Сохраняем ссылку на документ в реквизит формы
ДокументОтпуска = Параметры.Объект;
Иначе
// Обработка ситуации, если ссылка не была передана (например, при прямом открытии формы)
Сообщить("Внимание: Ссылка на документ не была передана! Выберите документ вручную или убедитесь, что обработка вызывается из формы документа.", СтатусСообщения.Важное);
// Отменяем открытие формы, если документ является обязательным условием для работы обработки
// Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Теперь реквизит формы ДокументОтпуска будет содержать ссылку на документ, из которого была открыта обработка. Вы можете удалить реквизит, который ранее использовался для ручного выбора документа пользователем.
После того как ссылка на документ получена и сохранена в реквизит формы, вы можете использовать её в вашей серверной логике для чтения или изменения данных документа.
Рассмотрим, как изменить процедуру ИзменитьПериодНаСервере, используя полученный реквизит формы:
&НаСервере
Процедура ИзменитьПериодНаСервере()
// Проверяем, что ссылка на документ установлена
Если ДокументОтпуска = Неопределено Или ДокументОтпуска.Пустая() Тогда
Сообщить("Ошибка: Документ для изменения не найден в параметрах формы.");
Возврат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| Отпуск.Ссылка КАК Ссылка
|ИЗ
| Документ.Отпуск КАК Отпуск
|ГДЕ
| Отпуск.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", ДокументОтпуска); // Используем реквизит формы "ДокументОтпуска"
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ДокументОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
ДокументОбъект.НачалоПериодаЗаКоторыйПредоставляетсяОтпуск = Объект.ДатаНачала; // Объект в данном контексте - это реквизит формы обработки
ДокументОбъект.КонецПериодаЗаКоторыйПредоставляетсяОтпуск = Объект.ДатаОкончания; // Предполагается, что ДатаНачала и ДатаОкончания - другие реквизиты формы
ДокументОбъект.Записать();
КонецЦикла;
КонецПроцедуры
Таким образом, мы успешно избавились от необходимости указывать документ вручную в форме обработки, получая его контекст автоматически при открытии формы.
В некоторых случаях внешняя обработка может быть предназначена не для открытия отдельной формы с последующим выбором документа, а для непосредственного выполнения действий над документом или массивом документов. Такой подход реализуется, если обработка зарегистрирована как ВидОбработкиЗаполнениеОбъекта.
В модуле объекта обработки мы определяем команду заполнения, которая указывает на вашу функцию-обработчик (например, Подключаемый_ЗаполнитьОбъект). Эта команда будет доступна в меню "Заполнить" или "Дополнительно" формы документа.
Процедура ДобавитьКомандыЗаполнения(КомандыЗаполнения, Параметры) Экспорт
Команда = КомандыЗаполнения.Добавить;
Команда.Представление = НСтр("ru = 'Изменить период'");
Команда.Идентификатор = "ЗаполнитьОбъект"; // Идентификатор команды заполнения
Команда.Обработчик = "Подключаемый_ЗаполнитьОбъект"; // Имя функции-обработчика в модуле формы или объекта
Команда.МножественныйВыбор = Ложь; // Если нужно обрабатывать только один документ
Команда.ИзменяетВыбранныеОбъекты = Истина;
Команда.ВидимостьВФормах = "ФормаДокумента";
Команда.РежимЗаписи = "НеЗаписывать";
// ... другие параметры
КонецПроцедуры
В модуле формы обработки (или в модуле объекта, если функция объявлена там) функция-обработчик, указанная в Команда.Обработчик, получит массив объектов в своем первом параметре МассивОбъектов. Если выбрана опция МножественныйВыбор = Ложь, то МассивОбъектов будет содержать один элемент – ссылку на текущий документ.
Посмотрим на пример, как использовать параметр МассивОбъектов в функции Подключаемый_ЗаполнитьОбъект:
&НаКлиенте
Функция Подключаемый_ЗаполнитьОбъект(МассивОбъектов, ПараметрыВыполнения) Экспорт
Если МассивОбъектов.Количество() > 0 Тогда
// Если ожидается один документ, берем первый элемент массива
СсылкаНаДокумент = МассивОбъектов[0];
// Если требуется интерактивное взаимодействие, можно открыть форму обработки,
// передав ей эту ссылку как параметр:
// ПараметрыДляФормы = Новый Структура("ИсходныйДокумент", СсылкаНаДокумент);
// ОткрытьФорму("ВнешняяОбработка.ИмяВашейОбработки.Форма", ПараметрыДляФормы);
// Если форма не нужна, и нужно сразу выполнить серверную логику:
ИзменитьПериодНаСервере(СсылкаНаДокумент); // Передаем ссылку на сервер для обработки
Иначе
Сообщить("Документ для заполнения не выбран.", СтатусСообщения.Важное);
КонецЕсли;
Возврат Истина; // Для обработчиков заполнения важно вернуть Истина
КонецФункции
&НаСервере
Процедура ИзменитьПериодНаСервере(СсылкаДокумента)
// Используем переданную ссылку на документ
Если СсылкаДокумента.Пустая() Тогда
Сообщить("Ошибка: Документ для изменения не найден.");
Возврат;
КонецЕсли;
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| Отпуск.Ссылка КАК Ссылка
|ИЗ
| Документ.Отпуск КАК Отпуск
|ГДЕ
| Отпуск.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", СсылкаДокумента); // Используем переданную ссылку
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
ДокументОбъект = ВыборкаДетальныеЗаписи.Ссылка.ПолучитьОбъект();
// Если эта процедура вызывается без открытия формы, то значения
// ДатаНачала и ДатаОкончания должны быть переданы как параметры
// или получены иным способом. Например:
ДокументОбъект.НачалоПериодаЗаКоторыйПредоставляетсяОтпуск = '20230101'; // Пример: если значения заданы константой
ДокументОбъект.КонецПериодаЗаКоторыйПредоставляетсяОтпуск = '20231231'; // Пример: если значения заданы константой
ДокументОбъект.Записать();
КонецЦикла;
КонецПроцедуры
Этот способ более подходит для ситуаций, когда обработка выполняет действие без интерактивного взаимодействия пользователя в отдельной форме, или когда форма открывается уже после получения ссылки на объект для дальнейших действий.
Если вы открываете форму внешней обработки программно (например, из клиентской процедуры команды документа, которая не является частью подсистемы "Дополнительные отчеты и обработки"), вы можете явно передать ссылку на документ через параметры функции ОткрытьФорму().
На стороне документа, в клиентской процедуре, которая вызывает вашу обработку, мы получаем ссылку на текущий документ и передаем ее в виде структуры параметров при вызове функции ОткрытьФорму().
&НаКлиенте
Процедура ОткрытьОбработкуИПередатьДокумент(Команда)
// Получаем ссылку на текущий объект (документ)
СсылкаНаТекущийДокумент = Объект.Ссылка;
// Создаем структуру параметров для передачи в форму обработки
ПараметрыФормы = Новый Структура("ИсходныйДокумент", СсылкаНаТекущийДокумент);
// Открываем форму внешней обработки, передавая параметры
ОткрытьФорму("ВнешняяОбработка.ИмяВашейОбработки.Форма", ПараметрыФормы);
КонецПроцедуры
В модуле формы внешней обработки, в процедуре ПриСозданииНаСервере, мы сможем получить переданный параметр из структуры Параметры.
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если Параметры.Свойство("ИсходныйДокумент") Тогда
// Сохраняем ссылку на документ в реквизит формы
ДокументОтпуска = Параметры.ИсходныйДокумент;
Иначе
Сообщить("Ссылка на исходный документ не была передана при программном открытии формы!");
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
Этот метод дает максимальный контроль над передачей параметров, но требует программной реализации открытия формы, а не использования стандартных механизмов регистрации команд дополнительных отчетов и обработок.
Заключение:
Мы видим, что для получения ссылки на документ в форме внешней обработки существует несколько действенных подходов. Выбор конкретного метода зависит от того, каким образом вы регистрируете и вызываете вашу обработку. В большинстве случаев, когда обработка вызывается из команды документа и открывает форму, наиболее чистым решением является использование параметра Объект в ПриСозданииНаСервере формы обработки. Если же обработка является обработкой заполнения объектов, то следует использовать параметр МассивОбъектов в функции-обработчике.