Практика создания заказной внешней печатной формы для УТ 11.3

Внешняя печатная форма «Счёт на оплату» для конфигурации Управление торговлей, редакция 11.3

Доброго времени суток!

   Раз уж уважаемый читатель моей статьи решил потратить своё драгоценное время на чтение, постараюсь раскрыть тему как можно более тщательно.

   В организации эксплуатируется конфигурация "Управление Торговлей". На момент приобретения актуальным был релиз 11.1.10.ХХХ

   После проведения пуско-наладочных работ, руководству понадобилось немного модифицировать счёт на оплату покупателю. Доработка несложная: нужно добавить логотип организации и одну строчку под итогом суммы. Вот так:

   То есть нужно добавить контактную информацию о менеджере. Логотип решил оставить на десерт и начать именно с этого. Всё можно было бы сделать крайне просто: зайти в "Макеты печатных форм", найти нужную и тупо вбить необходимую информацию.

   Если бы не одно НО, при выписке счёта конкретным менеджером должна указываться информация именно об этом менеджере. То есть нужно проанализировать текущего пользователя и вывести соответствующие данные. Сначала попробовал подсоединить внешнюю печатную форму, но готовой не нашёл, а с ходу сделать свою не смог, решил пойти по другому пути. Если перефразировать похабный анекдот про кота Матроскина и корову Мурку, получается: моя конфигурация, что хочу, то и делаю.

   Сказано ==> сделано. Зашёл в конфигуратор, включил возможность изменения, нашёл необходимый макет, доработал модуль и вуа-ля: всё работает. Так продолжалось полтора года. Всё было бы хорошо, если бы не один подводный камень. При всей несложности доработки почему-то с неопределённого момента перестали ставится обновления.

   Однако руководство решило работать на последнем обновившемся релизе и ничего не менять, но наступил 2024 год и перестал работать сервис "1С-Контрагент". Настало время вешать обратно замочек в конфигураторе. Долго ли умеючи? Конечно нет. Новый клиент стал снова заводиться по ИНН, а вот со счётом получилась печалька. Решил не наступать на те же грабли, а сделать внешнюю обработку. Однако, не смотря на солидный возраст дружбы с 1С стал немножечко буксовать.

   Нашёл интересную статью //infostart.ru/public/431523/ уважаемого El_Loco и решил всё делать по инструкции на конфигурации Управление торговлей, редакция 11 (11.3.3.159).  Мне была как раз нужна внешняя печатная форма для документа "Заказ клиента".

   1) Создал новую внешнюю обработку:

   2) Проанализировал модуль менеджера документа ЗаказКлиента:

#Область Печать
// Заполняет список команд печати.
//
// Параметры:
//   КомандыПечати - ТаблицаЗначений - состав полей см. в функции УправлениеПечатью.СоздатьКоллекциюКомандПечати
//
Процедура ДобавитьКомандыПечати(КомандыПечати) Экспорт
Если ПраваПользователяПовтИсп.ЭтоПартнер() Тогда
// Заказ клиента
КомандаПечати = КомандыПечати.Добавить();
КомандаПечати.МенеджерПечати = "Обработка.ПечатьЗаказовНаТоварыУслуги";
КомандаПечати.Идентификатор = "ЗаказКлиента";
КомандаПечати.Представление = НСтр("ru = 'Заказ клиента'");
КомандаПечати.ПроверкаПроведенияПередПечатью = Истина;
// Счет на оплату
КомандаПечати = КомандыПечати.Добавить();
КомандаПечати.МенеджерПечати = "Обработка.ПечатьСчетовНаОплату";
КомандаПечати.Идентификатор = "СчетНаОплату";
КомандаПечати.Представление = НСтр("ru = 'Счет на оплату'");
КомандаПечати.ПроверкаПроведенияПередПечатью = Истина;

