Как программно выбрать принтер для печати PDF-файла в 1С 7.7?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

Разработчики, работающие с платформой 1С 7.7, часто сталкиваются с необходимостью печати внешних файлов, таких как PDF. Стандартный подход с использованием объекта shell.application и метода ShellExecute через глагол print кажется самым простым, но он имеет существенный недостаток: файл отправляется на принтер, который установлен в операционной системе по умолчанию. Если же нам требуется отправить документ на конкретный аппарат (например, на складской принтер этикеток или бухгалтерский сетевой принтер), стандартных параметров ShellExecute оказывается недостаточно.

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

Проблема метода ShellExecute

Рассмотрим типовой код, который часто используют в 1С 7.7:


ПечПДФ = СоздатьОбъект("shell.application");
ПечПДФ.ShellExecute(ФайлДляПечати, "", "", "print", 1);

Функция ShellExecute вызывает системную команду, связанную с расширением файла. Для PDF это обычно Adobe Reader или Foxit Reader. Глагол print в системном реестре Windows жестко прописан для использования принтера по умолчанию. Параметра для передачи имени принтера в этом методе просто не существует. Выясним, какие у нас есть альтернативы.

Способ 1. Временная смена принтера по умолчанию через WScript.Network

Проанализируем самый доступный способ, не требующий установки дополнительных программ. Мы можем программно изменить принтер по умолчанию в Windows прямо перед печатью, отправить файл на выполнение и затем вернуть настройки обратно. Для этого идеально подходит объект WScript.Network.

Разберем реализацию этого метода по шагам:

  1. Создаем объект для работы с сетью и принтерами.
  2. Запоминаем текущий принтер (если это необходимо).
  3. Устанавливаем нужный нам принтер «по умолчанию».
  4. Выполняем печать через ShellExecute.
  5. Восстанавливаем исходные настройки.

// Создаем объект для управления системными настройками
Сеть = СоздатьОбъект("WScript.Network");

// Задаем имя нужного принтера (точно так, как он называется в Windows)
НужныйПринтер = "\\Server\HP_LaserJet_400";

Попытка
    // Устанавливаем принтер по умолчанию
    Сеть.SetDefaultPrinter(НужныйПринтер);
    
    // Печатаем файл
    ПечПДФ = СоздатьОбъект("shell.application");
    ПечПДФ.ShellExecute(ФайлДляПечати, "", "", "print", 1);
    
    // Важно: иногда приложению нужно время, чтобы подхватить принтер
    // Здесь можно добавить небольшую паузу
Исключение
    Сообщить("Ошибка при смене принтера: " + ОписаниеОшибки());
КонецПопытки;

Способ 2. Использование командной строки Adobe Reader или Foxit Reader

Если мы знаем, какая программа установлена для просмотра PDF, мы можем вызвать её напрямую с параметрами командной строки. Это более надежный метод, так как он не затрагивает глобальные настройки системы. Большинство популярных программ поддерживают ключи печати на конкретное устройство.

Рассмотрим пример для Adobe Reader. У него есть ключ /t, который принимает путь к файлу и имя принтера.


// Синтаксис: AcroRd32.exe /t "Путь_к_файлу" "Имя_принтера" "Имя_драйвера" "Порт"
// Драйвер и порт в современных ОС часто можно игнорировать
ПутьКРидеру = "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe";
ИмяПринтера = "HP LaserJet 400";
Команда = """" + ПутьКРидеру + """ /t """ + ФайлДляПечати + """ """ + ИмяПринтера + """";

// Выполняем команду
КомандаСистемы(Команда);

Для Foxit Reader синтаксис еще проще:

FoxitReader.exe /p "Файл.pdf" "Имя_принтера"

Способ 3. Использование легкой утилиты SumatraPDF (Рекомендуется)

Посмотрим на ситуацию со стороны стабильности. Установка тяжелых ридеров (Adobe) на сервер или рабочие станции может быть избыточной. Профессионалы часто используют SumatraPDF — это крохотный бесплатный просмотрщик, который можно просто положить в папку с базой 1С (файл SumatraPDF.exe).

