Довольно часто в системе 1С:Предприятие 7.7 у разработчика возникает потребность использовать на форме контрол, который бы давал возможность представить данные для пользователя в виде дерева. Штатные возможности системы таким функционалом не располагают, но внешняя компонента «FormEx», дает возможность разработчику это реализовать с помощью объекта «Дерево+Таблица», с которым мы сейчас и познакомимся.
Скачаем внешнюю компоненту с сайта http://www.dorex.ru. Последнюю стабильную сборку можно взять тут: http://www.dorex.ru/files/?formex_t.zip. Из скачанного архива нужно распаковать файл «formex.dll» в папку конфигурации или в папку «Bin» платформы 1С 7.7.
Затем создадим в какой-нибудь конфигурации для экспериментов обработку и на ее форму закинем обычную «ТаблицуЗначений», зададим ей идентификатор -«ТЗ». Это, впоследствии, и будет наше дерево. Кнопки «Выполнить» и «Закрыть», которые появляются при создании новой обработки, оставим на будущее, также как и пустую процедуру «Выполнить()» в модуле формы обработки. Т.е. в конфигураторе она будет выглядеть примерно так, см. рис.:
Далее будем писать код в модуле формы нашей обработки. Определим две глобальные переменные, они нам понадобятся для манипулирования деревом:
Перем гАтрФормыТЗ, гСтруктураТЗ;
И затем в процедуре «ПриОткрытии()» запишем код загрузки внешней компоненты «FormEx»:
Процедура ПриОткрытии() Если ЗагрузитьВнешнююКомпоненту("formex.dll")=0 Тогда Предупреждение("Не удалось загрузить внешнюю компоненту FormEx.",10); СтатусВозврата(0); Возврат; КонецЕсли; КонецПроцедуры // ПриОткрытии
А в теле модуля, т.е. после процедур и функций модуля формы обработки, заполним и сохраним в глобальную переменную модуля структуру «ТаблицыЗначений»:
ТЗ.НоваяКолонка("Ветка"); ТЗ.НоваяКолонка("Значек"); ТЗ.НоваяКолонка("ИмяВетки",,,,"Узлы"); гСтруктураТЗ=ЗначениеВСтрокуВнутр(ТЗ);
После чего в процедуре «ПослеОткрытия()», эта предопределенная процедура работает, если загружен «FormEx», напишем код, который преобразует нашу «ТаблицуЗначений» в дерево:
Процедура ПослеОткрытия() гАтрФормыТЗ = СоздатьОбъект("АтрибутФормы"); гАтрФормыТЗ.УстановитьАтрибут(Форма,"ТЗ"); гАтрФормыТЗ.ПерехватитьТаблицуЗначений(); гАтрФормыТЗ.ОпцииДерева(0,0); КонецПроцедуры // ПослеОткрытия
Вот, в принципе, пустое дерево мы создали. Стоит также отметить, что колонки, которые мы задали для «ТаблицыЗначений» - это те три минимальных служебных колонки, которые должны быть у «ТаблицыЗначений» в любом случае, для того, чтобы она успешно стала деревом. Т.е. это колонки «Ветка», «Значек», «ИмяВетки». Причем, ячейки колонки «Ветка» - фактически, должны хранить «ТаблицуЗначений», в которой хранится таблица подветок текущей ветки, если подветки у нее есть. Т.е. имеем структуру вложенных друг в друга «ТаблицЗначений». Ячейки колонки «Значек» можем пока не трогать, так как нам будет достаточно системных пиктограмм, а колонка «ИмяВетки» - это то, что будет отображаться в нашем дереве в качестве названий узлов-веток.
Теперь давайте заполним какими-нибудь произвольными данными наше дерево, чтобы можно было посмотреть, как это все выглядит.
Для этого в процедуре «Выполнить()», которую мы оставили пустой, после создания новой обработки в начале, напишем код заполнения нашего дерева какими-нибудь данными, например, такими (я тут намеренно не усложняю рекурсией и даю пример для дерева всего с двумя уровнями):
Процедура Выполнить() ТЗ.УдалитьСтроки(); Для Сч=1 По 10 Цикл ТЗ.НоваяСтрока(); ТЗ.ИмяВетки="Уровень номер "+НРег(СокрЛП(Формат(1,"ЧП")))+ ", узел номер "+НРег(СокрЛП(Формат(Сч,"ЧП"))); ТЗ.Ветка=ЗначениеИзСтрокиВнутр(гСтруктураТЗ); Для Сч2=1 По 5 Цикл ТЗ.Ветка.НоваяСтрока(); ТЗ.Ветка.ИмяВетки="Уровень номер "+НРег(СокрЛП(Формат(2,"ЧП")))+ ", узел номер "+НРег(СокрЛП(Формат(Сч2,"ЧП"))); ТЗ.Ветка.Ветка=ЗначениеИзСтрокиВнутр(гСтруктураТЗ); КонецЦикла; КонецЦикла; гАтрФормыТЗ.ОбновитьДерево(); КонецПроцедуры
Итак, весь код модуля формы нашей обработки таков:
Перем гАтрФормыТЗ, гСтруктураТЗ; Процедура Выполнить() ТЗ.УдалитьСтроки(); Для Сч=1 По 10 Цикл ТЗ.НоваяСтрока(); ТЗ.ИмяВетки="Уровень номер "+НРег(СокрЛП(Формат(1,"ЧП")))+ ", узел номер "+НРег(СокрЛП(Формат(Сч,"ЧП"))); ТЗ.Ветка=ЗначениеИзСтрокиВнутр(гСтруктураТЗ); Для Сч2=1 По 5 Цикл ТЗ.Ветка.НоваяСтрока(); ТЗ.Ветка.ИмяВетки="Уровень номер "+НРег(СокрЛП(Формат(2,"ЧП")))+ ", узел номер "+НРег(СокрЛП(Формат(Сч2,"ЧП"))); ТЗ.Ветка.Ветка=ЗначениеИзСтрокиВнутр(гСтруктураТЗ); КонецЦикла; КонецЦикла; гАтрФормыТЗ.ОбновитьДерево(); КонецПроцедуры // Выполнить Процедура ПриОткрытии() Если ЗагрузитьВнешнююКомпоненту("formex.dll")=0 Тогда Предупреждение("Не удалось загрузить внешнюю компоненту FormEx.",10); СтатусВозврата(0); Возврат; КонецЕсли; КонецПроцедуры // ПриОткрытии Процедура ПослеОткрытия() гАтрФормыТЗ = СоздатьОбъект("АтрибутФормы"); гАтрФормыТЗ.УстановитьАтрибут(Форма,"ТЗ"); гАтрФормыТЗ.ПерехватитьТаблицуЗначений(); гАтрФормыТЗ.ОпцииДерева(0,0); КонецПроцедуры // ПослеОткрытия ТЗ.НоваяКолонка("Ветка"); ТЗ.НоваяКолонка("Значек"); ТЗ.НоваяКолонка("ИмяВетки",,,,"Узлы"); гСтруктураТЗ=ЗначениеВСтрокуВнутр(ТЗ);
В итоге, запустив обработку в режиме предприятия и нажав кнопку выполнить, мы увидим примерно такую картину:
Щелкая мышкой по плюсикам/минусикам (слева), можно разворачивать и сворачивать узлы, наслаждаясь полученным эффектом.
Естественно, это далеко не весь функционал и особенности, которые есть у этого объекта, к этой публикации прилагается внешний отчет/обработка «ДеревоПлюсТаблица.ert». Там усложнен приведенный пример – рекурсивное заполнение дерева любым количеством уровней (задается пользователем), рекурсивный обход дерева с разворачиванием и сворачиванием всех узлов, есть дополнительный столбик с данными для узлов (в примере, просто порядковый номер), а также возможность редактировать ячейки дерева двойным щелчком мыши на ячейке. См. скрин.
Также может возникнуть вопрос вывода на печать этого дерева, привожу свой вариант печати. Это внешний отчет/обработка, которую можно использовать в любой конфигурации:
Печать объекта Дерево+Таблица внешней компоненты FormEx
И привожу ссылки на реальные проекты, где использовался этот объект в реальных условиях, в обработках для настройки тех или иных подсистем:
Универсальная подсистема «Подписи/согласования документов»
Универсальная подсистема «Фабрика событий» + «Доп. права документов» + «Сканы документов»
Универсальная подсистема «Дополнительные права для документов»