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

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

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

Метод 1. Использование свойства ТекущиеДанные (Стандартный подход)

Самый распространенный и рекомендуемый способ получения данных строки на клиенте — это обращение к свойству таблицы ТекущиеДанные. Проанализируем ситуацию: когда срабатывает событие ПриИзменении, фокус ввода (курсор) всё еще находится на той строке, которую редактирует пользователь. Следовательно, эта строка является «текущей» для элемента формы «Таблица».

Рассмотрим пример кода, который должен быть написан в модуле формы:


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

Важно понимать, что ТекущиеДанные возвращают объект типа ДанныеФормыСтруктура. Это «облегченная» копия данных строки, которая доступна на стороне клиента без лишних вызовов сервера.

Метод 2. Универсальное получение значения через Элемент.ПутьКДанным

Иногда требуется создать один общий обработчик для нескольких колонок или динамически определять, какое поле было изменено. В этом случае мы не можем жестко прописать ТекущиеДанные.Номенклатура, так как имя поля может меняться. Выясним причину ошибки из сообщения автора форума: он пытался использовать Элемент.Имя в качестве ключа, но имя элемента на форме (например, «ТоварыЦена») часто не совпадает с именем реквизита в базе данных (например, «Цена»).

Разберем алгоритм универсального получения значения:

  1. Используем свойство Элемент.ПутьКДанным, которое содержит полную цепочку, например: "Объект.Товары.Цена".
  2. Отсекаем путь к самой таблице, оставляя только имя реквизита.
  3. Используем полученное имя как ключ в структуре ТекущиеДанные.

Посмотрим на пример реализации:


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

Метод 3. Работа через идентификатор строки (Надежный метод)

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

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


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

Этот метод считается более «строгим», так как он обращается непосредственно к данным коллекции Объект, а не к визуальному представлению строки в элементе формы.

Критически важные нюансы при работе с ТекущиеДанные

Проанализируем несколько технических ограничений, о которых часто забывают:

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

Разбор типичной ошибки автора темы

Автор форума писал: ЗначениеИзменяемогоЭлемента = ТекущиеДанные[Элемент.Техника].

Выясним причину ошибки: в данном случае Элемент.Техника (если это поле формы) — это объект типа ПолеФормы, а не строка. Индексатор коллекции ТекущиеДанные[...] ожидает именно строковое название (имя) реквизита.

Правильно будет так:

Если мы знаем имя заранее: ТекущиеДанные.Техника.

Если мы хотим использовать имя элемента: ТекущиеДанные["ИмяВашегоРеквизита"] (в кавычках!).

Заключение

Для большинства задач достаточно использования ТекущиеДанные. Если вы пишете тиражируемое решение или сложную логику, используйте ПутьКДанным для динамического определения имен полей. Не забывайте о проверках на Неопределено и помните о различиях между клиентом и сервером. Совместное использование этих методов позволит вам создавать стабильный и быстрый интерфейс, который мгновенно реагирует на действия пользователя.

← На главную