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

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

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

Разберем по шагам, почему программно назначенные обработчики могут игнорироваться платформой, как правильно связать события с кодом и как гарантированно получить координаты выбранной ячейки и содержащиеся в ней данные.

Причины, по которым не срабатывает программно назначенный обработчик

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

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

Способ 1. Получение колонки и строки через событие ячейки «ПриИзменении»

Если задача заключается именно в реакции на ввод или редактирование значения, действие привязывается к каждому программно созданному полю ввода внутри цикла создания колонок.

Посмотрим на пример правильного серверного кода создания колонок и привязки действия:


&НаСервере
Процедура СоздатьКолонкиТаблицыНаСервере()
    ТаблицаПолейВыбора = Элементы.Найти("ТЗН");
    
    Для Каждого Колонка Из ТабличкаДанных.Колонки Цикл
        НовоеПоле = Элементы.Добавить(Колонка.Имя, Тип("ПолеФормы"), ТаблицаПолейВыбора);
        НовоеПоле.Вид = ВидПоляФормы.ПолеВвода;
        НовоеПоле.ПутьКДанным = "Табличка." + Колонка.Имя;
        
        // Назначаем клиентский обработчик
        НовоеПоле.УстановитьДействие("ПриИзменении", "Колонка_ПриИзменении");
    КонецЦикла;
КонецПроцедуры

Теперь объявим обработчик на клиенте с корректной сигнатурой, принимающей элемент управления:


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

Способ 2. Обработка клика через событие таблицы «Выбор»

Когда редактирование ячеек пользователю запрещено, а требуется реагировать на двойной клик или нажатие клавиши Enter (например, для открытия детального расписания или карточки записи), навешивать обработчики на каждое поле не требуется. Намного эффективнее назначить обработчик штатному событию Выбор самой таблицы формы.

Проанализируем назначение действия для таблицы формы на сервере:


&НаСервере
Процедура НастроитьСобытияТаблицы()
    ТаблицаФормы = Элементы.ТЗН;
    ТаблицаФормы.УстановитьДействие("Выбор", "ТЗН_Выбор");
КонецПроцедуры

Событие Выбор у таблицы формы передает в клиентскую процедуру готовые параметры: ссылку на выбранную строку и поле (колонку), по которому был произведен клик:


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

Способ 3. Отслеживание перемещения через «ПриАктивизацииЯчейки»

Если реакция интерфейса должна происходить при обычном одиночном клике мыши или при перемещении по таблице стрелками клавиатуры, используем событие таблицы ПриАктивизацииЯчейки.

Разберем клиентский обработчик для этого случая:


&НаКлиенте
Процедура ТЗН_ПриАктивизацииЯчейки(Элемент)
    // Элемент в данном случае — это ТаблицаФормы
    ТекущаяКолонка = Элемент.ТекущийЭлемент; // Объект ПолеФормы
    ТекущиеДанные = Элемент.ТекущиеДанные;   // Данные строки формы
    
    Если ТекущаяКолонка <> Неопределено И ТекущиеДанные <> Неопределено Тогда
        ИмяКолонки = ТекущаяКолонка.Имя;
        ЗначениеЯчейки = ТекущиеДанные[ИмяКолонки];
    КонецЕсли;
КонецПроцедуры

Важные особенности работы с динамическими реквизитами

Рассмотрим подводные камни, возникающие при динамической генерации полей и строк:

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