Как получить значение активной ячейки табличной части в управляемой форме 1С

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

В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача динамического получения значения, которое находится в ячейке, выбранной пользователем. Это может потребоваться для реализации контекстных подсказок, вывода дополнительной информации о товаре или автоматического заполнения связанных полей. Несмотря на кажущуюся простоту, задача имеет свои нюансы, связанные с архитектурой управляемых форм.

В этой статье мы подробно разберем, как правильно определить имя колонки, получить доступ к данным текущей строки и избежать типичных ошибок, таких как избыточные серверные вызовы.

Основы: работа с текущими данными и элементами формы

Для начала проанализируем, как управляемая форма хранит информацию о фокусе в таблице. У объекта ТаблицаФормы (который отображает нашу табличную часть) есть два ключевых свойства:

  1. ТекущиеДанные — это структура (тип ДанныеФормыКоллекцияЭлемент), содержащая значения всех полей в выделенной строке.
  2. ТекущийЭлемент — это ссылка на конкретный элемент формы (поле ввода, поле флажка и т.д.), в котором сейчас находится курсор.

Чтобы получить значение ячейки, нам нужно знать имя реквизита, который отображается в этом элементе. Рассмотрим самый простой способ реализации.

Способ 1: Получение значения через имя элемента

Этот метод основан на допущении, что имя элемента формы (колонки) совпадает с именем реквизита табличной части или может быть из него вычислено. Разберем пример кода в обработчике события ПриАктивизацииЯчейки:


&НаКлиенте
Процедура ТоварыПриАктивизацииЯчейки(Элемент)
    
    // Проверяем, что в таблице есть данные
    Если Элемент.ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    // Получаем имя текущего элемента (колонки)
    ИмяЭлемента = Элемент.ТекущийЭлемент.Имя;
    
    // Если имя элемента формы совпадает с именем реквизита:
    Попытка
        ЗначениеЯчейки = Элемент.ТекущиеДанные[ИмяЭлемента];
        Сообщить("Выбранное значение: " + ЗначениеЯчейки);
    Исключение
        // Имя элемента формы может отличаться от имени реквизита
    КонецПопытки;
    
КонецПроцедуры

Однако на практике имена колонок часто имеют префиксы (например, ТоварыНоменклатура вместо просто Номенклатура). В этом случае нам потребуется очистить имя от названия таблицы. Посмотрим, как это сделать программно:


ИмяТаблицы = "Товары";
ИмяКолонки = СтрЗаменить(Элемент.ТекущийЭлемент.Имя, ИмяТаблицы, "");
Значение = Элемент.ТекущиеДанные[ИмяКолонки];

Способ 2: Использование свойства ПутьКДанным (надежный метод)

Рассмотрим ситуацию, когда разработчик переименовал элементы формы вручную, и они никак не коррелируют с именами реквизитов. В этом случае свойство Имя нам не поможет. Самый надежный способ — обратиться к свойству ПутьКДанным. Проанализируем, как извлечь из него имя реквизита.

Свойство ПутьКДанным обычно имеет вид Объект.Товары.Номенклатура. Нам нужно получить последнюю часть этой строки.


&НаКлиенте
Функция ПолучитьИмяРеквизитаИзПути(ПутьКДанным)
    // Разделяем строку по точкам
    ЧастиПути = СтрРазделить(ПутьКДанным, ".");
    // Нас интересует последний сегмент
    Возврат ЧастиПути[ЧастиПути.ВГраница()];
КонецФункции

&НаКлиенте
Процедура ТаблицаПриАктивизацииЯчейки(Элемент)
    Если Элемент.ТекущиеДанные = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Путь = Элемент.ТекущийЭлемент.ПутьКДанным;
    Если ПустаяСтрока(Путь) Тогда
        Возврат; // У колонки может не быть привязки к данным (например, кнопка)
    КонецЕсли;
    
    ИмяРеквизита = ПолучитьИмяРеквизитаИзПути(Путь);
    
    // Теперь безопасно получаем значение
    Значение = Элемент.ТекущиеДанные[ИмяРеквизита];
КонецПроцедуры

Проблема вложенных реквизитов и "точек"

Важно помнить о полях, которые выводят данные через точку. Например, в табличную часть выведен Артикул номенклатуры (путь: Объект.Товары.Номенклатура.Артикул). В объекте ТекущиеДанные поля Артикул не существует — там есть только Номенклатура. Попытка обращения ТекущиеДанные["Артикул"] вызовет ошибку.

В такой ситуации мы должны проверить наличие поля в коллекции. Если поле отсутствует, возможно, стоит использовать ЭтаФорма[ПутьКДанным], но это потребует правильной обработки идентификатора строки. Рассмотрим, как получить значение в таких сложных случаях:


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

Внимание: Использование функции Вычислить() на клиенте допустимо, но требует осторожности и понимания контекста выполнения.

Оптимизация: избегаем серверных вызовов

Согласно документации 1С, в обработчике события ПриАктивизацииЯчейки запрещено использовать серверные методы формы (директива &НаСервере). Это связано с тем, что данное событие срабатывает крайне часто (при каждом движении курсора), и вызовы сервера приведут к катастрофическому падению производительности и "замиранию" интерфейса.

Чтобы решить задачу эффективно, воспользуемся кешированием. Выясним связи между именами элементов и именами реквизитов заранее, при создании формы.

  1. Создадим на форме реквизит типа Соответствие или Структура для хранения карты путей.
  2. Заполним её один раз на сервере.
  3. На клиенте будем мгновенно получать имя реквизита из кеша.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Инициализируем кеш колонок
    КешКолонок = Новый Соответствие;
    Для Каждого Эл Из Элементы.Товары.ПодчиненныеЭлементы Цикл
        Части = СтрРазделить(Эл.ПутьКДанным, ".");
        Если Части.Количество() > 0 Тогда
            КешКолонок.Вставить(Эл.Имя, Части[Части.ВГраница()]);
        КонецЕсли;
    КонецЦикла;
    // Помещаем кеш в реквизит формы (нужно предварительно создать его в редакторе)
    // Либо передаем на клиент через временное хранилище/параметры
КонецПроцедуры

Использование обработчика ожидания

Если вам все же необходимо выполнить тяжелые вычисления или сходить на сервер при активации ячейки, проанализируем технику с использованием ПодключитьОбработчикОжидания. Это позволит "отложить" выполнение кода на доли секунды. Если пользователь быстро пролистывает таблицу, код сработает только на той ячейке, на которой он остановится.


&НаКлиенте
Процедура ТоварыПриАктивизацииЯчейки(Элемент)
    // Сбрасываем предыдущий вызов и подключаем новый через 0.1 сек
    ОтключитьОбработчикОжидания("ВыполнитьОбработкуЯчейки");
    ПодключитьОбработчикОжидания("ВыполнитьОбработкуЯчейки", 0.1, Истина);
КонецПроцедуры

&НаКлиенте
Процедура ВыполнитьОбработкуЯчейки()
    ТекущийЭлемент = Элементы.Товары.ТекущийЭлемент;
    Данные = Элементы.Товары.ТекущиеДанные;
    // Здесь выполняем нужные действия
КонецПроцедуры

Подведем итоги

Для получения значения активной ячейки мы выяснили следующие правила:

Применяя эти подходы, вы сможете создавать быстрые и надежные интерфейсы, которые корректно обрабатывают действия пользователя в табличных частях документов.

← На главную