Выясним преимущества этого метода:

Пример кода для 1С 7.7:


ПутьКПрограмме = КаталогИБ() + "ExtForms\SumatraPDF.exe";
ФайлPDF = "C:\Docs\Report.pdf";
Принтер = "Canon_LBP6000";

// Формируем строку запуска
// Ключ -print-to позволяет указать целевой принтер
Команда = """" + ПутьКПрограмме + """ -print-to """ + Принтер + """ """ + ФайлPDF + """";

// Запускаем в скрытом режиме
WshShell = СоздатьОбъект("WScript.Shell");
WshShell.Run(Команда, 0, 1); // 0 - скрыть окно, 1 - ждать завершения

Способ 4. Работа с принтерами через WMI (Windows Management Instrumentation)

В ходе обсуждения на форуме был предложен вариант использования MSScriptControl для работы с коллекцией принтеров через Win32_Printer. Это полезно, когда нам нужно не просто отправить на печать, а сначала убедиться, что принтер существует или имеет определенные атрибуты.

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


Скрипт = СоздатьОбъект("MSScriptControl.ScriptControl");
Скрипт.Language = "vbscript";
Скрипт.AddCode("
|Function IsDefault(Attributes)
|   IsDefault = (Attributes AND 4)
|End Function");

Локатор = СоздатьОбъект("wbemscripting.swbemlocator");
Сервис = Локатор.ConnectServer();
Принтеры = Сервис.ExecQuery("Select * from Win32_Printer");

// Перебор коллекции принтеров
Перечисление = Принтеры._NewEnum;
Пока Перечисление.MoveNext(Принтер) = -1 Цикл
    Если Скрипт.Run("IsDefault", Принтер.Attributes) <> 0 Тогда
        Сообщить("Текущий принтер по умолчанию: " + Принтер.Name);
    КонецЕсли;
КонецЦикла;

Условие Attributes AND 4 (или Attributes % 8 / 4 = 1 в JavaScript-версии) проверяет четвертый бит атрибутов объекта Win32_Printer, который в спецификации WMI как раз и отвечает за признак PRINTER_ATTRIBUTE_DEFAULT.

Способ 5. Специализированная утилита PDFtoPrinter

Существует еще более узконаправленное решение — утилита PDFtoPrinter. В отличие от ридеров, она вообще не имеет графического интерфейса и создана исключительно для одной задачи: передать PDF в очередь печати конкретного устройства.

Разберем пример использования:


Команда = "PDFtoPrinter.exe ""документ.pdf"" ""Имя Принтера""";
КомандаСистемы(Команда);

Это считается одним из самых «чистых» способов автоматизации, так как он исключает появление лишних окон на экране пользователя и работает максимально прозрачно.

Важные нюансы при работе с сетевыми именами

Проанализируем типичную ошибку при указании имени принтера. Если принтер сетевой, его имя в системе может выглядеть как \\PRN-SERVER\Buh_Laser. При передаче такого имени в командную строку через 1С необходимо соблюдать следующие правила:

  1. Экранирование кавычек: Пути и имена принтеров с пробелами обязательно должны быть заключены в двойные кавычки. В языке 1С это достигается удвоением кавычек внутри строки.
  2. Точность имени: Имя принтера должно полностью совпадать с тем, что отображается в разделе «Принтеры и сканеры» панели управления.
  3. Права доступа: При работе в терминальном режиме (RDP) принтеры могут иметь динамические имена (например, "HP LaserJet (redirected 2)"). В этом случае лучше использовать методы поиска принтера по части имени через WMI перед печатью.

Подводя итог, можно сказать: если вы хотите решить задачу без установки внешних компонент (ВК), оптимальным выбором будет либо временная смена принтера через WScript.Network, либо использование портативной утилиты вроде SumatraPDF, которую можно распространять вместе с конфигурацией.

← На главную