Макет в клиентском коде 1С 8.3: серверный вызов, временное хранилище и кэш
Содержание
В тонком и веб-клиенте 1С 8.3 макет напрямую на клиенте не получить: метод ПолучитьМакет() и глобальный ПолучитьОбщийМакет() работают на сервере. Рабочая схема одна: серверная функция получает макет и возвращает его на клиент. Табличный или текстовый документ можно вернуть прямо как значение. Двоичные данные — значением или через временное хранилище, если файл крупный или его нужно сохранить на диск пользователя.
Какой способ выбрать, зависит от типа макета и от того, что вы с ним делаете дальше. Для печатной формы хватает серверного вызова без контекста. Для шаблона Word или Excel, который пользователь скачивает, удобнее временное хранилище. Для внешней обработки нужен серверный вызов с контекстом формы.
| Задача | Способ | Где выполняется |
|---|---|---|
| Заполнить и показать табличный документ | Функция &НаСервереБезКонтекста возвращает ТабличныйДокумент | Сервер → клиент |
| Отдать пользователю файл-шаблон (docx, xlsx) | Двоичные данные → ПоместитьВоВременноеХранилище → адрес на клиент | Сервер → хранилище → клиент |
| Макет внешней обработки или отчёта | &НаСервере + РеквизитФормыВЗначение("Объект") | Сервер, с контекстом формы |
| Многократный вывод без лишних вызовов | Получить один раз и кэшировать в клиентской переменной формы | Клиент |
| Обычное приложение, толстый клиент | Прямой вызов ПолучитьМакет() из модуля объекта | Клиент (только толстый) |
&НаСервереБезКонтекста, функция возвращает готовый ТабличныйДокумент. Заполняйте области на сервере, если нужны данные базы; на клиенте — если данные уже есть в форме.&НаСервере: объект обработки берётся из реквизита формы через РеквизитФормыВЗначение("Объект"), у него и вызываете ПолучитьМакет().Почему ПолучитьМакет() не вызывается на клиенте
Макет — часть метаданных конфигурации. Доступ к нему дают менеджеры (Документы.ИмяДокумента, Обработки.ИмяОбработки) и объекты прикладных типов. В управляемом приложении менеджеры на клиенте урезаны: ссылки и ПустаяСсылка() доступны, а ПолучитьМакет() — нет.
Если написать такой код в процедуре с директивой &НаКлиенте, тонкий клиент упадёт при выполнении с ошибкой вида Метод объекта не обнаружен (ПолучитьМакет). То же с ПолучитьОбщийМакет() для общих макетов.
Что при этом доступно на клиенте:
- ✅ сам объект
ТабличныйДокументи его методыПолучитьОбласть(),Вывести(),Присоединить(); - ✅ параметры областей:
Область.Параметры.ИмяПараметра = Значение; - ✅
ПолучитьИзВременногоХранилища(Адрес)— чтобы забрать то, что положил сервер; - ❌ получение макета из метаданных: только сервер.
Отсюда простой вывод: сервер «достаёт» макет, клиент с ним работает. Вся инструкция ниже — вариации этой схемы.
Если конфигурация в режиме обычного приложения и запускается только толстым клиентом, ПолучитьМакет() из модуля формы объекта работает напрямую. Но такой код ломается при переходе на тонкий или веб-клиент. Для новых разработок на него не опирайтесь.
Как получить макет на клиенте через серверную функцию
Самый частый случай — печатная форма из макета табличного документа. Сервер возвращает табличный документ целиком, клиент показывает его в поле формы или в отдельном окне.
Шаг 1. Серверная функция без контекста
&НаСервереБезКонтекста
Функция МакетСчета()
Возврат Документы.СчетНаОплатуПокупателю.ПолучитьМакет("ПечатнаяФорма");
КонецФункции
Директива &НаСервереБезКонтекста здесь принципиальна. С обычной &НаСервере на сервер и обратно уезжают все реквизиты формы. Если в форме уже лежит заполненный табличный документ или большая таблица, каждый вызов будет тяжёлым.
Шаг 2. Вызов и вывод на клиенте
&НаКлиенте
Процедура Сформировать(Команда)
Макет = МакетСчета();
ТабДок = Новый ТабличныйДокумент;
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ОбластьШапка.Параметры.НомерДокумента = НомерСчета;
ОбластьШапка.Параметры.ДатаДокумента = Формат(ДатаСчета, "ДЛФ=D");
ТабДок.Вывести(ОбластьШапка);
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого СтрокаТЧ Из Объект.Товары Цикл
ЗаполнитьЗначенияСвойств(ОбластьСтрока.Параметры, СтрокаТЧ);
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
ТабДок.Показать("Счёт на оплату");
КонецПроцедуры
Имена Шапка, Строка и параметры — это имена областей и параметров в вашем макете. Откройте макет в конфигураторе и сверьте их через свойства ячеек и областей.
Шаг 3. Решить, где заполнять
Заполнять области можно и на сервере, и на клиенте. Правило простое:
- 📦 нужны данные из базы (остатки, реквизиты контрагента, запрос) — заполняйте на сервере и возвращайте готовый документ;
- 🖥 все данные уже в форме — можно заполнять на клиенте, сервер нужен только для самого макета.
Заполнение на сервере почти всегда быстрее: один вызов вместо цепочки «получить макет → вернуться на сервер за данными».
Двоичные данные, временное хранилище и выгрузка макета в файл
Макеты типа «Двоичные данные» обычно хранят шаблоны Word и Excel, картинки, XML-заготовки. Их тоже можно вернуть значением, но для файлов удобнее временное хранилище: клиент получает строку-адрес, а файл забирает, когда нужно.
Положить макет во временное хранилище
&НаСервере
Функция АдресШаблонаДоговора()
ДвДанные = Обработки.ПечатьДоговоров.ПолучитьМакет("ШаблонДоговора");
Возврат ПоместитьВоВременноеХранилище(ДвДанные, УникальныйИдентификатор);
КонецФункции
Второй параметр — УникальныйИдентификатор формы. Данные живут, пока открыта форма, и не копятся в памяти сеанса. Поэтому функция с контекстом (&НаСервере): уникальный идентификатор — свойство формы.
Забрать на клиенте
&НаКлиенте
Процедура ОткрытьШаблон(Команда)
Адрес = АдресШаблонаДоговора();
ДвДанные = ПолучитьИзВременногоХранилища(Адрес);
// дальше — сохранить файл пользователю
КонецПроцедуры
Для сохранения на диск в современных конфигурациях на БСП есть ФайловаяСистемаКлиент.СохранитьФайл(): процедура принимает описание оповещения, адрес во временном хранилище и имя файла. Она сама выбирает асинхронный вариант для веб-клиента. Без БСП используйте асинхронные методы платформы для получения файлов с сервера.
Выгрузить макет в файл вручную
Иногда макет нужен не в коде, а у вас на диске: отправить коллеге, поправить в Excel, сравнить версии.
- Откройте конфигуратор, найдите объект в дереве метаданных, раскройте ветку
Макеты. - Откройте макет двойным щелчком.
- В меню
Файлвыберите сохранение в файл и укажите формат: для табличного документа —.mxl, для двоичных данных — исходное расширение.
Обратно файл загружают командой замены макета в контекстном меню макета в дереве метаданных. После этого конфигурацию сохраняют и обновляют конфигурацию базы данных.
Программно табличный документ выгружают на сервере методом ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.MXL). Затем его можно прочитать в ДвоичныеДанные и передать клиенту той же схемой через хранилище.
Макеты в управляемых формах и БСП: что учесть
Макеты, изменённые пользователем
В типовых конфигурациях на БСП бухгалтер может поправить печатную форму сам: Администрирование → Печатные формы, отчеты и обработки → Макеты печатных форм. Изменённая копия хранится в базе, а не в конфигурации.
Если получать макет через ПолучитьМакет() напрямую, правки пользователя не подхватятся. Он увидит старый вид счёта и решит, что программа «не сохраняет макет». В конфигурациях на БСП берите макет через УправлениеПечатью.МакетПечатнойФормы("Документ.ИмяДокумента.ИмяМакета"). Функция серверная, возвращает пользовательскую версию, если она есть, и типовую, если нет.
Не храните тяжёлые макеты в реквизитах формы
Реквизит формы типа ТабличныйДокумент удобен для поля просмотра. Но каждый вызов &НаСервере гоняет его по сети туда и обратно. Если документ большой (сотни строк, картинки), форма начинает подтормаживать на любой кнопке.
Что помогает:
- 🔹 вызовы без контекста везде, где не нужны реквизиты формы;
- 🔹 сам макет — в клиентской переменной модуля формы, а не в реквизите;
- 🔹 в реквизит кладите только результат, который пользователь видит.
Кэш макета на клиенте
&НаКлиенте
Перем КэшМакета;
&НаКлиенте
Функция МакетЭтикетки()
Если КэшМакета = Неопределено Тогда
КэшМакета = ПолучитьМакетЭтикеткиНаСервере();
КонецЕсли;
Возврат КэшМакета;
КонецФункции
&НаСервереБезКонтекста
Функция ПолучитьМакетЭтикеткиНаСервере()
Возврат Обработки.ПечатьЭтикеток.ПолучитьМакет("Этикетка");
КонецФункции
Переменная живёт, пока открыта форма. Сто этикеток подряд — один вызов сервера вместо ста.
Получение макетов из внешних обработок и отчётов
У внешней обработки нет менеджера в дереве метаданных, поэтому Обработки.Имя.ПолучитьМакет() не подходит. Макет берут у объекта обработки.
Из формы самой внешней обработки
&НаСервере
Функция МакетОбработки()
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
Возврат ОбработкаОбъект.ПолучитьМакет("ПечатнаяФорма");
КонецФункции
РеквизитФормыВЗначение() работает только с контекстом формы. С директивой &НаСервереБезКонтекста функция не скомпилируется.
Из модуля объекта обработки
Если печать вызывается из модуля объекта (так устроены внешние печатные формы для БСП), макет доступен прямо: ЭтотОбъект.ПолучитьМакет("ПечатнаяФорма") или просто ПолучитьМакет("ПечатнаяФорма"). Модуль объекта выполняется на сервере, ограничений клиента там нет.
Обработка из файла, которая не зарегистрирована в базе
- На клиенте пользователь выбирает файл
.epf, файл помещается во временное хранилище. - На сервере обработка подключается методом
ВнешниеОбработки.Подключить(Адрес, , БезопасныйРежим), который возвращает её имя. - Объект создаётся через
ВнешниеОбработки.Создать(Имя), и у него вызываетсяПолучитьМакет(). - Готовый макет или заполненный документ возвращается на клиент.
Платформа предупреждает о потенциально опасных действиях при открытии внешних файлов. Подключайте только обработки из надёжного источника и не отключайте эту защиту ради удобства.
Для внешнего отчёта всё так же, только менеджер — ВнешниеОтчеты. Если макет — схема компоновки данных, её обычно не таскают на клиент: отчёт формируется на сервере, клиент получает результат.
Различия в толстом, тонком и веб-клиенте
| Клиент | Получить макет на клиенте | Сохранить файл на диск | Что учесть |
|---|---|---|---|
| Толстый, обычное приложение | Да, ПолучитьМакет() из модуля объекта или формы | Синхронные методы работают | Код непереносим в тонкий клиент |
| Толстый, управляемое приложение | Технически возможно, но не опирайтесь | Да | Пишите как для тонкого клиента |
| Тонкий клиент | Только через сервер | Да, лучше асинхронно | Следите за объёмом передачи |
| Веб-клиент | Только через сервер | Асинхронные методы; доступ к файлам может требовать расширения работы с файлами | Синхронные вызовы могут быть запрещены настройками конфигурации |
В веб-клиенте чаще всего ломается не получение макета, а сохранение файла. Если конфигурация запрещает синхронные вызовы расширений платформы, старые ПолучитьФайл() и запись ДвоичныеДанные.Записать() на клиенте выдадут ошибку. Переходите на асинхронные методы или на ФайловаяСистемаКлиент из БСП.
Проверяйте код сразу в тонком клиенте. Режим запуска из конфигуратора задают в Сервис → Параметры → Запуск 1С:Предприятия. Ошибка с методом на клиенте всплывёт в первом же тесте, а не у пользователя.
Пример: динамическая модификация макета на клиенте
Задача: форма печати ценников. Пользователь отмечает, выводить ли штрихкод и старую цену, и сразу видит результат. Ходить на сервер на каждый щелчок флажка не хочется.
Макет Ценник содержит области:
Заголовок— наименование и артикул;СтараяЦена— зачёркнутая цена;Цена— актуальная цена;Штрихкод— строка с кодом.
Макет получаем один раз (кэш из раздела выше), дальше собираем документ на клиенте:
&НаКлиенте
Процедура ОбновитьПредпросмотр()
Макет = МакетЦенника();
Результат = Новый ТабличныйДокумент;
Для Каждого Строка Из Товары Цикл
Область = Макет.ПолучитьОбласть("Заголовок");
Область.Параметры.Наименование = Строка.Наименование;
Область.Параметры.Артикул = Строка.Артикул;
Результат.Вывести(Область);
Если ПоказыватьСтаруюЦену И Строка.СтараяЦена > Строка.Цена Тогда
Область = Макет.ПолучитьОбласть("СтараяЦена");
Область.Параметры.СтараяЦена = Формат(Строка.СтараяЦена, "ЧДЦ=2");
Результат.Вывести(Область);
КонецЕсли;
Область = Макет.ПолучитьОбласть("Цена");
Область.Параметры.Цена = Формат(Строка.Цена, "ЧДЦ=2");
Результат.Вывести(Область);
Если ПоказыватьШтрихкод Тогда
Область = Макет.ПолучитьОбласть("Штрихкод");
Область.Параметры.Штрихкод = Строка.Штрихкод;
Результат.Вывести(Область);
КонецЕсли;
КонецЦикла;
Предпросмотр = Результат;
КонецПроцедуры
&НаКлиенте
Процедура ПоказыватьШтрихкодПриИзменении(Элемент)
ОбновитьПредпросмотр();
КонецПроцедуры
Здесь Товары — таблица значений формы, Предпросмотр — реквизит типа ТабличныйДокумент, связанный с полем на форме. Флажки ПоказыватьСтаруюЦену и ПоказыватьШтрихкод — булевы реквизиты.
Что даёт такой подход:
- Сервер вызывается один раз — при первом формировании.
- Переключение флажков перестраивает документ мгновенно, даже на медленном канале.
- Логика вывода остаётся в одном месте, её легко дополнить новой областью.
Если ценников тысячи, перенесите сборку на сервер: вывод тысяч областей на клиенте нагружает компьютер пользователя, а итоговый документ всё равно придётся передать.
Типичные ошибки при получении макета
&НаКлиенте. Перенесите получение макета в функцию &НаСервереБезКонтекста и верните результат клиенту.&НаСервереБезКонтекста. Для внешней обработки нужен контекст формы: замените директиву на &НаСервере.УправлениеПечатью.МакетПечатнойФормы().ФайловаяСистемаКлиент.СохранитьФайл().&НаСервере. Перейдите на вызовы без контекста и держите макет в клиентской переменной.Частые вопросы
Можно ли вернуть с сервера на клиент любой макет?
Чем ПолучитьМакет отличается от ПолучитьОбщийМакет?
ПолучитьМакет() возвращает макет конкретного объекта: документа, обработки, отчёта. ПолучитьОбщийМакет() — макет из ветки Общие → Общие макеты. Оба работают на сервере.Нужно ли удалять данные из временного хранилища?
УдалитьИзВременногоХранилища(Адрес).Можно ли менять оформление ячеек на клиенте?
Как получить макет внешней печатной формы, подключённой через БСП?
ПолучитьМакет("ИмяМакета") без дополнительных серверных функций.