Макет 1С — заготовка, которая хранится в конфигурации: бланк печатной формы, текст письма, файл Word, схема отчёта, логотип. Код получает макет методом ПолучитьМакет или ПолучитьОбщийМакет, берёт копию и заполняет её данными. Ниже — какие типы макетов есть в платформе 8.3 и что возвращает каждый, как добавить макет в конфигураторе, как получить его программно из формы, общего модуля и внешней обработки, и на чём обычно спотыкаются.
С макетами сталкиваются почти в любой доработке: новая печатная форма документа, этикетка, выгрузка по фиксированному XML-шаблону, письмо клиенту с номером заказа, отчёт на СКД внутри обработки. Заготовку в таких задачах не собирают кодом с нуля, а один раз рисуют в конфигураторе и дальше только заполняют. Если вывод без макета всё же нужен, это отдельный приём — он разобран в статье про табличный документ 1С.
Тип выбирается в конструкторе при создании макета. От него зависит, объект какого типа вернёт код.
| Тип макета | Что вернёт код | Для чего |
|---|---|---|
| Табличный документ | ТабличныйДокумент | печатные формы, бланки, этикетки, шапки отчётов |
| Текстовый документ | ТекстовыйДокумент | шаблоны писем и SMS, текстовые выгрузки |
| Двоичные данные | ДвоичныеДанные | логотипы, шаблоны Word и Excel, XSD и JSON |
| HTML-документ | ОболочкаHTMLДокумента | справка и подсказки в поле HTML на форме |
| Схема компоновки данных | СхемаКомпоновкиДанных | отчёты, отборы и выборки в обработках |
| Макет оформления компоновки данных | МакетОформленияКомпоновкиДанных | собственное оформление отчётов на СКД |
| Графическая схема | ГрафическаяСхема | схемы процессов |
| Географическая схема | ГеографическаяСхема | карты с привязкой данных |
| Внешняя компонента | архив компоненты | zip-архив внешней компоненты для ПодключитьВнешнююКомпоненту("ОбщийМакет.Имя", ...) |
Большую часть задач закрывают первые пять строк. Тип «Внешняя компонента» есть в платформе с 8.3.9: в него кладут zip-архив с вариантами компоненты под разные операционные системы, а подключают её прямо по имени макета, без выгрузки во временный файл. В списке типов конструктора есть ещё Active-документ — наследие старых версий: он хранит документ Word или Excel и работает через OLE только в Windows. В новых разработках такой файл кладут в макет «Двоичные данные».
Макет живёт в одном из трёх мест, и от этого зависит, как его потом получать:
Чтобы создать макет в 1С:
ПФ_MXL_ для табличных и ПФ_DOC_ для файлов Word.Заказ № [Номер] от [Дата].Как сделать макет 1С под конкретный бланк — с объединением ячеек, повторяющейся шапкой таблицы и подвалом на каждой странице — подробно показано в статье макет печатной формы в конструкторе. Здесь сосредоточимся на коде.
Способ зависит от того, где лежит макет и откуда идёт вызов:
// Макет объекта конфигурации: через менеджер (сервер)
Макет = Документы.ЗаказКлиента.ПолучитьМакет("ПФ_MXL_Заказ");
// В модуле объекта документа или обработки: метод самого объекта
Макет = ПолучитьМакет("ПФ_MXL_Заказ");
// Общий макет
Логотип = ПолучитьОбщийМакет("ЛоготипОрганизации"); // ДвоичныеДанные
// Основная схема отчета на СКД
Схема = Отчеты.ПродажиПоМенеджерам.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Всё это серверный код. В модуле объекта (документа, обработки) метод ПолучитьМакет вызывается без префикса — это метод самого объекта. В модуле управляемой формы такого метода нет, там нужен менеджер или объект.
Ниже — общий модуль, который закрывает типовые сценарии: макет объекта по полному имени с понятной ошибкой, общий макет на языке пользователя, текстовый шаблон с подстановкой, двоичный макет как строка или временный файл.
// Общий модуль РаботаСМакетамиСервер.
// Свойства модуля: Сервер - Истина, Вызов сервера - Ложь.
// Платформа 8.3.9 и выше (СтрШаблон, ПолучитьСтрокуИзДвоичныхДанных).
#Область ПрограммныйИнтерфейс
// Возвращает макет объекта конфигурации.
//
// Параметры:
// ПолноеИмяОбъекта - Строка - например, "Документ.ЗаказКлиента" или "Обработка.ЗагрузкаПрайса".
// ИмяМакета - Строка - имя макета этого объекта.
//
// Возвращаемое значение:
// ТабличныйДокумент, ТекстовыйДокумент, ДвоичныеДанные, СхемаКомпоновкиДанных и др. -
// тип зависит от типа макета.
//
Функция МакетОбъекта(ПолноеИмяОбъекта, ИмяМакета) Экспорт
МетаданныеОбъекта = Метаданные.НайтиПоПолномуИмени(ПолноеИмяОбъекта);
Если МетаданныеОбъекта = Неопределено Тогда
ВызватьИсключение СтрШаблон(НСтр("ru = 'Не найден объект метаданных %1'"), ПолноеИмяОбъекта);
КонецЕсли;
Менеджер = МенеджерОбъекта(МетаданныеОбъекта);
Если МетаданныеОбъекта.Макеты.Найти(ИмяМакета) = Неопределено Тогда
ВызватьИсключение СтрШаблон(НСтр("ru = 'У объекта %1 нет макета %2'"), ПолноеИмяОбъекта, ИмяМакета);
КонецЕсли;
Возврат Менеджер.ПолучитьМакет(ИмяМакета);
КонецФункции
// Возвращает общий макет на языке сеанса: если в конфигурации есть
// макет "<ИмяМакета>_<код языка>" (например, "ШаблонПисьма_en"), берется он,
// иначе основной макет.
//
Функция ОбщийМакетНаЯзыкеСеанса(ИмяМакета) Экспорт
ИмяЯзыковогоМакета = ИмяМакета + "_" + ТекущийЯзык().КодЯзыка;
Если Метаданные.ОбщиеМакеты.Найти(ИмяЯзыковогоМакета) <> Неопределено Тогда
Возврат ПолучитьОбщийМакет(ИмяЯзыковогоМакета);
КонецЕсли;
Возврат ПолучитьОбщийМакет(ИмяМакета);
КонецФункции
// Подставляет значения в текст общего макета типа "Текстовый документ".
// В тексте макета параметры записаны в фигурных скобках: {НомерЗаказа}.
//
// Параметры:
// ИмяМакета - Строка - имя общего макета.
// Параметры - Структура - ключ совпадает с именем параметра в тексте.
//
// Возвращаемое значение:
// Строка
//
Функция ТекстПоШаблону(ИмяМакета, Параметры) Экспорт
Текст = ОбщийМакетНаЯзыкеСеанса(ИмяМакета).ПолучитьТекст();
Для Каждого КлючИЗначение Из Параметры Цикл
Текст = СтрЗаменить(Текст, "{" + КлючИЗначение.Ключ + "}", Строка(КлючИЗначение.Значение));
КонецЦикла;
Возврат Текст;
КонецФункции
// Читает общий макет типа "Двоичные данные" как текст в UTF-8 (XML, JSON, XSD).
//
Функция ТекстДвоичногоМакета(ИмяМакета) Экспорт
Данные = ПолучитьОбщийМакет(ИмяМакета);
Возврат ПолучитьСтрокуИзДвоичныхДанных(Данные, КодировкаТекста.UTF8);
КонецФункции
// Сохраняет общий макет типа "Двоичные данные" во временный файл на сервере
// (шаблон Word, Excel и т.п.). После работы файл удалить: УдалитьФайлы(ИмяФайла).
//
Функция ДвоичныйМакетВоВременныйФайл(ИмяМакета, Расширение) Экспорт
ИмяФайла = ПолучитьИмяВременногоФайла(Расширение);
Данные = ПолучитьОбщийМакет(ИмяМакета);
Данные.Записать(ИмяФайла);
Возврат ИмяФайла;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Функция МенеджерОбъекта(МетаданныеОбъекта)
Имя = МетаданныеОбъекта.Имя;
Если Метаданные.Документы.Содержит(МетаданныеОбъекта) Тогда
Возврат Документы[Имя];
ИначеЕсли Метаданные.Справочники.Содержит(МетаданныеОбъекта) Тогда
Возврат Справочники[Имя];
ИначеЕсли Метаданные.Обработки.Содержит(МетаданныеОбъекта) Тогда
Возврат Обработки[Имя];
ИначеЕсли Метаданные.Отчеты.Содержит(МетаданныеОбъекта) Тогда
Возврат Отчеты[Имя];
ИначеЕсли Метаданные.РегистрыСведений.Содержит(МетаданныеОбъекта) Тогда
Возврат РегистрыСведений[Имя];
ИначеЕсли Метаданные.РегистрыНакопления.Содержит(МетаданныеОбъекта) Тогда
Возврат РегистрыНакопления[Имя];
КонецЕсли;
ВызватьИсключение СтрШаблон(НСтр("ru = 'Для %1 получение макета не предусмотрено'"),
МетаданныеОбъекта.ПолноеИмя());
КонецФункции
#КонецОбласти
Второй пример — форма внешней обработки: как в 1С получить макет обработки на сервере, заполнить его области и показать результат на клиенте.
// Модуль управляемой формы внешней обработки.
// У обработки есть табличная часть Товары (Номенклатура, Количество, Цена, Сумма)
// и табличный макет "Бланк" с областями "Шапка" и "Строка".
&НаКлиенте
Процедура Сформировать(Команда)
ТабДок = СформироватьНаСервере();
ТабДок.Показать(НСтр("ru = 'Список товаров'"));
КонецПроцедуры
&НаСервере
Функция СформироватьНаСервере()
// У внешней обработки нет менеджера в коллекции Обработки,
// поэтому макет берем у объекта.
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
Макет = ОбработкаОбъект.ПолучитьМакет("Бланк");
// Области получаем один раз, до цикла.
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
ТабДок = Новый ТабличныйДокумент;
ОбластьШапка.Параметры.ДатаФормирования = ТекущаяДатаСеанса();
ТабДок.Вывести(ОбластьШапка);
Для Каждого СтрокаТоваров Из ОбработкаОбъект.Товары Цикл
ЗаполнитьЗначенияСвойств(ОбластьСтрока.Параметры, СтрокаТоваров);
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
Возврат ТабДок;
КонецФункции
Метаданные.НайтиПоПолномуИмени и Макеты.Найти — проверка до вызова. Вместо общей ошибки платформы получаете сообщение с именем объекта и макета. Полное имя передаётся в том виде, в каком его возвращает ПолноеИмя(): "Документ.ЗаказКлиента".МенеджерОбъекта — коллекции Документы, Справочники и другие индексируются именем объекта, а Содержит определяет вид метаданных. Макеты есть не у всех объектов, поэтому неподдерживаемый вид отсекается исключением раньше, чем код обратится к свойству Макеты. Нужны планы видов характеристик или бизнес-процессы — добавьте ветки по тому же образцу.ПолучитьМакет каждый раз возвращает новую копию. Изменения копии — текст ячеек, ширина колонок — не попадают ни в конфигурацию, ни в следующий вызов. Поэтому макет и области получают один раз до цикла, а не на каждой строке.ТекстПоШаблону — метки {Имя} придуманы нами, платформа их не обрабатывает. Даты и суммы форматируйте функцией Формат до передачи в структуру, иначе Строка() выведет дату вместе со временем.РеквизитФормыВЗначение("Объект") работает только в процедуре с директивой &НаСервере: ей нужны данные формы. Для обработки из конфигурации удобнее Обработки.Имя.ПолучитьМакет в процедуре &НаСервереБезКонтекста — на сервер не передаются данные формы.ЗаполнитьЗначенияСвойств(ОбластьСтрока.Параметры, СтрокаТоваров) переносит значения по совпадению имён. Параметр, которому не нашлось колонки с таким же именем, молча остаётся пустым.С нетабличными макетами код короче: получить объект и отдать его тому, кто умеет с ним работать. HTML-макет превращается в строку для поля HTML на форме, схема компоновки — в источник настроек для компоновщика:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// ТекстСправки - реквизит формы типа Строка,
// на форме выведен полем с видом "Поле HTML-документа".
ТекстСправки = ПолучитьОбщийМакет("СправкаПоЗагрузке").ПолучитьТекст();
// Схема компоновки из макета обработки - для настройки отбора на форме.
// АдресСхемы - реквизит формы типа Строка,
// КомпоновщикОтбора - реквизит типа КомпоновщикНастроекКомпоновкиДанных.
Схема = Обработки.ЗагрузкаПрайса.ПолучитьМакет("СхемаОтбора");
АдресСхемы = ПоместитьВоВременноеХранилище(Схема, УникальныйИдентификатор);
КомпоновщикОтбора.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(АдресСхемы));
КомпоновщикОтбора.ЗагрузитьНастройки(Схема.НастройкиПоУмолчанию);
КонецПроцедуры
Схему компоновки нельзя передать на клиент как значение, поэтому она уходит на форму адресом во временном хранилище. Табличный документ, строку и двоичные данные, наоборот, можно вернуть из серверной функции напрямую.
Если в конфигурации несколько языков, у макетов два механизма локализации. Тексты ячеек табличного макета задаются в конфигураторе на каждом языке конфигурации, и при выводе платформа по умолчанию берёт язык сеанса. Вывести форму на другом языке — например, счёт для иностранного покупателя — можно, не меняя язык сеанса:
Макет = Документы.ЗаказКлиента.ПолучитьМакет("ПФ_MXL_Заказ");
Макет.КодЯзыка = "en"; // многоязычные тексты ячеек пойдут на английском
Письмо = ПолучитьОбщийМакет("ШаблонПисьма"); // ТекстовыйДокумент
Письмо.КодЯзыкаМакета = "en";
Для текстового макета и HTML-макета то же делает свойство КодЯзыкаМакета. Двоичный макет так не переведёшь, поэтому для каждого языка заводят отдельный макет с суффиксом: ШаблонДоговора, ШаблонДоговора_en. Функция ОбщийМакетНаЯзыкеСеанса из модуля выше выбирает нужный вариант и откатывается к основному, если перевода нет.
ПолучитьМакет у менеджера и ПолучитьОбщийМакет работают на сервере, в толстом клиенте и во внешнем соединении. В тонком и веб-клиенте их нет, поэтому в управляемом приложении схема одна: клиентская процедура вызывает серверную, та получает макет, заполняет его и возвращает результат.
В обычных формах модуль формы обработки выполняется в контексте объекта, и в старых конфигурациях там пишут просто ПолучитьМакет("Бланк"). Перенос такого кода в управляемую форму без изменений — самая частая причина первой ошибки из списка ниже.
РеквизитФормыВЗначение("Объект").ПолучитьМакет(...) в процедуре &НаСервере или на вызов через менеджер."Строка|Колонка".ЗаполнитьЗначенияСвойств не нашёл совпадающих имён: параметр называется «Товар», а колонка — «Номенклатура». Переименуйте параметр или заполните его отдельной строкой.ПолучитьМакет читает макет из конфигурации и эту копию не видит. Для печатных форм БСП берите макет через УправлениеПечатью.МакетПечатнойФормы("Документ.ЗаказКлиента.ПФ_MXL_Заказ").ПолучитьМакет и ПолучитьОбласть вызываются внутри цикла по документам. Получите их один раз перед циклом.В конфигурацию — нет: код работает с копией, сам макет меняется только в конфигураторе. Если пользователям нужно править бланк самим, изменённую копию хранят в базе, например в регистре сведений с ресурсом типа ХранилищеЗначения, и при печати сначала ищут её там. БСП делает именно так.
ПолучитьМакет — метод менеджера или объекта, ищет среди макетов конкретного объекта. ПолучитьОбщийМакет — метод глобального контекста, ищет в ветке «Общие макеты». Макет документа через ПолучитьОбщийМакет не получить, и наоборот.
Только через объект обработки. В её модуле объекта — ПолучитьМакет без префикса. Снаружи сначала создают объект подключённой внешней обработки, затем вызывают у него ПолучитьМакет. Менеджера вида Обработки.Имя у внешней обработки нет.
В макете — если шаблон меняется только вместе с релизом конфигурации. Если его правят пользователи или у каждой организации свой бланк, храните файл в базе (присоединённые файлы, реквизит типа ХранилищеЗначения), а макет оставьте как вариант по умолчанию.
Через метаданные: Метаданные.Документы.ЗаказКлиента.Макеты.Найти("ИмяМакета") вернёт Неопределено, если макета нет. Для общего макета — Метаданные.ОбщиеМакеты.Найти, для внешней обработки — ОбработкаОбъект.Метаданные().Макеты.Найти.
Если нужен не один макет, а комплект печатных форм под фирменный бланк, выгрузка по чужому XML-шаблону или отчёт на СКД с несколькими наборами данных, быстрее отдать задачу программисту. На 1c-only.ru это делают в рамках разработки отчётов и обработок 1С, печатные формы — отдельное направление в списке услуг. Разместите задачу — оценка бесплатная, ответ в течение рабочего дня.
Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.