Соответственно, мне нужна обработка "ПечатьСчетовНаОплату"

   El_Loco рекомендует весь модуль менеджера обработки "ПечатьСчетовНаОплату" перенести в модуль нашей обработки. Там оказалось 9 процедур и 7 функций. Но нет ничего проще копипасты. Скопировал. Сохранил обработку, подгрузил в программу. Всё шло, как и предсказывал El_Loco:

   А вот тут что-то пошло не так. Рекомендовалось убрать лишний аргумент ПараметрыПечати из процедуры "Печать" и прописать его в начале процедуры:


ПараметрыПечати = Новый Структура();

   Так я и сделал, но вместо того, чтобы макет вывелся на печать, хоть и не тот, получил сообщение: "В обработчике печати не был сформирован табличный документ для: ЗаказКлиента". Оказалось, что не всё так просто. Процедура СведенияОВнешнейОбработке пишется не просто так:

Функция СведенияОВнешнейОбработке() экспорт
ПараметрыРегистрации = Новый Структура;
МассивНазначений = Новый Массив;
МассивНазначений.Добавить("Документ.ЗаказКлиента");
ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
ПараметрыРегистрации.Вставить("Назначение", МассивНазначений);
ПараметрыРегистрации.Вставить("Наименование", "Счёт (Треугольник)");
ПараметрыРегистрации.Вставить("БезопасныйРежим", ЛОЖЬ);
ПараметрыРегистрации.Вставить("Версия", "1.05");
ПараметрыРегистрации.Вставить("Информация", "Счёт (Треугольник)");
ТаблицаКоманд = ПолучитьТаблицуКоманд();
ДобавитьКоманду(ТаблицаКоманд, "Счёт (Треугольник)", "СчетНаОплату", "ВызовСерверногоМетода", Истина, "ПечатьMXL");
ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
Возврат ПараметрыРегистрации;
КонецФункции

   В ней есть оператор ДобавитьКоманду, и третий параметр в нём должен содержать именно ту команду, которая потом будет использоваться в процедуре Печать.

   Эта ошибка была устранена, попробовал напечатать получившуюся форму. Но получилось вот так:

   Стал разбираться, откуда взялось НаименованиеБанкаПолучателя, оказалось, что это значение процедуры ЗаполнитьТабличныйДокументИзвещение, которая в свою очередь вызывается из функции СформироватьПечатнуюФормуИзвещение.

   Анатолий Наумович Рыбаков придумал крылатую фразу "Нет человека — нет проблемы", в нашем случае это "Нет кода — нет проблемы". Тем более, что разработчики исходного кода заботливо поместили функцию и процедуру внутрь области "Извещение":

   Свернул указанную область и удалил одним махом. Соответственно, процедура "Печать" после обрезания должна выглядеть вот так:

Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
ПараметрыПечати = Новый Структура();

Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "СчетНаОплату") Тогда
СтруктураТипов = ОбщегоНазначенияУТ.СоответствиеМассивовПоТипамОбъектов(МассивОбъектов);
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"СчетНаОплату",
НСтр("ru='Счет на оплату'"),
СформироватьПечатнуюФормуСчетНаОплату(СтруктураТипов, ОбъектыПечати, ПараметрыПечати));
КонецЕсли;
ФормированиеПечатныхФорм.ЗаполнитьПараметрыОтправки(ПараметрыВывода.ПараметрыОтправки, МассивОбъектов, КоллекцияПечатныхФорм)
КонецПроцедуры

   Ну вот, теперь другое дело. Внешняя печатная форма наконец-то напечаталась. С единственной оговоркой, что вместо описанного El_Loco способа в самом начале процедуры ЗаполнитьРеквизитыШапкиСчетаНаОплату нужно прописать вот такой код:

Макет = ПолучитьМакет("ПФ_MXL_СчетНаОплату");

   Теперь нужно доработать макет, собственно ради чего всё и затевалось. Сначала в секцию ПодвалСчета я добавил строку ВашМенеджер:

   Для красоты объединил все ячейки, которые находятся под жирной сплошной линией в самом верху секции. Затем зашёл в свойства получившейся ячейки и оформил заполнение как параметр:

   Осталось только правильно вписать код в процедуру "ЗаполнитьРеквизитыПодвалаСчетаНаОплату". Сразу после строк в ней

