Разработка и Конфигурация · 13 мин
Как перебрать элементы формы в 1С: практическое руководство
Как перебрать элементы формы в 1С: обход ЭлементыФормы и Элементы, поиск по имени и типу, рекурсия по группам, обход реквизитов и табличных частей. Примеры кода.
Перебор элементов формы — типичная задача при доработке конфигураций 1С: нужно массово скрыть кнопки, заблокировать поля ввода, найти конкретный элемент по части имени или собрать список всех таблиц на форме. Платформа предоставляет коллекцию элементов формы, которую можно обходить в цикле, но синтаксис зависит от типа формы: обычная форма (толстый клиент, режим совместимости) и управляемая форма используют разные объекты и разные свойства.
Ключевое различие: в обычной форме коллекция называется ЭлементыФормы, а в управляемой — Элементы. Кроме того, в управляемых формах элементы представляют собой декларативное описание интерфейса, и многие операции (например, изменение данных) выполняются через реквизиты формы, а не через сами элементы. Путаница между этими моделями — самая частая причина ошибок вида «Поле объекта не обнаружено».
Ниже разобраны оба варианта: простой обход коллекции, поиск элемента по имени и типу, рекурсивный обход с учётом групп, перебор реквизитов формы и типовые ошибки. Все примеры приведены на встроенном языке 1С и могут быть адаптированы под конкретную конфигурацию.
Отличия обычной и управляемой формы при переборе элементов
Прежде чем писать цикл, определите, с какой формой работаете. В обычной форме коллекция ЭлементыФормы содержит объекты конкретных типов: ПолеВвода, Кнопка, ТабличноеПоле и так далее. Тип элемента проверяется функцией ТипЗнч() с конкретным типом, например Тип("ТабличноеПоле").
В управляемой форме коллекция Элементы содержит объекты типа ПолеФормы, ГруппаФормы, КнопкаФормы, ТаблицаФормы. Здесь доступно свойство Вид, уточняющее назначение элемента (например, ВидПоляФормы.ПолеВвода). Родителя элемента можно получить через свойство Родитель, а вложенные элементы группы — через ПодчиненныеЭлементы.
Ещё одно важное отличие: в управляемой форме коллекция Элементы доступна только в контексте формы (в модуле формы через ЭтаФорма.Элементы или просто Элементы). Передать её на сервер вне контекста формы нельзя — это структура клиентского интерфейса, а не данные.
Простой перебор всех элементов формы
Базовый сценарий — пройтись по всем элементам верхнего уровня и выполнить с ними однотипное действие. В управляемой форме код выглядит так:
Для Каждого Элемент Из Элементы Цикл
// Пример: вывести имя и тип каждого элемента
Сообщить(Элемент.Имя + " — " + ТипЗнч(Элемент));
КонецЦикла;
В обычной форме синтаксис идентичен, меняется только имя коллекции:
Для Каждого Элемент Из ЭлементыФормы Цикл
Сообщить(Элемент.Имя);
КонецЦикла;
Обратите внимание: цикл по коллекции Элементы в управляемой форме обходит все элементы, включая вложенные в группы, — коллекция плоская по составу, хотя иерархия сохраняется через свойство Родитель. В обычной форме ЭлементыФормы содержит только элементы верхнего уровня, а элементы внутри панелей и групп доступны через коллекции соответствующих родительских элементов.
Практический пример — массовая установка видимости. Такой приём используют, когда нужно скрыть блок реквизитов по условию, не перечисляя каждый элемент по имени:
Для Каждого Элемент Из Элементы Цикл
Если СтрНайти(Элемент.Имя, "Служебный_") > 0 Тогда
Элемент.Видимость = Ложь;
КонецЕсли;
КонецЦикла;
Поиск элемента по имени без полного перебора
Полный перебор нужен не всегда. Если известно имя элемента, эффективнее использовать метод Найти(), который возвращает элемент или Неопределено, если элемента нет:
НайденныйЭлемент = Элементы.Найти("Комментарий");
Если НайденныйЭлемент <> Неопределено Тогда
НайденныйЭлемент.ТолькоПросмотр = Истина;
КонецЕсли;
Обращение к элементу напрямую по имени — Элементы.Комментарий — тоже работает, но если элемента с таким именем нет, возникнет ошибка выполнения. Вариант с Найти() безопаснее, когда форма может отличаться в разных режимах или дорабатывается расширением.
Если нужно найти несколько элементов по шаблону имени, метод Найти() не подходит — он ищет точное совпадение. В этом случае используйте перебор со СтрНайти() или регулярную логику сравнения, как в примере со служебными полями выше.
- 1Определите тип формы: обычная (ЭлементыФормы) или управляемая (Элементы)
- 2Если имя известно точно — вызовите Элементы.Найти(Имя) и проверьте результат на Неопределено
- 3Если имя известно частично — переберите коллекцию и сравнивайте имена через СтрНайти()
- 4Проверьте тип найденного элемента перед изменением свойств, чтобы не обратиться к несуществующему свойству
- 5Протестируйте форму в режиме предприятия: убедитесь, что элемент найден и изменения применились
Фильтрация элементов по типу и виду
Частая задача — обработать только элементы определённого типа, например заблокировать все поля ввода или найти все таблицы формы. В управляемой форме проверка строится через ТипЗнч():
Для Каждого Элемент Из Элементы Цикл
Если ТипЗнч(Элемент) = Тип("ПолеФормы") Тогда
Элемент.ТолькоПросмотр = Истина;
КонецЕсли;
КонецЦикла;
Когда нужен более точный отбор, комбинируйте тип со свойством Вид. Например, чтобы отличить поле флажка от поля ввода:
Если ТипЗнч(Элемент) = Тип("ПолеФормы")
И Элемент.Вид = ВидПоляФормы.ПолеФлажка Тогда
// обработка только флажков
КонецЕсли;
Учтите, что не у всех элементов есть свойства ТолькоПросмотр, Видимость или Доступность в одинаковом наборе. Перед массовой установкой свойства убедитесь, что оно применимо к типу элемента, иначе получите ошибку «Свойство объекта не обнаружено». Безопасный шаблон — сначала фильтровать по типу, потом менять свойство.
Рекурсивный обход вложенных групп
В обычных формах и при работе со структурой управляемой формы иногда требуется обойти элементы с учётом иерархии: например, обработать только содержимое конкретной группы. Для этого используется рекурсивная процедура, которая проходит по ПодчиненныеЭлементы:
Процедура ОбойтиЭлементыРекурсивно(Родитель)
Для Каждого Элемент Из Родитель.ПодчиненныеЭлементы Цикл
Сообщить(Элемент.Имя);
Если ТипЗнч(Элемент) = Тип("ГруппаФормы") Тогда
ОбойтиЭлементыРекурсивно(Элемент);
КонецЕсли;
КонецЦикла;
КонецПроцедуры;
// Вызов:
ОбойтиЭлементыРекурсивно(Элементы.ГруппаНастройки);
Рекурсия удобна, когда действие должно применяться к поддереву формы: скрыть целый раздел, собрать все поля внутри страницы, построить карту иерархии для отладки. Если нужно обработать всю форму целиком без привязки к иерархии, простой плоский цикл по Элементы проще и быстрее.
Глубина вложенности групп в типовых формах невелика, поэтому риск переполнения стека при рекурсии практически отсутствует. Тем не менее не вызывайте рекурсивный обход в обработчиках, срабатывающих на каждое изменение формы, — это заметно нагружает клиентское приложение.
Сравнение подходов
Подходит для обработки всех элементов формы без учёта иерархии; простой и быстрый, но не даёт информации о вложенности
Оптимален при известном точном имени; не работает с шаблонами и частичными совпадениями
Нужна для обработки отдельной ветки формы; требует аккуратности и чуть больше кода
Перебор реквизитов формы и связь с элементами
Элементы формы — это только отображение. Данные хранятся в реквизитах формы, и их тоже бывает нужно перебрать: например, чтобы программно заполнить набор полей или проверить, какие реквизиты существуют. Для этого используется метод ПолучитьРеквизиты():
МассивРеквизитов = ЭтаФорма.ПолучитьРеквизиты();
Для Каждого Реквизит Из МассивРеквизитов Цикл
Сообщить(Реквизит.Имя + " : " + Реквизит.ТипЗначения);
КонецЦикла;
Метод ПолучитьРеквизиты() принимает необязательный параметр — путь к родительскому реквизиту. Без параметра возвращаются реквизиты верхнего уровня; если передать имя реквизита-объекта (например, "Объект" в форме документа), получите его реквизиты, то есть фактически реквизиты самого документа.
Связь между реквизитом и элементом не обязательна: реквизит может существовать без элемента на форме, а элемент (надпись, декорация, кнопка) — без реквизита. У полей формы связь задаётся свойством ПутьКДанным. Поэтому перебор элементов и перебор реквизитов решают разные задачи: первый — про интерфейс, второй — про данные.
Перебор строк табличной части и динамического списка на форме
Отдельный частный случай — перебор не самих элементов, а данных, которые элементы отображают. Для табличной части объекта перебираются строки коллекции, а не элементы:
Для Каждого Строка Из Объект.Товары Цикл
Строка.Цена = Строка.Цена * 1.1;
КонецЦикла;
Если на форме размещён динамический список, перебирать его строки напрямую нельзя — список формируется запросом и подгружает данные порциями. Чтобы получить данные, нужно работать с запросом списка (через схему компоновки) или использовать методы получения данных. Попытка «перебрать элементы таблицы формы, чтобы прочитать строки» — типичная ошибка: элемент ТаблицаФормы даёт доступ только к текущей строке и выделенным строкам, а не ко всем данным списка.
Для обычной таблицы значений, выведенной на форму как реквизит, перебор выполняется по коллекции реквизита: Для Каждого Строка Из ИмяТаблицы Цикл. Элемент формы здесь служит только визуальным представлением.
Как проверить результат
Все целевые элементы изменили состояние (скрыты, заблокированы) как задумано
Часть элементов не изменилась — вероятно, они вложены в группу, которую цикл не охватил, или фильтр по имени не сработал
Нет ошибок «Свойство объекта не обнаружено» и «Поле объекта не обнаружено»
Есть ошибки — значит, код обратился к свойству, несовместимому с типом элемента, или к несуществующему элементу
Логика срабатывает стабильно при каждом открытии
Результат плавающий — обработчик может быть привязан к событию, которое не всегда вызывается
Где размещать код перебора и ограничения
Код перебора элементов размещается в модуле формы. Типичные события: ПриСозданииНаСервере (первичная настройка видимости и доступности), ПриОткрытии (клиентские корректировки), обработчики изменения ключевых реквизитов. Для управляемых форм помните о директивах компиляции: &НаСервере, &НаКлиенте — коллекция Элементы доступна в обоих контекстах формы, но вызов серверных процедур с клиента требует явного объявления.
Не размещайте тяжёлые переборы в событиях, которые срабатывают часто (например, при каждой активизации строки). Если логика сложная, кэшируйте результаты поиска элементов в переменных формы при создании и используйте их дальше.
Наконец, при доработке типовых конфигураций предпочтительнее использовать расширения и программное изменение формы в обработчике ПриСозданииНаСервере, а не прямое изменение модуля формы типового объекта — это упрощает обновление конфигурации.
Что важно запомнить
Перебор выполняется циклом по коллекции Элементы (управляемая форма) или ЭлементыФормы (обычная). Для точного поиска используйте Найти(), для вложенных групп — рекурсию по ПодчиненныеЭлементы, для данных — перебор реквизитов и строк табличных частей, а не элементов. Всегда проверяйте тип элемента перед изменением свойств.
Часто задаваемые вопросы
Как перебрать элементы формы в управляемом приложении 1С?
Используйте цикл «Для Каждого Элемент Из Элементы Цикл» в модуле формы. Коллекция Элементы содержит все элементы, включая вложенные в группы. Для фильтрации проверяйте тип через ТипЗнч(Элемент) и свойство Вид.
Чем отличается Элементы от ЭлементыФормы?
ЭлементыФормы — коллекция обычной формы (режим обычного приложения), содержит объекты типа ПолеВвода, Кнопка, ТабличноеПоле. Элементы — коллекция управляемой формы с объектами ПолеФормы, ГруппаФормы, КнопкаФормы, ТаблицаФормы. Синтаксис перебора одинаковый, отличаются типы и наборы свойств элементов.
Как найти элемент формы, если известна только часть имени?
Метод Найти() ищет только точное совпадение, поэтому переберите коллекцию циклом и проверяйте имена функцией СтрНайти(Элемент.Имя, "ЧастьИмени") > 0. Совпавшие элементы складывайте в массив, а обрабатывайте после завершения цикла.
Можно ли перебрать элементы формы на сервере?
Да, в модуле управляемой формы коллекция Элементы доступна и в серверных процедурах контекста формы. Но передать её как параметр в общий модуль или на другой объект нельзя — коллекция существует только внутри формы.
Почему возникает ошибка «Свойство объекта не обнаружено» при переборе?
Потому что не у всех типов элементов есть одинаковые свойства: у группы нет ПутьКДанным, у декорации — ТолькоПросмотр. Решение — фильтровать элементы по типу через ТипЗнч() перед установкой свойства и менять только совместимые свойства.
Как перебрать строки таблицы на форме, а не сами элементы?
Перебирайте коллекцию данных реквизита, а не элемент формы: Для Каждого Строка Из Объект.Товары Цикл. Элемент ТаблицаФормы даёт доступ только к текущей и выделенным строкам, а динамический список вообще не позволяет перебрать строки напрямую — нужен запрос.