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