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