Предисловие: Этот способ является лишь альтернативой стандартному, который вы можете почерпнуть из цикла статей от poppy
1. Внешние печатные формы в восьмерке
2. Внешние печатные формы в восьмерке II
3. Обработка для тестирования внешних печатных форм в восьмерке
Как показала практика, применение этого способа оправдано лишь в очень редких случаях. Но сам по себе способ итересен в смысле возможности исполнения процедур и функций, которые будут выполнятся в контексте другого объекта.
Итак. Чтобы далеко не ходить, возьмем типовую 1С Бухгалтерию 1.6. И сделаем для нее внешнюю печатную форму печати счета-фактуры выданного со своим макетом и с возможностью изменения модуля формирования печатной формы.
Мы проделаем такую работу:
1. Создадим внешнюю печатную форму, повторяющую типовую.
2. Заменим в печати в поле грузоотправителя "он же" на данные организации.
3. Немного изменим макет.
Начнем :)
Начало ничем не отличается от создания обыной внешней печатной формы.
1. Создаем внешнюю обработку.
2. Назавем ее "ВнешнийСчетФактураВыданный".
3. Добавим реквизит "СсылкаНаОбъект" с типом "ДокументСсылка.СчетФактураВыданный".
4. В модуле обработки создадим экспортную функцию "Печать".
5. Добавим форму, упрощающую отладку (идея была почерпнута с инфостарта). Назовем ее "ФормаПрямойПечати". В ней должно быть полеВвода для ввода значения "СсылкаНаОбъект". А по нажатю на кнопку "Выполнить" будет вызываться наша функция "Печать" с выводом на экран результата.
Процедура КнопкаВыполнитьНажатие(Кнопка)
Печать().Показать();
КонецПроцедуры
Это позволит печатать вызывать нашу обработку без подключения внешней печатной формы, просто открыв файл.
6. Скопируем макет счета фактуры в нашу обработку. Так как этих макетов полно, скопируем все. На всякий случай.
Пока все как обычно. Результат - см рисунок 1.
А вот теперь, начинается "Магия".
7. Создаем еще одну форму. Назовем ее "ФормаСчетаФактуры".
8. Изменим основной реквизит второй формы ("ФормаСчетаФактуры"): Поменяем наименование с "ОбработкаОбъект" на "ДокументОбъект", а тип с "ВнешняяОбработка.ВнешнийСчетФактураВыданный" на "ДокументОбъект.СчетФактураВыданный". Обращаю ваше внимание, именно ДокументОбъект!
9. В модуле формы объявим экпортную переменную "ВнОбработка". Она будет содержать объект нашей внешней обработки для доступа к макетам. Почему не реквизит? Потому что при использовании реквизита, она (обработка) оставалась в активной в предприятии, даже после закрытия всех окон.
10. В модуле обработки в функции "Печать" добавим код:
Функция Печать() Экспорт
СчетФактураОбъект = СсылкаНаОбъект.ПолучитьОбъект();
ФормаСчетаФактуры = ПолучитьФорму("ФормаСчетаФактуры");
ФормаСчетаФактуры.ДокументОбъект = СчетФактураОбъект;
ФормаСчетаФактуры.ВнОбработка = ЭтотОбъект;
ТабДок = ФормаСчетаФактуры.ПечатьВнешнейФормы();
Возврат(ТабДок);
КонецФункции
Стоит немного отвлечься и объяснить. Итак. При вызове функции "Печать()" из СсылкаНаОбъект мы получаем объект документа СчетаФактуры. Значение этого объект мы используем для передачи его в основной реквизит формы "ФормаСчетаФактуры". Как только мы это сделали, форма "ФормаСчетаФактуры" ничем не отличается от формы, созданной в дереве метаданных в документе "СчетФактураВыданный". То есть, после этого форма "думает" что она - форма документа "СчетФактураВыданный", и ей доступен весь контекст объекта по прямому обращению. И все экспортные переменные, функции и процедуры, реквизиты и табличные части.
Дело за малым:
11. Переносим (методом копировать/вставить) из модуля Документа в модуль формы "ФормаСчетаФактуры" все необходимые процедуры. А их надо сказать у Счета-фактуры много:
- ИнициализацияТаблицыСтрок
- СобратьДанныеПоОтчетКомитентуОПродажах
- СобратьДанныеПоОтчетКомиссионераОПродажах
- СобратьДанныеПоРеализацияТоваровУслуг
- СобратьДанныеПоВозвратТоваровПоставщику
- СобратьДанныеПоПКО
- СобратьДанныеПоСВП
- СобратьДанныеПоПлатежномуОрдеру
- СобратьДанныеПоАкту
- СобратьДанныеПоПередачеОС
- СобратьДанныеПоПередачеНМАОрганизаций
- СобратьДанныеПоОтражениюРеализацииТоваровИУслуг
- СобратьДанныеПоРеализацияУслугПоПереработке
- СобратьДанныеПоПринятиюКУчетуОС
- СобратьДанныеПоМодернизацииОС
- СобратьДанныеПоНачислениеНДСпоСМРхозспособом
- СобратьДанныеСФнаАвансИСуммовуюРазницу
- ПроставитьПрочеркиВПустыеПоля
- ПерезаполнитьСуммыПоУЕвРублях
- ПечатьСчетаФактуры
Но пусть вас не пугает их количество. Как видите большинство из них это "СобратьДанные...". И служебные для печати. Также есть функция "ПечатьСчетаФактуры".
Стоит заметить что все они не экспортные. Именно из-за этого мы их и копировали.
Отдельный разговор по переносу процедуры Печать(...) из модуля документа.
Это самый сложный момент.
Переименуем ее в ПечатьВнешнейФормы. Но мало того, переделаем ее в функцию. Для этого заменим все "Возврат" на Возврат (Неопределено).
А вызов процедуры в конце модуля процедуры
УниверсальныеМеханизмы.НапечататьДокумент(ТабДокумент, КоличествоЭкземпляров, НаПринтер, ОбщегоНазначения.СформироватьЗаголовокДокумента(ЭтотОбъект, ЭтотОбъект.Метаданные().Представление()), НепосредственнаяПечать);
заменим на
Возврат(ТабДокумент);
Также теперь нам не нужны параметры: КоличествоЭкземпляров, НаПринтер, НепосредственнаяПечать.
Да и параметр "ИмяМакета" нам неактуален. Просто зададим его значение в теле функции:
ИмяМакета = "СчетФактура";
убрав его из параметров.
12. Осталось заменить вызов общих Макетов на макеты из обработки. Меняем строки вида
Макет = ПолучитьОбщийМакет("...") и Макет = ПолучитьМакет("...")
заменим на
Макет = ВнОбработка.ПолучитьМакет("...");
ВСЁ! (практически)
У нас есть внешняя печатная форма Счета-Фактуры, с перенесенными в неё функциями и процедурами формирования и макетами.
Сохраняем. Ага - ругается на "мНадписьПредоплата". Смотрим в модуле документа - это переменная модуля объекта. Объявляем в нашей форме и присваеваем значение(как в модуле документа).
Перем ВнОбработка Экспорт;
Перем мНадписьПредоплата;
//... (все процедуры и функции)
мНадписьПредоплата = "Предварительная оплата";
Октрываем в 1С предприятие и тестируем!).
Заменяем Грузоотправитель.
В функции ПечатьВнешнейФормы после строк
Если ДанныеДляПечати = Неопределено или ТипЗнч(ДанныеДляПечати) = Тип("Соответствие") Тогда
Продолжить;
КонецЕсли
Вставляем
// Заменяем в печати "он же" на Организацию
Если ДанныеДляПечати.Грузоотправитель = "он же" тогда
ДанныеДляПечати.Грузоотправитель = ДанныеДляПечати.Организация;
КонецЕсли;
А вот теперь вообще всё! Меняем как хотим макеты, получение данных, формирование печатных форм.
PS. Обработку см во вложении.
Дополнение1. Рассмотрен "сложный" пример. Счет на оплату, накладная и проч печатаются еще легче, но принцип тот же. Критика и замечания приветствуются.
Дополнение2. Работает только на релизе платформы старше 8.1.11.
Дополнение3. Долго думал над картинками. Так и не придумал.
Дополнение4. При подключении внешней печатной формы можно заместить ей штатную, дабы не напрягать юзеров выбором в диалоге (с) Поручик
Дополнение5. Для тестирования и отладки внешней печатной формы вместо создания спецформы в КАЖДОЙ обработке можно воспользоваться инструментом от poppy //infostart.ru/public/14686/ (с) artbear
Дополнение6. Шаблоны для создания внешних печатных форм и примеры внешних печатных форм http://www.infostart.ru/public/67060/ (с) alexk-is