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