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