Форум 1С
Программистам, бухгалтерам, администраторам, пользователям
Задай вопрос - получи решение проблемы
28 мар 2024, 11:18

Пакетная печать на дуплексном принтере

Автор mixqn, 29 июл 2013, 10:40

0 Пользователей и 1 гость просматривают эту тему.

mixqn

Краткая предыстория (для лучшего понимания сути дела): для оптимизации печати пакетов документов используется дуплексный многолотковый принтер. Каждый лоток принтера настроен на определенного сотрудника. В теории должно работать так: нажимается условно одна кнопочка, после чего в нужный лоток (с подписью «Иванов») печатается комплект документов.
На практике принтер иногда дает сбои и какой-то 1 лист из комплекта документов идет в верхний лоток, а не туда, куда положено.
Разобраться в причинах ошибки не удалось и стоит задача средствами 1С решить проблему.

Попытки, предпринимавшиеся ранее (еще до меня) результата не дали.
Мне предложили сделать тупым механическим способом: создать единый макет (единый по той причине, что некоторое ПФ имеют ориентацию ландшафт, другие – портрет) для всего пакета документов, таким образом создавать 1 задание на принтер и избавиться от ошибки. Решение мне крайне не нравилось и я стал искать другие варианты.
Нашел (вернее подсказали) следующий вариант решения: через виртуальный принтер (PDFCreator) формировать единый PDF и уже его печатать.
Скачал PDFCreator, попробовал «ручками» – работает. Надо запрограммировать через COM.

Теперь собственно текущий вопрос: можно ли каким-то образом кроме как через свойство табличного документа ИмяПринтера задать принтер по умолчанию? Свойство таб. дока не хотелось бы использовать по той причине, что уже существует обработка пакетной печати документов, в ней используются типовые процедуры печати (типа Реализация.Печать("ТОРГ12_БезУслуг", 1, ПечататьНаПринтер)), поэтому нет возможности обратиться к свойствам таб. документа. Если возможно, хотелось бы «малой кровью», т.е. внеся минимальные изменения в существующий код, вывести весь пакет документов на виртуальный принтер, а затем сохранить результат в PDF и уже его напечатать. Т.е. в идеале примерно так:
1.       вкл. принтер по умолчанию PDFCreator
2.       формирование пакета
3.       выкл. принтер по умолчанию PDFCreator
4.       печать (на обычном принтере по умолчанию)

MuI_I_Ika

Стандартными средствами только ИмяПринтера у табличного документа. Иначе только скриптами менять системные установки винды, а потом их обратно возвращать.

mixqn

Цитата: MuI_I_Ika от 29 июл 2013, 12:13Иначе только скриптами менять системные установки винды, а потом их обратно возвращать.
такой вариант вполне подойдет. есть пример кода/ссылка на документацию/описание методов и свойств и т.д.?
яндекс найти не помогает...

MuI_I_Ika

Скрипт = Новый ComОбъект("WScript.Network");
Скрипт .SetDefaultPrinter(<Name>);

mixqn

Цитата: MuI_I_Ika от 29 июл 2013, 13:14
Скрипт = Новый ComОбъект("WScript.Network");
Скрипт .SetDefaultPrinter(<Name>);


Спасибо, это работает.

А как получить текущий принтер (потом же надо вернуть как было)?
GetDefaultPrinter не работает:
Попытка
Скрипт = Новый ComОбъект("WScript.Network");

ТекущийПринтер = Скрипт.GetDefaultPrinter();
Сообщить(ТекущийПринтер);
Скрипт.SetDefaultPrinter(ИмяПринтера);

Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;

{Форма.Форма.Форма(6)}: Метод объекта не обнаружен (GetDefaultPrinter)

вот так тоже не работает

Перем ТекущийПринтер;

Попытка
Скрипт = Новый ComОбъект("WScript.Network");

Скрипт.GetDefaultPrinter(ТекущийПринтер);
Сообщить(ТекущийПринтер);
Скрипт.SetDefaultPrinter(ИмяПринтера);

Исключение
Сообщить(ОписаниеОшибки());
КонецПопытки;

mixqn

в интернете нашел вот такой вариант:

