Как программно добавить компоновщик настроек на управляемую форму

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

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

Почему стандартный метод создания элементов не работает

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

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

Метод рекурсивного копирования: стратегия решения

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

Шаг 1. Подготовка реквизитов формы

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


&НаСервере
Процедура СоздатьРеквизитыКомпоновщика(Количество)
    МассивРеквизитов = Новый Массив;
    ТипРеквизита = Новый ОписаниеТипов("КомпоновщикНастроекКомпоновкиДанных");
    
    Для Сч = 1 По Количество Цикл
        ИмяРеквизита = "ДинамическийКомпоновщик_" + Сч;
        НовыйРеквизит = Новый РеквизитФормы(ИмяРеквизита, ТипРеквизита);
        МассивРеквизитов.Добавить(НовыйРеквизит);
    КонецЦикла;
    
    // Добавляем реквизиты на форму
    ИзменитьРеквизиты(МассивРеквизитов);
КонецПроцедуры

Шаг 2. Реализация функции рекурсивного копирования

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


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

    // Рекурсивно обрабатываем вложенные элементы (колонки таблицы, кнопки группы)
    Для Каждого Подчиненный Из ЭлементИсточник.ПодчиненныеЭлементы Цикл
        СкопироватьЭлементРекурсивно(Подчиненный, НовыйЭлемент, Суффикс);
    КонецЦикла;

    Возврат НовыйЭлемент;
КонецФункции

Шаг 3. Инициализация компоновщика данных

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

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


&НаСервере
Процедура ИнициализироватьПрограммныйКомпоновщик(Индекс)
    ИмяРеквизита = "ДинамическийКомпоновщик_" + Индекс;
    ОбъектКомпоновщик = ЭтотОбъект[ИмяРеквизита];
    
    // Получаем схему (например, из макета отчета)
    Схема = Отчеты.МойОтчет.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
    ИсточникНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(Схема);
    
    ОбъектКомпоновщик.Инициализировать(ИсточникНастроек);
    ОбъектКомпоновщик.ЗагрузитьНастройки(Схема.НастройкиПоУмолчанию);
КонецПроцедуры

Важные технические нюансы

При программном создании интерфейса следует учитывать несколько «подводных камней», которые могут повлиять на работоспособность решения:

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

Заключение

Программное управление интерфейсом компоновщика настроек — задача нетривиальная из-за тесной связи визуальных элементов с системными механизмами платформы. Мы рассмотрели наиболее гибкий подход, основанный на рекурсивном дублировании заранее подготовленного шаблона. Этот метод позволяет динамически создавать неограниченное количество панелей настроек, сохраняя при этом весь богатый функционал стандартного интерфейса 1С (группировки, виды сравнения, быстрые отборы).

Используя данный подход, вы сможете создавать действительно динамические отчеты и рабочие места, адаптирующиеся под нужды пользователя «на лету».

← На главную