Как наложить отбор на дерево макетов печати и ограничить выбор типов документов через метаданные

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

В практике разработки на платформе 1С:Предприятие часто возникают задачи, связанные с доработкой типовых механизмов печати. В старых конфигурациях (таких как УТ 10.3, УПП 1.3 или КА 1.1) для формирования списка доступных печатных форм используется подсистема УниверсальныеМеханизмы. Проанализируем, как правильно работать с деревом макетов и как эффективно фильтровать объекты метаданных для выбора пользователем.

Фильтрация печатных форм в дереве макетов

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

Проанализируем структуру строки дерева макетов. В типовых механизмах объект СтрокаДерева содержит следующие колонки:

  1. Текст — отображаемое название печатной формы (например, "Счет на оплату").
  2. Имя — внутренний идентификатор макета или процедуры формирования.
  3. Расшифровка — служебная информация (часто структура или массив).

Для того чтобы наложить отбор по конкретным именам (например, оставить только «ЗаказПокупателя» и «РеализацияТоваровИУслуг»), мы можем использовать два основных подхода.

Способ 1: Проверка условия внутри цикла обхода

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


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

В данном случае мы используем прямое сравнение. Если список имен большой, удобнее использовать коллекцию Массив или СписокЗначений и метод Найти().

Способ 2: Использование метода НайтиСтроки

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


Отбор = Новый Структура;
Отбор.Вставить("Имя", "ЗаказПокупателя");

// Метод НайтиСтроки возвращает массив подходящих строк
НайденныеСтроки = Дерево.Строки.НайтиСтроки(Отбор);

Для Каждого Строка Из НайденныеСтроки Цикл
    НоваяСтрока = ТаблицаМакетовПечати.Добавить();
    НоваяСтрока.ПечатнаяФорма = Строка.Текст;
    НоваяСтрока.Имя = Строка.Имя;
КонецЦикла;

Важное техническое замечание: Метод НайтиСтроки() работает только на том уровне дерева, у которого он вызван. Если ваше дерево содержит вложенные уровни (группировки), данный поиск не увидит подчиненные строки. В таких случаях необходимо использовать рекурсивный обход всех уровней Строки.

Оптимизация выбора типа документа из метаданных

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

Рассмотрим, как можно оптимизировать процедуру ТипДокументаНачалоВыбора. Вместо создания таблицы значений вручную и заполнения её в цикле, следует обращаться к нужным объектам метаданных напрямую.

Правильный подход к ограничению списка выбора

Если нам нужно, чтобы пользователь выбирал только из двух видов документов («Заказ покупателя» и «Реализация товаров»), проанализируем следующий код:


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

В этом решении мы полностью исключили цикл Для Каждого по коллекции метаданных. Это не только ускоряет работу интерфейса, но и делает код гораздо более читаемым. Мы напрямую обращаемся к Метаданные.Документы.ИмяДокумента, что гарантирует получение ссылки на описание объекта метаданных.

Работа с типами данных в таблицах

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

Рассмотрим пример создания типизированной колонки:


МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("ДокументСсылка.ЗаказПокупателя"));
МассивТипов.Добавить(Тип("ДокументСсылка.РеализацияТоваровУслуг"));

ОписаниеТипаДокумента = Новый ОписаниеТипов(МассивТипов);

ТаблицаДок = Новый ТаблицаЗначений;
ТаблицаДок.Колонки.Добавить("ТипДокумента", ОписаниеТипаДокумента, "Тип документа");

Резюмируем изученное:

Эти рекомендации помогут вам создавать более производительные и надежные механизмы в среде 1С:Предприятие 8.

← На главную