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