Как обычно, сначала поискал готовое решение. Максимально близко решение данной задачи описано в этой публикации: //infostart.ru/public/92500/. С той лишь разницей, что там данная задача решалась для конфигурации УТ 11.
Тем не менее, именно эта публикация была взята за основу, и часть работающего кода заимствована оттуда.
РС (регистр сведений) "Пользовательские макеты печати", в котором собственно хранятся макеты, измененные пользователем, является частью подсистемы Печать из БСП (библиотеки стандартных подсистем). И поначалу я думал, что придётся внедрять в УПП версию БСП 2.1. Однако оказалось, что в УПП 1.3 последних версий данный регистр уже включен и даже используется в паре объектов конфигурации. Например, в документе "Выпуск продукции". Это существенно сокращает количество изменений, которые придется внести в конфигурацию, но давайте по порядку.
1. Чтобы дополнить перечень объектов, которые мы видим в форме РС ПользовательскиеМакетыПечати и для которых мы можем редактировать пользовательский макет, надо внести изменения в форму МакетыПечатныхФорм. Также надо не забыть увеличить длину измерения Объект в этом РС, на случай слишком длинного наименования ВПФ (внешней печатной формы). Я указал длину 250.
// ----------------------------------------------------------------------------
&НаСервере
Процедура ЗаполнитьСписокМетаданных(Фильтр = Неопределено)
СписокМакетовДерево = РеквизитФормыВЗначение("СписокМакетов");
ЗаполнитьДеревоПоКоллекцииМетаданных(СписокМакетовДерево, Метаданные.Справочники, Ложь, Фильтр);
ЗаполнитьДеревоПоКоллекцииМетаданных(СписокМакетовДерево, Метаданные.Документы, Ложь, Фильтр);
ЗаполнитьДеревоПоКоллекцииМетаданных(СписокМакетовДерево, Метаданные.Обработки, Ложь);
ЗаполнитьДеревоПоКоллекцииМетаданных(СписокМакетовДерево, Метаданные.ОбщиеМакеты, Истина);
// Miha
ЗапросВПФ = Новый Запрос;
ЗапросВПФ.Текст =
"ВЫБРАТЬ
| ВнешниеОбработки.Ссылка,
| ВнешниеОбработки.Наименование,
| ВнешниеОбработки.ХранилищеВнешнейОбработки
|ИЗ
| Справочник.ВнешниеОбработки КАК ВнешниеОбработки
|ГДЕ
| ВнешниеОбработки.ВидОбработки = ЗНАЧЕНИЕ(Перечисление.ВидыДополнительныхВнешнихОбработок.ПечатнаяФорма)
| И НЕ ВнешниеОбработки.ПометкаУдаления
| И НЕ ВнешниеОбработки.ЭтоГруппа";
Выборка = ЗапросВПФ.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ОбработкаEPF = Выборка.ХранилищеВнешнейОбработки.Получить();
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("epf");
ОбработкаEPF.Записать(ИмяВременногоФайла);
ВнешОбработка = ВнешниеОбработки.Создать(ИмяВременногоФайла);
ДобавитьКоллекциюМакетов(ВнешОбработка.Метаданные().Макеты,
СписокМакетовДерево,
"Справочники.ВнешниеОбработки/"+Выборка.Ссылка.УникальныйИдентификатор()+"#",
Выборка.Наименование,
Фильтр);
КонецЦикла;
// Miha - End
Если СписокМакетовДерево.Строки.Количество() > 0 Тогда
// ----------------------------------------------------------------------------
2. Чтобы появилась возможность получить для редактирования макет из ВПФ и сохранить его в наш регистр, надо доработать общий модуль УправлениеПечатью.
// --------------------------------------------------------------------------
Функция ПолучитьМакет(ПолныйПутьКМакету) Экспорт
ЧастиПути = СтрЗаменить(ПолныйПутьКМакету, ".", Символы.ПС);
Если СтрЧислоСтрок(ЧастиПути) = 3 Тогда
// Miha
Если Лев(ПолныйПутьКМакету,12) = "Справочники." Тогда
абПозиция=Найти(ПолныйПутьКМакету,"/");
абПозиция1=Найти(ПолныйПутьКМакету,"#");;
Если абПозиция<>0 Тогда
СтрокаУИД=Сред(ПолныйПутьКМакету,абПозиция+1,абПозиция1-абПозиция-1);
УИД=Новый УникальныйИдентификатор(СтрокаУИД);
абОбъект=Справочники.ВнешниеОбработки.ПолучитьСсылку(УИД);
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПользовательскиеМакетыПечати.ИмяМакета,
| ПользовательскиеМакетыПечати.Объект,
| ПользовательскиеМакетыПечати.Макет,
| ПользовательскиеМакетыПечати.Использование
|ИЗ
| РегистрСведений.ПользовательскиеМакетыПечати КАК ПользовательскиеМакетыПечати
|ГДЕ
| ПользовательскиеМакетыПечати.Объект ПОДОБНО &Объект";
Запрос.УстановитьПараметр("Объект", "%"+СтрокаУИД+"%");
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
абМакет=ВыборкаДетальныеЗаписи.Макет.Получить();
Результат = ПолучитьТабличныйДокументПоДвоичнымДанным(абМакет);
Возврат Результат;
Иначе
Если абОбъект<>Справочники.ВнешниеОбработки.ПустаяСсылка() Тогда
абОбработкаEPF=абОбъект.ХранилищеВнешнейОбработки.Получить();
ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
абОбработкаEPF.Записать(ИмяВременногоФайла);
абОбработка=ВнешниеОбработки.Создать(ИмяВременногоФайла);
абМакет=абОбработка.ПолучитьМакет(СтрПолучитьСтроку(ЧастиПути, 3));
Возврат абМакет;
КонецЕсли;
КонецЕсли;
КонецЕсли;
Иначе
ПутьКМетаданным = СтрПолучитьСтроку(ЧастиПути, 1) + "." + СтрПолучитьСтроку(ЧастиПути, 2);
ПутьКОбъектуМетаданных = СтрПолучитьСтроку(ЧастиПути, 3);
КонецЕсли;
//ПутьКМетаданным = СтрПолучитьСтроку(ЧастиПути, 1) + "." + СтрПолучитьСтроку(ЧастиПути, 2);
//ПутьКОбъектуМетаданных = СтрПолучитьСтроку(ЧастиПути, 3);
// Miha - End
ИначеЕсли СтрЧислоСтрок(ЧастиПути) = 2 Тогда
ПутьКМетаданным = СтрПолучитьСтроку(ЧастиПути, 1);
ПутьКОбъектуМетаданных = СтрПолучитьСтроку(ЧастиПути, 2);
Иначе
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Макет ""%1"" не найден. Операция прервана.'"), ПолныйПутьКМакету);
КонецЕсли;
// --------------------------------------------------------------------------
3. Также понадобится передавать во внешнюю обработку параметр со ссылкой на элемент справочника "Внешние обработки", чтобы ВПФ могла найти свой пользовательский макет в регистре. Для этого правим общий модуль УниверсальныеМеханизмы.
// --------------------------------------------------------------------------
Функция НапечататьВнешнююФорму(Ссылка, ИсточникМакета) Экспорт
Перем ДополнительныеПараметры;
ДвоичныеДанные = ИсточникМакета.СсылкаНаВнешнююОбработку.Принадлежность[ИсточникМакета.НомерСтроки - 1].ХранилищеВнешнейОбработки.Получить();
// Получить дополнительные параметры внешней обработки
ИсточникМакета.Свойство("ДополнительныеПараметрыОбработки", ДополнительныеПараметры);
// Miha
Если ДополнительныеПараметры = Неопределено Тогда
ДополнительныеПараметры = Новый Структура;
КонецЕсли;
ДополнительныеПараметры.Вставить("СсылкаНаВнешнююОбработку", ИсточникМакета.СсылкаНаВнешнююОбработку);
// Miha - End
// --------------------------------------------------------------------------
На этом изменения в конфигураторе завершены. Остальные изменения можно делать непосредственно в файлах ВПФ.
4. Во-первых, понадобится добавить реквизит ДополнительныеПараметры с типом Произвольный.
5. В названии макетов должно быть одно из сочетаний: ПФ_MXL, ПФ_DOC или ПФ_ODT. Это проверяется встроенной подсистемой.
6. Когда получаем макет, вместо стандартного ПолучитьМакет вызываем функцию МСК_ПолучитьМакет. Нужный код приведен ниже.
// --------------------------------------------------------------------------
Функция МСК_ПолучитьМакет(ИмяМакета)
СтрокаУИД=Строка(ДополнительныеПараметры.СсылкаНаВнешнююОбработку.УникальныйИдентификатор());
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПользовательскиеМакетыПечати.ИмяМакета,
| ПользовательскиеМакетыПечати.Объект,
| ПользовательскиеМакетыПечати.Макет
|ИЗ
| РегистрСведений.ПользовательскиеМакетыПечати КАК ПользовательскиеМакетыПечати
|ГДЕ
| ПользовательскиеМакетыПечати.Объект ПОДОБНО &Объект
| И ПользовательскиеМакетыПечати.Использование";
Запрос.УстановитьПараметр("Объект", "%"+СтрокаУИД+"%");
Результат = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = Результат.Выбрать();
Если ВыборкаДетальныеЗаписи.Следующий() Тогда
ДвМакет=ВыборкаДетальныеЗаписи.Макет.Получить();
ИспользуемыйМакет = ПолучитьТабличныйДокументПоДвоичнымДанным(ДвМакет);
Иначе
ИспользуемыйМакет = ПолучитьМакет(ИмяМакета);
КонецЕсли;
Возврат ИспользуемыйМакет;
КонецФункции
// --------------------------------------------------------------------------
Функция ПолучитьТабличныйДокументПоДвоичнымДанным(ДвоичныеДанные) Экспорт
ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
ДвоичныеДанные.Записать(ИмяВременногоФайла);
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.Прочитать(ИмяВременногоФайла);
Возврат ТабличныйДокумент;
КонецФункции
// --------------------------------------------------------------------------
Вы можете скачать готовый пример обработки и подключить её к любому документу в конфигурации, чтобы проверить, как всё работает.