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

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

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

В этой статье мы подробно разберем, почему популярные строковые методы получения имен колонок опасны, как правильно использовать свойство ПутьКДанным, и как реализовать максимально быстрое решение на клиенте вообще без вызовов сервера.

В чем опасность «наивного» строкового метода?

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


// Пример небезопасного кода ("костыля")
ИмяТаблицы = ЭтаФорма.Элементы.ф_Таб.Имя; 
ИмяЭлементаКолонки = ЭтаФорма.Элементы.ф_Таб.ТекущийЭлемент.Имя; 
ИмяКолонки = СокрЛП(Прав(ИмяЭлементаКолонки, СтрДлина(ИмяЭлементаКолонки) - СтрДлина(ИмяТаблицы)));

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

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

Использование свойства «ПутьКДанным» на сервере

Единственным надежным способом связать элемент формы с реальным реквизитом является свойство ПутьКДанным. Оно хранит точный путь к реквизиту (например, ф_Таб.Цена или Объект.Товары.Номенклатура).

Важное ограничение: Обращаться к свойству ПутьКДанным элементов формы можно только в серверном контексте. Попытка прочитать его на клиенте вызовет критическую ошибку выполнения.

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


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

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

Лучшая практика: Клиентское решение с кэшированием (без вызовов сервера)

Что делать, если имя текущей колонки вам требуется определять на клиенте интерактивно (например, при активизации ячейки для условного оформления или мгновенных расчетов)? Вызывать сервер при каждом переходе пользователя из ячейки в ячейку — очень плохая идея, которая приведет к «зависанию» интерфейса и перегрузке базы данных.

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

Шаг 1. Объявим переменную в самом верху модуля управляемой формы (вне процедур и функций). Эта переменная будет доступна во всех клиентских процедурах модуля:

Перем СоответствиеКолонок; // Кэш соответствия Имени Элемента и Имени Реквизита

Шаг 2. Наполним наше соответствие на сервере в момент инициализации формы и передадим его на клиент при открытии:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Заполняем кэш один раз при открытии формы
    СоответствиеКолонок = ПолучитьКартуКолонокНаСервере();
КонецПроцедуры

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

Шаг 3. Теперь мы можем мгновенно, без единого серверного вызова, получать имя колонки в любом клиентском событии (например, в обработчике активизации ячейки таблицы):


&НаКлиенте
Процедура ф_ТабПриАктивизацииЯчейки(Элемент)
    ТекущийЭлементФормы = Элементы.ф_Таб.ТекущийЭлемент;
    Если ТекущийЭлементФормы <> Неопределено Тогда
        ИмяКолонки = "";
        // Быстро получаем имя колонки из кэша в памяти клиента
        Если СоответствиеКолонок.Свойство(ТекущийЭлементФормы.Имя, ИмяКолонки) Тогда
            // Переменная ИмяКолонки теперь содержит точное имя реквизита (например, "Номенклатура")
            ПоказатьОповещениеПользователя("Активная колонка реквизита:", , ИмяКолонки);
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

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

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

Получение значения текущей ячейки: Нам не нужно обращаться к серверу, чтобы прочитать значение в текущей строке. Достаточно использовать квадратные скобки для обращения к свойству строки:


ТекущиеДанныеСтроки = Элементы.ф_Таб.ТекущиеДанные;
Если ТекущиеДанныеСтроки <> Неопределено Тогда
    ЗначениеЯчейки = ТекущиеДанныеСтроки[ИмяКолонки];
    // Выполняем дальнейшую логику с полученным значением
КонецЕсли;

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

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


&НаКлиенте
Процедура СортироватьПоТекущейКолонке(Команда)
    ТекущийЭлементФормы = Элементы.ф_Таб.ТекущийЭлемент;
    Если ТекущийЭлементФормы <> Неопределено Тогда
        ИмяКолонки = "";
        Если СоответствиеКолонок.Свойство(ТекущийЭлементФормы.Имя, ИмяКолонки) Тогда
            // ф_Таб - реквизит формы с типом ДанныеФормыКоллекция
            ф_Таб.Сортировать(ИмяКолонки); 
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Резюме: Разработанный метод с использованием кэширования структуры колонок при открытии формы позволяет полностью отказаться от ненадежных строковых алгоритмов и исключить лишние вызовы сервера. Это гарантирует высокую скорость работы интерфейса и стабильность конфигурации при последующих доработках другими программистами. Для стандартизации и ускорения динамической настройки интерфейса можно использовать модуль для программного изменения управляемых форм.

← На главную