Попросили создать печатную форму, да не простую, а с возможностью редактирования по кнопке «Изменить макет» общей формы Печати документа. Бегло поискал в интернете, и, не найдя готового решения, начал шерстить типовой код.
Сначала я проверил, что вообще влияет на видимость данного элемента в общей форме ПечатьДокументов - помимо прав проверяется заполнение свойства ПутьКМакету у элементов таблицы НастройкиПечатныхФорм, которое в свою очередь заполняется из свойства ПолныйПутьКМакету элементов таблицы КоллекцияПечатныхФорм. Данную таблицу мы не раз видели в модуле объекта печатных форм - в нее мы помещаем сформированный табличный документ, имя макета и много чего ещё. Так почему же ПолныйПутьКМакету пустой? Ответ был найден в процедуре УправлениеПечатью.ПечатьПоВнешнемуИсточнику:

Значит, мы должны сделать так, чтобы МакетСуществует вернул нам Истина. Долго искать не пришлось:

Мы можем передать путь, окончание которого будет содержать префикс "ПФ_" и уникальный идентификатор. Добавляем следующие строки в модуль объекта печатной формы (идентификатор для каждой новой формы генерируем свой):
Функция ПутьКМакету()
Возврат "ВнешняяОбработка.ВнешняяПечатнаяФорма.ПФ_56f3852d-0d82-4f8b-9e6b-ed7b4aea8230";
КонецФункции
Начало строки может быть любым, проверяется лишь подстрока после последней точки.
Передаём наш путь в параметрах процедуры УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию:
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(КоллекцияПечатныхФорм, ИмяМакета, СинонимМакета,
ПечатьСчетаНаОплату(МассивОбъектов, ОбъектыПечати, ПараметрыПечати),, ПутьКМакету());
Но нашего макета всё ещё нет в справочнике МакетыПечатныхФорм. Добавляем следующие функции и процедуры для записи макета в справочник и его получения:
Процедура ЗарегистрироватьМакет(Заменить) Экспорт
СсылкаМакета = Справочники.МакетыПечатныхФорм.СсылкаМакета(ПутьКМакету());
Если СсылкаМакета = Неопределено Тогда
Объ = Справочники.МакетыПечатныхФорм.СоздатьЭлемент();
ИначеЕсли Заменить Тогда
Объ = СсылкаМакета.ПолучитьОбъект();
Объ.ИсточникиДанных.Очистить();
Иначе
Возврат;
КонецЕсли;
Объ.ТипМакета = "MXL";
Объ.Идентификатор = Справочники.МакетыПечатныхФорм.ИдентификаторМакета(ПутьКМакету());
Объ.Макет = Новый ХранилищеЗначения(ПолучитьМакет("Макет"));
Объ.Наименование = "Внешняя печатная форма";
Объ.ИсточникДанных = ОбщегоНазначения.ИдентификаторОбъектаМетаданных(Метаданные.Документы.СчетНаОплатуПокупателю);
Стр = Объ.ИсточникиДанных.Добавить();
Стр.ИсточникДанных = Объ.ИсточникДанных;
Объ.Записать();
КонецПроцедуры
Функция МакетИзСправочника()
Макет = Неопределено;
Для НомерПопытки = 1 По 2 Цикл
Макет = Справочники.МакетыПечатныхФорм.НайтиМакет(
ПутьКМакету(), ОбщегоНазначения.КодОсновногоЯзыка());
Если Макет <> Неопределено Тогда
Прервать;
КонецЕсли;
Если НомерПопытки = 1 Тогда
ЗарегистрироватьМакет(Ложь);
Иначе
ВызватьИсключение "Макет не найден";
КонецЕсли;
КонецЦикла;
Возврат Макет;
КонецФункции
Теперь достаточно вызвать нашу функцию МакетИзСправочника, которая при первом вызове запишет макет в справочник, а при последующих будет запрашиваться макет из справочника. Проверим:



При последующей печати будет запрошен уже отредактированный пользователем макет. На всякий случай добавим возможность сбросить изменения - для этого я добавил команду в основную форму со следующим кодом на сервере:
ОбъектОбработки = РеквизитФормыВЗначение("Объект");
ОбъектОбработки.ЗарегистрироватьМакет(Истина);
Сообщить("Макет успешно восстановлен");
Проверено на следующих конфигурациях и релизах:
- Бухгалтерия предприятия, редакция 3.0, релизы 3.0.191.41
Вступайте в нашу телеграмм-группу Инфостарт