При разработке отчетов и обработок в среде 1С:Предприятие 8 часто возникает задача перебора макетов объекта для выполнения определенных действий. Например, нам может потребоваться вывести пользователю список только тех макетов, которые являются Схемами компоновки данных (СКД), или найти среди множества двоичных данных конкретный файл. В этой статье мы подробно разберем, как правильно обращаться к свойствам макетов, какие системные перечисления использовать и каких распространенных ошибок стоит избегать.
Рассмотрим типичную ситуацию: у внешнего отчета создано несколько макетов. Среди них есть обычные печатные формы (табличные документы), текстовые файлы и несколько схем компоновки данных. Нам необходимо программно заполнить список выбора на форме именами только тех макетов, которые относятся к типу СхемаКомпоновкиДанных.
Для решения этой задачи мы будем использовать коллекцию метаданных объекта. Важно помнить, что работа с метаданными должна происходить на стороне сервера. Если мы попытаемся перебирать макеты в контексте клиента, система выдаст ошибку, так как доступ к структуре метаданных на клиенте ограничен.
Самый эффективный и «каноничный» способ проверки типа макета — это обращение к свойству ТипМакета в метаданных и его сравнение с системным перечислением Метаданные.СвойстваОбъектов.ТипМакета. Проанализируем, почему этот метод является предпочтительным: при таком подходе система не считывает само содержимое макета (которое может весить несколько мегабайт) из базы данных или файла, а обращается только к его описанию.
Разберем программный код, который решает задачу фильтрации макетов:
// Получаем объект отчета из реквизита формы
ОбъектОтчета = РеквизитФормыВЗначение("Отчет");
// Очищаем список выбора перед заполнением
Элементы.МакетОтчета.СписокВыбора.Очистить();
// Перебираем коллекцию макетов в метаданных
Для Каждого Макет Из ОбъектОтчета.Метаданные.Макеты Цикл
// Проверяем, является ли макет схемой компоновки данных
Если Макет.ТипМакета = Метаданные.СвойстваОбъектов.ТипМакета.СхемаКомпоновкиДанных Тогда
// Добавляем имя и синоним макета в список выбора на форме
Элементы.МакетОтчета.СписокВыбора.Добавить(Макет.Имя, Макет.Синоним);
КонецЕсли;
КонецЦикла;
В данном примере вместо СхемаКомпоновкиДанных мы можем подставить любое другое значение из системного перечисления, в зависимости от наших целей.
Для того чтобы наше решение было универсальным, рассмотрим основные типы макетов, которые поддерживает платформа 1С:
Проанализируем распространенную ошибку, которую часто допускают начинающие разработчики. Попытка использовать конструкцию вида Если Тип(Макет.ТипМакета) = Тип("СхемаКомпоновкиДанных") является в корне неверной по нескольким причинам.
Во-первых, функция Тип() ожидает в качестве аргумента строковое имя типа данных, определенного в системе. Однако строкового типа "СхемаКомпоновкиДанных" как самостоятельного типа объекта не существует — это значение перечисления. Во-вторых, свойство Макет.ТипМакета само по себе уже возвращает значение специального типа метаданных, а не объект макета.
Выясним разницу между проверкой метаданных и проверкой уже полученного объекта:
Макет.ТипМакета возвращает описание того, чем является макет в структуре конфигурации.ТипЗнч() вернула ожидаемый результат, макет сначала нужно прочитать из памяти методом ПолучитьМакет().Рассмотрим пример того, как это работает «в тяжелом весе» (этот метод медленнее и потребляет больше ресурсов):
ТекущийМакет = ПолучитьМакет("ИмяВашегоМакета");
Если ТипЗнч(ТекущийМакет) = Тип("СхемаКомпоновкиДанных") Тогда
// Этот код сработает, так как мы проверяем ТИП ОБЪЕКТА, загруженного в память
Сообщить("Это СКД");
ИначеЕсли ТипЗнч(ТекущийМакет) = Тип("ТабличныйДокумент") Тогда
Сообщить("Это печатная форма");
КонецЕсли;
Важный нюанс: никогда не используйте метод ПолучитьМакет() внутри цикла просто для проверки типа. Это приведет к значительным задержкам в работе программы, так как на каждой итерации 1С будет пытаться полностью загрузить данные макета в оперативную память.
При работе с внешними отчетами (файлами .erf) мы часто используем метод РеквизитФормыВЗначение("Отчет"). Это позволяет нам получить доступ к программному объекту отчета и его метаданным. Однако стоит помнить, что у отчета есть встроенное свойство ОсновнаяСхемаКомпоновкиДанных.
Если ваша задача — найти именно тот макет, который назначен главным, вам не обязательно перебирать всю коллекцию. Достаточно проверить это свойство:
ИмяОсновнойСхемы = ОбъектОтчета.Метаданные.ОсновнаяСхемаКомпоновкиДанных.Имя;
Однако если в отчете реализовано несколько альтернативных схем (например, для разных режимов работы), то перебор коллекции Метаданные.Макеты с проверкой ТипМакета остается единственным надежным способом.
Для корректной и быстрой проверки типа макета в 1С всегда используйте прямое сравнение со значениями Метаданные.СвойстваОбъектов.ТипМакета. Это гарантирует стабильность кода, высокую скорость работы и отсутствие ошибок типизации. Избегайте лишнего использования функции ПолучитьМакет() там, где достаточно обратиться к метаданным, и всегда выполняйте подобные операции на сервере.