// Вывести подписи
Область = Макет.ПолучитьОбласть("ПодвалСчета");
СтруктураДанныхПодвал = Новый Структура;

добавил код:

СтруктураДанныхПодвал.Вставить("ВашМенеджер","Ваш менеджер: "+ДанныеПечати.Менеджер+
" 8(23232)23232, 8(23232)32323, e-mail:paradise777@mail.ru");

   Разумеется, здесь, или в другой любой области макета каждый может написать то, что нужно конкретно ему, здесь мы обсуждаем принцип размещения данных. Вообще использование внешнего макета раскрывает огромный простор для полёта фантазии. Главное всё тестировать и сохранять предыдущие версии макета и обработки, иначе легко запутаться и всё придётся начинать заново.

   Наступило время разобраться с логотипом. Оказалось всё достаточно примитивно. В разных релизах может быть свой способ открыть справочник Организации, в Управлении торговлей 11.3.3.159 это делается так: жмём шестерёночку сверху "НСИ и администрирование", в левом вертикальном меню выбираем пункт "Сведения о предприятии", в центральной области окна отобразится соответствующая информация, выбираем первый пункт "Сведения об организации" и выходим на такое окно:

   Соответственно переходим на вкладочку "Настройка печати" и попадаем в окно для установки логотипа и факсимиле:

   В результате получился доработанный счёт с логотипом. Здесь нужно отметить, что красота полученного счёта прямо пропорциональна размерам логотипа, если он квадратный и небольшой, то всё будет хорошо, а если прямоугольный вытянутый, то нужно немножко поколдовать с макетом:

   То есть растянуть область картинки под логотип и сжать текст мелким шрифтом справа от него.

   Однако при таком построении отчёта не будет выводиться область  факсимиле, а это уже плохо, потому что в некоторых случаях она нужна, а в некоторых нет. Ещё раз проанализировал модуль менеджера документа ЗаказКлиента:

        // Счет на оплату
КомандаПечати = КомандыПечати.Добавить();
КомандаПечати.МенеджерПечати = "Обработка.ПечатьСчетовНаОплату";
КомандаПечати.Идентификатор = "СчетНаОплату";
КомандаПечати.Представление = НСтр("ru = 'Счет на оплату'");
КомандаПечати.ПроверкаПроведенияПередПечатью = Истина;

// Счет на оплату
КомандаПечати = КомандыПечати.Добавить();
КомандаПечати.МенеджерПечати = "Обработка.ПечатьСчетовНаОплату";
КомандаПечати.Идентификатор = "СчетНаОплату";
КомандаПечати.Представление = НСтр("ru = 'Счет на оплату с факсимиле'");
КомандаПечати.ПроверкаПроведенияПередПечатью = Истина;
КомандаПечати.ДополнительныеПараметры.Вставить("ОтображатьФаксимиле", Истина);

   Разница только в последней строчке, осталось только подумать, куда её вставить. В процедуре ЗаполнитьРеквизитыПодвалаСчетаНаОплату есть вызов процедуры общего модуля ФормированиеПечатныхФорм:

Процедура ВывестиФаксимилеВТабличныйДокумент(Макет, ОбластьМакета, Организация, ПараметрыПечати = Неопределено) Экспорт

ОтображатьФаксимиле = Ложь;
Если ПараметрыПечати <> Неопределено И ПараметрыПечати.Свойство("ОтображатьФаксимиле") Тогда
ОтображатьФаксимиле = ПараметрыПечати.ОтображатьФаксимиле;
КонецЕсли;

   То есть, если в структуру ПараметрыПечати добавить свойство ОтображатьФаксимиле в положении Истина, то всё должно получиться. Так я и сделал в процедуре Печать:

Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
ПараметрыПечати = Новый Структура();
ПараметрыПечати.Вставить("ОтображатьФаксимиле", Истина);

   Всё получилось. Теперь нужно разобраться с тем, что факсимиле нужно выводить не всегда, а для этого понадобятся две команды печати. Сначала хотел сделать две внешние обработки, одну с факсимиле, а другую без, но это было бы немножко не профессионально. Нужно, чтобы одна внешняя печатная форма создавала две команды печати, поэтому стал разбираться и эксперементировать. Сначала скопировал строку ДобавитьКоманду в функции СведенияОВнешнейОбработке:

