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