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

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

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

В этой статье мы подробно разберем, как правильно обрабатывать нажатия на таблицу, почему стандартное обращение к элементу формы может вернуть «ДанныеФормыЭлементКоллекции» вместо нужного значения, и как реализовать универсальный механизм получения данных из любой колонки.

Понимание архитектуры управляемых форм

Прежде чем переходить к коду, давайте проанализируем, как 1С работает с таблицами на форме. В управляемом приложении существует четкое разделение между Данными (реквизитом формы типа ТаблицаЗначений или Список) и Элементом формы (визуальным отображением этих данных).

Когда вы обращаетесь к Элементы.Список.ТекущиеДанные, система возвращает вам объект типа ДанныеФормыЭлементКоллекции. Это не конкретное значение «Номенклатура» или «Цена», а вся строка таблицы целиком. Чтобы вытащить из этой строки значение конкретной ячейки, нам нужно знать имя колонки.

Выбор подходящего события: «Выбор» против «ПриАктивизацииЯчейки»

Выясним причину, по которой выбор события определяет удобство работы пользователя:

  1. Событие «Выбор» (Selection): Срабатывает при двойном клике мышкой или нажатии клавиши Enter. Это наиболее подходящий вариант для открытия документов или выполнения значимых действий.
  2. Событие «ПриАктивизацииЯчейки» (OnActivateCell): Срабатывает каждый раз, когда пользователь просто перемещает курсор по таблице (даже стрелками на клавиатуре). Используйте его только если вам нужно обновлять какую-то информацию на форме «на лету» без лишних кликов.

Рассмотрим реализацию через событие Выбор, так как именно оно чаще всего требуется в бизнес-задачах.

Метод 1: Статическое получение значения (когда имя колонки известно)

Если ваша логика завязана на одну конкретную колонку (например, вы всегда хотите открывать карточку товара, вне зависимости от того, куда нажал пользователь в строке), рассмотрим следующий пример кода:


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

Метод 2: Динамическое получение значения (универсальный способ)

Теперь разберем более сложную и интересную ситуацию: нам нужно получить значение именно той ячейки, в которую «тыкнул» пользователь. Здесь мы не можем жестко прописать имя колонки через точку, так как колонки могут быть разными. Проанализируем, как использовать параметр Поле, который передает платформа в обработчик события.

Ключевым моментом здесь является использование квадратных скобок для обращения к свойству объекта по строковому имени переменной.


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

КонецПроцедуры

Тонкости использования Поле.Имя и Поле.ПутьКДанным

Рассмотрим подробнее важный нюанс, на котором часто спотыкаются новички. В обработчике события параметр Поле — это объект типа ПолеФормы.

Если вы используете конструкцию ДанныеСтроки[Поле.Имя], и имя колонки в таблице значений (реквизите) не совпадает с именем элемента на форме, вы получите ошибку. Поэтому правильнее всего либо называть их одинаково, либо использовать логику очистки пути к данным от лишних префиксов.

Пример реализации с открытием разных документов

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


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

КонецПроцедуры

Почему Элементы.Список.ТекущаяСтрока — это идентификатор, а не данные?

Проанализируем ситуацию: в Сообщении 11 пользователь пытался использовать Элементы.Список.ТекущаяСтрока как индекс массива. Это распространенная ошибка. В управляемых формах ТекущаяСтрока — это Идентификатор (число), а не индекс (0, 1, 2...).

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


// Если "Список" - это реквизит формы типа ТаблицаЗначений
СтрокаДанных = Список.НайтиПоИдентификатору(Элементы.Список.ТекущаяСтрока);

Однако использование Элементы.Список.ТекущиеДанные является более современным и предпочтительным способом, так как он сразу возвращает нужный объект без поиска по всей таблице.

Итоги и рекомендации

Подводя итог нашему разбору, выделим основные правила работы с ячейками в 1С:

  1. Для получения значения ячейки всегда проверяйте ТекущиеДанные на Неопределено. Это убережет вашу программу от аварийного завершения в пустых таблицах.
  2. Для доступа к значению по динамическому имени используйте квадратные скобки: Строка[ИмяКолонки].
  3. Помните, что Поле.Имя относится к визуальному элементу, а доступ к данным в ТекущиеДанные осуществляется по именам колонок реквизита.
  4. Если вы работаете в отчете, всегда рассматривайте возможность использования стандартной Обработки расшифровки системы компоновки данных (СКД), которая зачастую делает всю описанную выше работу автоматически.

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

← На главную