Как в динамическом списке получить текущую активную колонку и ее значение?

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

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

Постановка задачи и базовые понятия

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

Для решения нам понадобятся два ключевых свойства таблицы формы:

  1. ТекущийЭлемент (CurrentItem) — это объект типа ПолеФормы, который соответствует ячейке, находящейся в фокусе.
  2. ТекущиеДанные (CurrentData) — это структура (точнее, объект ДанныеФормыСтруктура), содержащая значения всех полей текущей строки динамического списка.

Шаг 1: Получение имени текущей колонки на клиенте

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


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

Важно различать Имя и ПутьКДанным. Имя — это внутренний идентификатор элемента на форме (например, "СписокНаименование"), а ПутьКДанным — это ссылка на поле источника данных (например, "Объект.Список.Наименование" или просто "Наименование"). В большинстве случаев для поиска значения в структуре данных нам понадобится именно вторая информация, но очищенная от префикса списка.

Шаг 2: Получение значения из текущей колонки

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


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

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

Проблема составных путей данных

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

Если вы столкнулись с тем, что ДанныеСтроки[ИмяПоля] вызывает ошибку, проанализируем причины:

Решение через серверный вызов (самый надежный способ)

Если на клиенте получить значение не удается (например, для пользовательских полей или вычисляемых колонок), разберем метод с обращением к серверу. Мы передадим идентификатор строки и имя поля, чтобы получить точные данные из базы или схемы компоновки.


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

&НаСервереБезКонтекста
Функция ПолучитьЗначениеНаСервере(СсылкаНаОбъект, ПутьКДанным)
    
    // Здесь можно выполнить запрос к БД или вычислить значение
    // ПутьКДанным может потребовать очистки от префикса "Список."
    // ... логика получения данных ...
    Возврат Результат;
    
КонецФункции

Нюансы и особенности платформы

Важно помнить, что в старых релизах платформы (например, 8.3.10) наблюдались ошибки, при которых обращение к ТекущийЭлемент в определенных условиях приводило к аварийному завершению работы приложения. В современных версиях (8.3.15+) эта проблема устранена.

Также проанализируем использование события ПриАктивизацииЯчейки. Если ваша цель — просто визуально реагировать на перемещение курсора, это событие подходит лучше. Однако ПередНачаломИзменения идеально подходит именно для блокировки или переопределения логики редактирования. Если в этом событии установить параметр Отказ = Истина, стандартное окно редактирования не откроется, и вы сможете вызвать свою процедуру.

Резюмируем: для стабильной работы используйте Элементы.Список.ТекущийЭлемент.ПутьКДанным для определения колонки и Элементы.Список.ТекущиеДанные для получения значения. Если данные отсутствуют в структуре — проверьте свойство "Использовать всегда" в настройках динамического списка.

← На главную