ТаблицаКоманд = ПолучитьТаблицуКоманд();
ДобавитьКоманду(ТаблицаКоманд, "Счёт (Т)", "СчетНаОплату", "ВызовСерверногоМетода", Истина, "ПечатьMXL");
ДобавитьКоманду(ТаблицаКоманд, "Счёт (Т) с факсимиле", "СчетНаОплатуСФаксимиле", "ВызовСерверногоМетода", Истина, "ПечатьMXL");
ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);

   Потом сделал соответствующую доработку в процедуре Печать:

Процедура Печать(МассивОбъектов, КоллекцияПечатныхФорм, ОбъектыПечати, ПараметрыВывода) Экспорт
ПараметрыПечати = Новый Структура();
Если УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "СчетНаОплату") Тогда
СтруктураТипов = ОбщегоНазначенияУТ.СоответствиеМассивовПоТипамОбъектов(МассивОбъектов);
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"СчетНаОплату",
НСтр("ru='Счет на оплату'"),
СформироватьПечатнуюФормуСчетНаОплату(СтруктураТипов, ОбъектыПечати, ПараметрыПечати));
ИначеЕсли
УправлениеПечатью.НужноПечататьМакет(КоллекцияПечатныхФорм, "СчетНаОплатуСФаксимиле") Тогда
ПараметрыПечати.Вставить("ОтображатьФаксимиле", Истина);
СтруктураТипов = ОбщегоНазначенияУТ.СоответствиеМассивовПоТипамОбъектов(МассивОбъектов);
УправлениеПечатью.ВывестиТабличныйДокументВКоллекцию(
КоллекцияПечатныхФорм,
"СчетНаОплатуСФаксимиле",
НСтр("ru='Счет на оплату'"),
СформироватьПечатнуюФормуСчетНаОплату(СтруктураТипов, ОбъектыПечати, ПараметрыПечати));
КонецЕсли;
ФормированиеПечатныхФорм.ЗаполнитьПараметрыОтправки(ПараметрыВывода.ПараметрыОтправки, МассивОбъектов, КоллекцияПечатныхФорм)
КонецПроцедуры

   Теперь всё чётко. Есть два варианта, с факсимиле и без в одной внешней форме. Можно было бы ещё проанализировать, не осталось ли неиспользуемых процедур или функций, но это уже на работу никак не влияет, поэтому решил оставить так.

   Спасибо за внимание.

9 Comments

  1. Amur_MVS

    Спасибо! Очень полезно

    Reply
  2. user633533_encantado

    Не по феншую, не используются соответствующие БСП в модулях описания внешней обработки.

    Reply
  3. Hamsik

    Что в вашей практике необычного ? Обычное создание ВПФ ?

    Reply
  4. dock

    Прекрасная статья! Читается замечательно 🙂

    ИМХО, основная полезность не в коде (и результирующей обработке), а именно в описании процесса: как думал, о чем думал, как реагировал на внезапно возникший перед носом черенок от граблей…

    Reply
  5. zemskov

    (3) На необычность не претендовал. Хотел как раз осветить сам процесс.

    Reply
  6. Scop

    Спасибо, тема отлично раскрыта, плюсик в карму.

    Reply
  7. AlX0id

    Еще бы добавить про использование http://infostart.ru/public/162019/ для отладки — было бы вообще в тему )

    Reply
  8. sss999

    Спасибо хорошим людям!Я бы сам не догадался про команду в печати и в описании

    Reply
  9. -=AleXX=-

    Очень помогло! Спасибо!

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *