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