Как исправить ошибку «Текущие данные таблицы недоступны на сервере» в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке управляемых форм в 1С:Предприятии 8.3 разработчики часто сталкиваются с исключением: «Ошибка при получении значения атрибута контекста (ТекущиеДанные): Текущие данные таблицы недоступны на сервере». Проанализируем, почему возникает данная ошибка, как устроена работа с таблицами формы в контексте клиента и сервера, а также разберем правильные методы изменения и чтения данных строк.

Причина возникновения ошибки

В управляемом интерфейсе 1С действует строгое разделение контекстов выполнения кода:

  1. Клиентский контекст: отвечает за отображение интерфейса, обработку действий пользователя и визуальное состояние элементов. Свойство ТекущиеДанные таблицы формы возвращает объект типа ДанныеФормыЭлементКоллекции, соответствующий визуально выделенной пользователем строке, и доступно только на клиенте.
  2. Серверный контекст: отвечает за бизнес-логику и работу с базой данных. На сервере интерфейс не визуализируется, поэтому свойство ТекущиеДанные у элементов формы не существует и обращение к нему вызывает исключительную ситуацию.

Если в коде серверной процедуры при обходе табличной части документа написать:


Для Каждого СтрокаТЧ Из Объект.Начисления Цикл
    // ОШИБКА: Элементы.Начисления.ТекущиеДанные недоступны на сервере!
    Элементы.Начисления.ТекущиеДанные.Результат = Элементы.Начисления.ТекущиеДанные.Результат + 1000;
КонецЦикла;

Такой код гарантированно приведет к ошибке, так как сервер не знает, какая строка является текущей в интерфейсе через коллекцию элементов.

Решение 1. Изменение данных через итератор цикла

Если задача заключается в обходе строк табличной части на сервере и изменении значений реквизитов, обращаться к элементу формы вообще не требуется. Переменная цикла уже содержит ссылку на изменяемую строку коллекции ДанныеФормыКоллекция (например, Объект.Начисления).

Посмотрим на пример правильного обхода и изменения реквизитов строки:


&НаСервере
Процедура ПересчитатьНачисленияНаСервере()
    Для Каждого СтрокаТЧ Из Объект.Начисления Цикл
        // Обращаемся напрямую к свойствам текущей строки коллекции
        СтрокаТЧ.Результат = СтрокаТЧ.Результат + 1000;
    КонецЦикла;
КонецПроцедуры

Все изменения, внесенные в реквизит Объект на сервере, автоматически передаются обратно на клиент и отображаются в интерфейсе после завершения серверного вызова.

Решение 2. Получение текущей выделенной строки на сервере

Если серверной процедуре действительно необходимо знать, на какой именно строке пользователь спозиционировал курсор, используем связку свойства ТекущаяСтрока и метода НайтиПоИдентификатору().

В отличие от ТекущиеДанные, свойство ТекущаяСтрока доступно и на сервере. Оно хранит числовой идентификатор активной строки (ИдентификаторСтроки).

Разберем по шагам, как получить строку по идентификатору:


&НаСервере
Процедура ОбработатьТекущуюСтрокуНаСервере()
    Идентификатор = Элементы.Начисления.ТекущаяСтрока;
    
    Если Идентификатор <> Неопределено Тогда
        СтрокаДанных = Объект.Начисления.НайтиПоИдентификатору(Идентификатор);
        Если СтрокаДанных <> Неопределено Тогда
            СтрокаДанных.Результат = СтрокаДанных.Результат + 1000;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Также хорошей практикой является передача идентификатора строки с клиента в серверную процедуру в качестве параметра:


&НаКлиенте
Процедура ВыполнитьДействие(Команда)
    ИдентификаторСтроки = Элементы.Начисления.ТекущаяСтрока;
    Если ИдентификаторСтроки <> Неопределено Тогда
        ОбработатьСтрокуНаСервере(ИдентификаторСтроки);
    КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ОбработатьСтрокуНаСервере(ИдентификаторСтроки)
    // Серверная обработка конкретной строки
КонецПроцедуры

Ошибки в сопутствующей логике выборки и сравнения

Рассмотрим частые ошибки, которые сопутствуют подобным алгоритмам:

  1. Неправильное заполнение массива из выборки запроса:

    При написании конструкции Массив.Добавить(Выборка) внутри цикла Пока Выборка.Следующий() в массив каждый раз помещается один и тот же объект выборки. После завершения цикла все элементы массива будут указывать на последнюю запись. В массив нужно добавлять конкретное значение (например, Массив.Добавить(Выборка.Сотрудник)) либо сразу выгружать результат в таблицу: Таблица = Запрос.Выполнить().Выгрузить().

  2. Сравнение по наименованию вместо ссылки:

    Конструкции вида СтрокаТЧ.Сотрудник.Наименование = Сотр.Наименование приводят к неявным обращениям к базе данных через точку для каждой строки таблицы. В 1С ссылочные типы всегда следует сравнивать напрямую по ссылке: СтрокаТЧ.Сотрудник = Сотр.Сотрудник.

  3. Использование поиска по коллекции:

    Для сопоставления данных удобнее использовать метод Найти() коллекции строк формы вместо ручного перебора с индексами:

    
    Выборка = Запрос.Выполнить().Выбрать();
    Пока Выборка.Следующий() Цикл
        СтрокаТЧ = Объект.Начисления.Найти(Выборка.Сотрудник, "Сотрудник");
        Если СтрокаТЧ <> Неопределено Тогда
            СтрокаТЧ.Результат = СтрокаТЧ.Результат + Выборка.Сумма;
        КонецЕсли;
    КонецЦикла;
    

Рекомендации по обработчику «ПриАктивизацииСтроки»

Событие ПриАктивизацииСтроки возникает каждый раз при перемещении пользователя по табличной части. Вызов серверных процедур в данном обработчике приводит к постоянным сетевым вызовам и зависанию интерфейса при навигации стрелками клавиатуры. Если серверный расчет обязателен при переходе по строкам, рекомендуется использовать клиентский обработчик ожидания через ПодключитьОбработчикОжидания с интервалом 0.2–0.3 секунды.

← На главную