Функция ПолучитьПринтерПоУмолчанию() Экспорт
   
    Скрипт = Новый ComObject("MSScriptControl.ScriptControl");
    Скрипт.Language = "vbscript";                 
    Скрипт.AddCode("
         |Function GetDefaultPrinter()
         |GetDefaultPrinter=vbNullString
         |Set objWMIService=GetObject(""winmgmts:"" _
         |& ""{impersonationLevel=impersonate}!\\.\root\cimv2"")
         |Set colInstalledPrinters=objWMIService.ExecQuery _
         |(""Select * from Win32_Printer"")
         |For Each objPrinter in colInstalledPrinters
         |If objPrinter.Attributes and 4 Then
         |GetDefaultPrinter=objPrinter.Name
         |Exit For
         |End If
         |Next
         |End Function");
         
    Возврат СокрЛП(Скрипт.run("GetDefaultPrinter"));
   
КонецФункции


можно как-то проще сделать?

MuI_I_Ika

Скрипт = Новый ComОбъект("WScript.Shell");
    Printer = Скрипт .RegRead("HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device");
    Сообщить("Принтер по умолчанию:" + Printer);

mixqn

Цитата: MuI_I_Ika от 29 июл 2013, 14:36
Скрипт = Новый ComОбъект("WScript.Shell");
    Printer = Скрипт .RegRead("HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device");
    Сообщить("Принтер по умолчанию:" + Printer);


спасибо, работает

mixqn

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

Теперь задача в том, чтобы заставить PDFCreator сделать следующее:
1.   Заблокировать показ стандартного окна, которое выплывает при отправке на печать документа (пользователь не должен знать о PDFCreator)
2.   После того, как все документы последовательно отправлены на печать собрать их в один (кнопка «Combine all» или метод cCombineAll)
3.   Сохранить полученный документ в формате PDF (команда cPrinterStop и далее не понятно пока что, возможно, если настроен авто-сейв то больше ничего не требуется).
У меня все это дело не работает.

Привожу куски кода:
// текст процедуры, не имеющий отношения к PDFCreator
ТекущийПринтер = ПолучитьПринтерПоУмолчаниюРМВ();
УстановитьПринтерПоУмолчаниюРМВ("PDFCreator");
ПринтерПДФ = Новый COMОбъект("PDFCreator.clsPDFCreator");

НаборОпций = ПринтерПДФ.cReadOptions();

НаборОпций.AutosaveDirectory = КаталогВременныхФайлов();
НаборОпций.AutosaveFilename = Реализация.Ссылка.УникальныйИдентификатор();
НаборОпций.AutosaveFormat = 0; // PDF
НаборОпций.UseAutosave = 1;
НаборОпций.UseAutosaveDirectory = 1;
НаборОпций.AutosaveStartStandardProgram = 0;
НаборОпций.PDFUseSecurity = 1;
НаборОпций.PDFDisallowCopy = 1;
НаборОпций.PDFDisallowModifyContents = 1;

ПринтерПДФ.cOptions = НаборОпций;
// алгоритм печати пакета документов (без изменений по сравнению с тем, что было до реализации через PDFCreator)
УстановитьПринтерПоУмолчаниюРМВ(ТекущийПринтер);
ПринтерПДФ.cCombineAll();
ПринтерПДФ.cPrinterStop = Истина;

Текст процедур ПолучитьПринтерПоУмолчаниюРМВ и УстановитьПринтерПоУмолчаниюРМВ не привожу - его можно представить себе по сообщениям выше.

мой код игнорируется полностью кроме изменений принтера по умолчанию.
такое ощущение, что создание COM-объекта приводит к появлению еще одного процесса, вместо подключения к существующему.

если мое предположение верно, то нужно 1 из 2-ух: либо не создавать новый COM-объект, а как-то подключиться к существующему, либо дополнительно при печати передавать какой-то еще параметр (непонятно каким образом).

в общем, буду признателен за подсказку направления, в котором продолжить поиски решения

Dethmontt

ПринтерПДФ =  ПолучитьCOMОбъект(,"PDFCreator.clsPDFCreator"); //Выполняет поиск запущенного экземпляра COM объекта
Если долго всматриваться в учебник...то в голову может прийти мысль его открыть!

Теги:

Похожие темы (5)

Рейтинг@Mail.ru

Поиск