При разработке на обычных формах (ОФ) программисты часто сталкиваются с задачей массовой обработки данных, находящихся на форме. Типичный сценарий: в обработке или форме списка расположено несколько табличных полей, и нам необходимо программно установить в них одинаковый отбор (например, по организации или периоду), не прописывая обращение к каждому полю вручную. Рассмотрим, почему стандартные методы управляемых форм здесь не работают и как правильно решить эту задачу.
В управляемых формах (УФ) мы привыкли к методу ПолучитьРеквизиты(), который возвращает коллекцию всех данных формы. В обычных формах ситуация иная. Если вы попытаетесь вызвать ЭтаФорма.Метаданные().Реквизиты, вы получите только те реквизиты, которые принадлежат объекту метаданных (самой обработке или документу), но не те, которые вы добавили локально на форму в редакторе на закладке «Реквизиты».
Проанализируем причины этого поведения: в архитектуре ОФ локальные реквизиты формы не регистрируются в дереве метаданных конфигурации как постоянные объекты. Они являются временными свойствами программного объекта «Форма». К сожалению, в языке 1С для обычных форм не предусмотрено встроенной коллекции, которую можно было бы перебрать конструкцией Для каждого, чтобы получить список этих локальных реквизитов.
Поскольку наша цель — программно установить отборы в списках (которые автор темы назвал «динамическими списками», хотя в ОФ это Табличные поля), нам нужно перебирать не абстрактные реквизиты, а визуальные элементы управления. Именно элементы управления связаны с данными, которыми мы хотим манипулировать.
Рассмотрим по шагам, как реализовать универсальный алгоритм поиска всех списков на форме и установки в них фильтра:
ЭтаФорма.ЭлементыФормы.ТабличноеПоле.Значение или Данные. Если в табличное поле загружен список (справочника, документа или регистра), у него будет доступен объект Отбор.Посмотрим на пример кода, который реализует этот подход:
Процедура УстановитьОтборыНаФорме(ЗначениеОтбора)
// Перебираем все элементы, размещенные на форме
Для каждого Элемент Из ЭтаФорма.ЭлементыФормы Цикл
// Проверяем, является ли элемент табличным полем
Если ТипЗнч(Элемент) = Тип("ТабличноеПоле") Тогда
// Получаем объект, который выступает источником данных для поля
ИсточникДанных = Элемент.Значение;
ТипИсточника = ТипЗнч(ИсточникДанных);
// Выясним, является ли источник типом "Список"
// Например: СправочникСписок.Номенклатура, ДокументСписок.РеализацияТоваровУслуг
Если Найти(Строка(ТипИсточника), "Список") > 0 Тогда
// Пытаемся установить отбор по конкретному полю, например "Организация"
Попытка
Если ИсточникДанных.Отбор.Найти("Организация") <> Неопределено Тогда
ИсточникДанных.Отбор.Организация.Установить(ЗначениеОтбора);
ИсточникДанных.Отбор.Организация.Использование = Истина;
КонецЕсли;
Исключение
// Если поля "Организация" в данном списке не существует, просто пропускаем
КонецПопытки;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Если ваша задача — перебрать не элементы управления, а основные реквизиты обработки, которые заданы в конфигураторе (в дереве метаданных), то метод Метаданные() сработает, но обращаться нужно к объекту ЭтотОбъект (самой обработке), а не к форме. Проанализируем ситуацию на примере:
// Для встроенной обработки в ОФ
МетаданныеОбъекта = ЭтотОбъект.Метаданные();
Для каждого МетаРеквизит Из МетаданныеОбъекта.Реквизиты Цикл
ИмяРеквизита = МетаРеквизит.Имя;
// Получаем текущее значение реквизита из объекта
ТекущееЗначение = ЭтотОбъект[ИмяРеквизита];
Сообщить("Обработка реквизита: " + ИмяРеквизита + " со значением: " + ТекущееЗначение);
КонецЦикла;
Важный момент: если ваша обработка является «внешней» (файл .epf), то обращение через ЭтотОбъект.Метаданные() также будет работать корректно, возвращая описание структуры внешней обработки.
В отличие от управляемых форм, где используется система компоновки данных (СКД) внутри динамического списка, в обычных формах объект Отбор работает напрямую с табличным полем. Рассмотрим подробнее свойства этого объекта:
ИсточникДанных.Отбор.Склад.ВидСравнения = ВидСравнения.ВГруппе;Использование = Истина, иначе фильтр не применится, даже если значение заполнено.ТаблицейЗначений. В этом случае свойства Отбор у него не будет. Для фильтрации строк ТаблицыЗначений в ОФ используются методы построителя отчета или программная фильтрация строк через Строки.Скрыть() / Строки.Отобразить() (в зависимости от конкретной версии платформы).Хотя мы выяснили, что перечислить локальные реквизиты формы в цикле невозможно, существует способ обращения к ним по имени, если имена определяются динамически (например, хранятся в массиве строк). Вы можете использовать синтаксис квадратных скобок для объекта формы:
ТекущееЗначение = ЭтаФорма["ИмяРеквизита"];
Это позволяет строить гибкие алгоритмы, если вы заранее знаете список имен реквизитов, которые нужно обработать, но не хотите прописывать их через точку в коде.
Таким образом, для решения задачи автора темы наиболее эффективным и правильным путем является сканирование коллекции ЭлементыФормы. Это позволяет «дотянуться» до данных через визуальные компоненты, что является стандартной практикой для разработки в режиме обычного приложения.