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

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

При работе с табличными частями в управляемых формах 1С часто возникает задача: после того как пользователь выбрал значение в одной из ячеек (например, контрагента), нужно выполнить какие-то действия с данными именно той строки, где произошло это событие. Автор вопроса столкнулся с тем, что в обработчике события ОбработкаВыбора он видит только выбранное значение, но не понимает, как получить доступ к другим данным строки, в которую это значение будет помещено.

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

Решение 1: Получение данных через свойство "ТекущиеДанные"

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

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

Рассмотрим на примере:

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

  1. Создадим для поля "Контрагент" в табличной части обработчик события ОбработкаВыбора.
  2. В коде обработчика получим доступ к текущей строке.

&НаКлиенте
Процедура ТоварыКонтрагентОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)

    // Проверяем, что значение действительно было выбрано
    Если НЕ ЗначениеЗаполнено(ВыбранноеЗначение) Тогда
        Возврат;
    КонецЕсли;

    // Получаем доступ к данным текущей (активной) строки табличной части "Товары"
    ДанныеТекущейСтроки = Элементы.Товары.ТекущиеДанные;

    // Теперь мы можем работать с данными этой строки
    // Например, выведем сообщение с номенклатурой из этой же строки
    Сообщить("Выбран контрагент '" + ВыбранноеЗначение + "' для номенклатуры '" + ДанныеТекущейСтроки.Номенклатура + "'");

    // Или выполним какую-то логику, например, изменим другое поле в этой же строке
    ДанныеТекущейСтроки.Сумма = РассчитатьСуммуПоКонтрагенту(ВыбранноеЗначение);

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

Как видите, конструкция Элементы.ИмяТабличнойЧасти.ТекущиеДанные — это ключ к решению. Она возвращает объект типа ДанныеФормыЭлементКоллекции, который соответствует активной строке табличной части, и через него можно как читать, так и изменять данные.

Решение 2: Использование декларативных механизмов — "ПараметрыВыбора" и "СвязиПараметровВыбора"

Часто необходимость в обработчиках НачалоВыбора и ОбработкаВыбора возникает из-за желания настроить динамический отбор. Например, показывать только тех контрагентов, которые относятся к организации, указанной в другой колонке той же строки. Для таких задач в платформе есть более удобные и "правильные" инструменты, не требующие написания кода.

Свойство "ПараметрыВыбора"

Используется для установки статического отбора, который не меняется в процессе работы пользователя. Например, показывать в поле выбора только контрагентов с флагом "Поставщик".

Это настраивается в палитре свойств элемента формы в конфигураторе. Вы просто добавляете новый элемент отбора и указываете для него фиксированное значение.

Свойство "СвязиПараметровВыбора"

Это более мощный механизм для динамической фильтрации. Он позволяет связать параметр отбора поля выбора со значением другого поля на форме (в том числе из той же строки табличной части).

Проанализируем ситуацию: в табличной части "Товары" есть колонка "Организация" и "Контрагент". Мы хотим, чтобы при выборе контрагента форма выбора открывалась с отбором по организации из текущей строки.

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

Вот и все! Теперь платформа будет автоматически отслеживать значение в колонке "Организация" и при открытии формы выбора контрагента применять нужный отбор для каждой строки индивидуально. Код писать не нужно.

Если форма создается программно, эти связи также можно настроить. Это актуально, так как в обсуждении автор упомянул, что форма создается кодом.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)

    // Пример программного добавления поля и настройки связи
    НовыйЭлемент = Элементы.Добавить("ТоварыКонтрагент", Тип("ПолеФормы"), Элементы.Товары);
    НовыйЭлемент.Вид = ВидПоляФормы.ПолеВвода;
    НовыйЭлемент.ПутьКДанным = "Объект.Товары.Контрагент";

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

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

Решение 3: Правильное использование события "НачалоВыбора"

Если логика отбора сложнее, чем простая связь полей, и требует вычислений, то без обработчика НачалоВыбора не обойтись. Однако и здесь можно избежать использования ОбработкаВыбора, если основная цель — просто поместить выбранное значение в ячейку.

Ключевой момент — это правильное использование функции ОткрытьФорму(). Третьим параметром она принимает "Владельца" — элемент формы, который инициировал открытие. Если передать туда элемент, из которого происходит выбор, платформа сама поймет, куда вернуть результат.

Посмотрим на пример: отбор контрагентов по типу, который указан в другой колонке.


&НаКлиенте
Процедура ТоварыКонтрагентНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)

    // Получаем данные текущей строки, чтобы использовать их для отбора
    ТекущаяСтрока = Элементы.Товары.ТекущиеДанные;

    // Если в строке указан тип контрагента, установим отбор
    Если ЗначениеЗаполнено(ТекущаяСтрока.ТипКонтрагента) Тогда

        // Отменяем стандартное открытие формы выбора
        СтандартнаяОбработка = Ложь;

        // Создаем структуру для параметров формы выбора
        ПараметрыФормы = Новый Структура;
        СтруктураОтбора = Новый Структура("ТипКонтрагента", ТекущаяСтрока.ТипКонтрагента);
        ПараметрыФормы.Вставить("Отбор", СтруктураОтбора);

        // Открываем форму выбора, передавая в качестве владельца (3-й параметр)
        // сам элемент, который вызвал событие.
        // Платформа автоматически поместит выбранное значение в это поле.
        ОткрытьФорму("Справочник.Контрагенты.ФормаВыбора", ПараметрыФормы, Элемент);

    КонецЕсли;

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

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

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

← На главную