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

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

При разработке на управляемых формах в 1С часто возникает задача программного анализа структуры данных. Одной из таких задач является получение типов конкретной колонки таблицы значений, которая добавлена как реквизит формы. Это особенно актуально, когда колонка имеет составной тип данных и нам необходимо динамически изменять поведение интерфейса или проверять корректность вводимых данных. В этой статье мы подробно разберем, как получить объект ОписаниеТипов и извлечь из него массив конкретных типов, используя различные методы платформы 1С.

Понимание контекста: Реквизит формы vs Объект данных

Прежде чем мы перейдем к коду, важно проанализировать, как устроена память управляемой формы. Реквизит типа ТаблицаЗначений на форме — это не совсем та «классическая» таблица значений, к которой мы привыкли в серверных процедурах. Это специальная структура данных управляемой формы (ДанныеФормыКоллекция). У этой структуры нет прямого доступа к метаданным колонок через свойство ТипЗначения, как у обычной таблицы. Поэтому нам необходимо либо обратиться к описанию самой формы, либо временно преобразовать данные в объектный тип.

Способ 1: Использование метода ПолучитьРеквизиты (Самый эффективный)

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

Рассмотрим по шагам, как найти нужную колонку и получить её типы:


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

В данном примере мы используем встроенную функцию ПолучитьРеквизиты(). Она возвращает массив объектов типа РеквизитФормы. Каждый такой объект содержит свойство ТипЗначения, которое и является искомым ОписаниеТипов. Метод .Типы() превращает его в обычный массив ссылок на типы.

Способ 2: Выгрузка структуры в «классическую» таблицу значений

Если вам привычнее работать с объектом ТаблицаЗначений, можно воспользоваться методом Выгрузить(). Однако здесь есть важный нюанс: если в таблице тысячи строк, простая выгрузка создаст полную копию данных в памяти, что существенно замедлит работу системы.

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


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

Этот способ хорош тем, что он лаконичен и понятен. Использование Новый Массив в качестве первого аргумента — это критически важный момент для экономии ресурсов сервера.

Способ 3: Метод РеквизитФормыВЗначение

Метод РеквизитФормыВЗначение() преобразует данные формы в прикладной объект. В случае с таблицей значений он превратит ДанныеФормыКоллекция в обычную ТаблицаЗначений.

Выясним, как это выглядит в коде:


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

Важное замечание: Несмотря на свою простоту, этот метод является самым ресурсозатратным. Он не только копирует структуру, но и полностью сериализует все данные таблицы. Если ваша таблица содержит сотни или тысячи строк, использование РеквизитФормыВЗначение только ради получения типа колонки будет крайне неэффективным решением.

Ограничения клиентского контекста

Рассмотрим ситуацию, когда нам нужно получить типы на клиенте. К сожалению, напрямую обратиться к ОписаниеТипов колонки на клиенте невозможно. Функция ТипЗнч() на клиенте сработает только для конкретного значения в ячейке. Если ячейка пустая (содержит Неопределено), вы не узнаете, какие типы туда можно записать.

Поэтому алгоритм действий всегда должен быть следующим:

  1. Вызов серверной функции (через &НаСервере или &НаСервереБезКонтекста).
  2. Получение массива типов одним из описанных выше способов.
  3. Возврат массива на клиент для дальнейшего использования (например, для программного открытия формы выбора с фильтром по типу).

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

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


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

Использование через метаданные (если ТЗ связана с объектом)

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

Посмотрим на пример обращения к метаданным:


&НаСервере
Функция ПолучитьТипИзМетаданных()
    // Пример для табличной части "Состав" документа "РеализацияТоваровУслуг"
    ОписаниеТипов = Метаданные.Документы.РеализацияТоваровУслуг.ТабличныеЧасти.Состав.Реквизиты.Номенклатура.Тип;
    Возврат ОписаниеТипов.Типы();
КонецФункции

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

Резюме и рекомендации

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

  1. Приоритет 1: Если колонка принадлежит табличной части объекта (документа, справочника), используйте обращение через Метаданные.
  2. Приоритет 2: Для произвольного реквизита формы используйте ПолучитьРеквизиты(). Это наиболее быстрый способ в контексте формы.
  3. Приоритет 3: Если нужно быстро написать код и производительность не критична, используйте Выгрузить(Новый Массив, "ИмяКолонки").
  4. Избегайте: Использования РеквизитФормыВЗначение только для чтения типов, так как это создает избыточную нагрузку на сервер.

Использование правильного метода позволит вашему приложению работать быстрее и стабильнее, особенно при работе с большими объемами данных в интерфейсе.

← На главную