Как программно сохранить документы в PDF из 1С: возможности и ограничения "Microsoft Print to PDF" и альтернативы

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Мы часто сталкиваемся с необходимостью программной конвертации различных документов в формат PDF из системы 1С. Одним из наиболее привлекательных на первый взгляд решений является использование встроенного в Windows виртуального принтера "Microsoft Print to PDF", который не требует дополнительной установки. Однако, как мы убедимся, его автоматизация имеет существенные ограничения. Разберем ситуацию подробнее и рассмотрим доступные альтернативы, чтобы найти наиболее эффективный способ решения задачи.

Программное управление "Microsoft Print to PDF" через COM-соединение

Автор изначально задавался вопросом: "Возможно ли установить COM-соединение с виртуальным принтером 'Microsoft Print to PDF'?" Идея была логичной, поскольку существуют примеры работы с другими виртуальными принтерами, например, PDFCreator, через COM-объекты. Тем не менее, "Microsoft Print to PDF" существенно отличается от сторонних решений, и это различие играет ключевую роль в возможности его автоматизации.

Ключевая проблема заключается в том, что "Microsoft Print to PDF" по своей сути предназначен для взаимодействия с пользователем. При каждой попытке печати на этот принтер система Windows автоматически вызывает диалоговое окно "Сохранить результат печати как", требуя от пользователя вручную указать имя файла и путь сохранения. Это делает его крайне неудобным, а в большинстве случаев и вовсе непригодным, для автоматизированной обработки на сервере без какого-либо вмешательства человека. Стандартный функционал 1С или прямое COM-соединение не предоставляют механизмов для подавления этого диалога или программного указания пути сохранения для "Microsoft Print to PDF" без сложных обходных путей.

Хотя программно направить документ на этот принтер возможно (например, через классы PrintDocument в .NET, которые могут быть доступны из 1С через COM-объекты .NET), обойти это диалоговое окно без использования сторонних утилит или сложных методов имитации пользовательского интерфейса крайне сложно. Имитация пользовательского интерфейса (например, отправка клавиатурных команд или кликов мышью) является ненадежным и нерекомендуемым подходом для серверных решений из-за зависимости от текущего состояния системы и потенциальных проблем безопасности.

Для исследования доступных COM-объектов в системе вы можете воспользоваться утилитой OleView.Exe. Эта программа, часто входящая в состав Visual Studio или доступная для загрузки отдельно, позволяет просматривать зарегистрированные OLE/COM объекты и их интерфейсы. Вы можете попробовать найти в ней объект, связанный с "Microsoft Print to PDF". Однако, как показывает практика, для этого принтера вы вряд ли найдете интерфейс, позволяющий полноценно автоматизировать процесс печати с сохранением без участия пользователя и появления диалоговых окон.

Встроенные возможности 1С для сохранения табличных документов в PDF

Если ваша задача заключается в сохранении в PDF табличных документов, созданных средствами 1С, то существует простое и эффективное встроенное решение, не требующее использования виртуальных принтеров или стороннего программного обеспечения. Объекты типа ТабличныйДокумент имеют метод Записать(), который позволяет сохранять их в различных форматах, включая PDF.

Рассмотрим подробнее пример использования этого метода. Предположим, у нас уже есть сформированный табличный документ (в разработке которого поможет универсальная форма отладки для внешней обработки печатных форм), который мы хотим сохранить:


// Предполагаем, что у нас есть объект ТабличныйДокумент, например, ТабДок.
// ТабДок = Новый ТабличныйДокумент;
// ... здесь происходит заполнение табличного документа данными, настройка областей и т.д. ...

// Определяем полный путь, по которому будет сохранен PDF-файл.
// Важно убедиться, что у пользователя, под которым запускается 1С-сервер,
// есть права на запись в указанную директорию.
ПутьКФайлуPDF = "C:\МоиДокументы\ОтчетОПродажах.pdf";

// Используем метод Записать() объекта ТабличныйДокумент.
// Первым параметром передаем путь к файлу, вторым – тип файла, в данном случае PDF.
ТабДок.Записать(ПутьКФайлуPDF, ТипФайлаТабличногоДокумента.PDF);

// Выводим сообщение об успешном сохранении файла.
Сообщить("Табличный документ успешно сохранен в: " + ПутьКФайлуPDF);

Этот метод является идеальным решением для специфической задачи сохранения 1С-овских табличных документов. Он полностью автономен, не требует никаких внешних компонентов или настроек операционной системы, кроме базовых прав доступа к файловой системе. Однако, необходимо подчеркнуть, что он не подходит для конвертации произвольных HTML-документов, что было основной целью автора темы. Метод Записать() предназначен исключительно для объектов ТабличныйДокумент, которые генерируются внутри 1С.

Использование сторонних виртуальных принтеров с поддержкой COM-автоматизации

В отличие от "Microsoft Print to PDF", существуют сторонние виртуальные принтеры PDF, которые специально разработаны для автоматизации и предоставляют полноценные COM-интерфейсы. Эти решения созданы с учетом потребностей программного управления, позволяя разработчикам интегрировать их в свои приложения для автоматической печати в PDF. Одним из таких популярных решений является PDFCreator.

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

Для работы с PDFCreator из 1С вам потребуется создать COM-объект. Как было отмечено в обсуждении, для получения информации о состоянии и настройках самого PDFCreator используется один объект (например, PDFCreator.clsPDFCreator), а для постановки заданий в очередь на конвертацию и управления ими — другой (например, PDFCreator.JobQueue).

Рассмотрим примеры кода для взаимодействия с PDFCreator (хотя в оригинальном сообщении приведена синтаксическая форма JavaScript, мы адаптируем ее для 1С):


// *** Пример работы с объектом для получения информации о PDFCreator ***

Попытка
    // Создаем COM-объект PDFCreator.clsPDFCreator.
    // Если PDFCreator не установлен или зарегистрирован некорректно, здесь возникнет ошибка.
    PDFCreatorInfo = Новый COMОбъект("PDFCreator.clsPDFCreator");
    Сообщить("PDFCreator успешно инициализирован для получения информации.");
    Сообщить("Версия PDFCreator: " + PDFCreatorInfo.Version);
    Сообщить("Язык интерфейса: " + PDFCreatorInfo.Language);
    Сообщить("Настройка по умолчанию: " + PDFCreatorInfo.cOption_Get("PdfSettings")); // Пример получения настройки
    
    // После использования, рекомендуется освободить COM-объект.
    PDFCreatorInfo = Неопределено;
Исключение
    Сообщить("Ошибка при создании COM-объекта PDFCreator.clsPDFCreator: " + ОписаниеОшибки());
    Сообщить("Убедитесь, что PDFCreator установлен и правильно зарегистрирован в системе.");
КонецПопытки;

Сообщить("-----------------------------------");

// *** Пример работы с очередью заданий для конвертации ***

Попытка
    // Создаем COM-объект для управления очередью заданий.
    PDFCreatorQueue = Новый COMОбъект("PDFCreator.JobQueue");
    
    // Инициализируем очередь заданий. Это обязательный шаг перед добавлением заданий.
    PDFCreatorQueue.Initialize(); 
    Сообщить("Очередь заданий PDFCreator успешно инициализирована.");

    // Для демонстрации, как это могло бы выглядеть в реальном сценарии:
    // 1. Отправка документа на виртуальный принтер PDFCreator (например, через стандартный механизм печати Windows).
    // 2. Ожидание появления задания в очереди PDFCreator.
    // PDFCreatorQueue.WaitForJob(10); // Ждать до 10 секунд новое задание в очереди.
    
    // 3. Получение следующего задания из очереди.
    // Если задание найдено:
    // Если PDFCreatorQueue.Count > 0 Тогда
    //     PDFCreatorJob = PDFCreatorQueue.NextJob;
    //     Сообщить("Найдено задание в очереди: " + PDFCreatorJob.Filename);
    //
    //     // Установка свойств задания, например, выходного файла, профиля конвертации.
    //     PDFCreatorJob.SetPropertyValue("Filename", "МойКонвертированныйДокумент");
    //     PDFCreatorJob.SetPropertyValue("OutputFilePath", "C:\Temp\");
    //     // PDFCreatorJob.SetProfileByGuid("{DefaultGuid}"); // Установить стандартный профиль
    //
    //     // Выполнение конвертации.
    //     PDFCreatorJob.ConvertTo("C:\Temp\МойКонвертированныйДокумент.pdf");
    //
    //     // Освобождение задания.
    //     PDFCreatorJob.SetCom(); // Для корректного завершения и освобождения ресурсов
    // КонецЕсли;
    
    // После завершения всех операций с очередью, необходимо освободить COM-объект очереди.
    PDFCreatorQueue.ReleaseCom(); 
    Сообщить("COM-объект очереди заданий PDFCreator освобожден.");

Исключение
    Сообщить("Ошибка при работе с очередью заданий PDFCreator.JobQueue: " + ОписаниеОшибки());
    Сообщить("Проверьте установку PDFCreator и его состояние.");
КонецПопытки;

Важно понимать: использование таких сторонних принтеров требует их установки на сервере 1С. Это часто является нежелательным требованием для администраторов, как было отмечено в сообщении 8 ("стороннее программное обеспечение, на сервере не желательное"). Причинами могут быть лицензионные ограничения, дополнительные требования к обслуживанию или соображения безопасности. Однако, если установка возможна, это один из наиболее надежных и функциональных способов программной печати в PDF, особенно если вам необходим полный контроль над процессом конвертации и множество дополнительных настроек.

Использование внешних утилит для конвертации HTML в PDF

Если основной задачей является конвертация входящих HTML-документов в PDF, и использование COM-соединения со стандартным принтером Windows оказалось невозможным, а установка стороннего виртуального принтера нежелательна, то оптимальным решением часто становятся специализированные консольные утилиты. Они позволяют выполнять конвертацию без графического интерфейса и диалоговых окон, что делает их идеальными для серверной среды.

Одной из наиболее популярных, эффективных и широко используемых утилит для этой цели является wkhtmltopdf.

wkhtmltopdf — это утилита с открытым исходным кодом, которая использует движок рендеринга WebKit (на котором основаны старые версии браузеров Safari и Google Chrome) для преобразования HTML-страниц и SVG-изображений в PDF или различные форматы изображений. Она работает из командной строки, что делает ее идеальной для серверной автоматизации, поскольку не требует запуска графического интерфейса, не вызывает диалоговых окон и потребляет относительно мало системных ресурсов при правильной настройке.

Для работы с wkhtmltopdf из 1С вам потребуется выполнить следующие шаги:

  1. Скачать и установить wkhtmltopdf: Вам нужно загрузить соответствующую версию wkhtmltopdf для вашей серверной операционной системы (например, Windows Server x64) и установить ее. Либо просто скопировать исполняемый файл (wkhtmltopdf.exe) и все необходимые библиотеки в доступное для 1С-сервера место.
  2. Вызвать утилиту из 1С: Используйте методы ЗапуститьПриложение() или КомандаСистемы() (для асинхронного или синхронного выполнения соответственно) для вызова wkhtmltopdf.exe с необходимыми параметрами.

Рассмотрим пример вызова wkhtmltopdf из 1С. Предполагается, что wkhtmltopdf.exe либо находится в системном PATH, либо указан полный путь к исполняемому файлу:


// Определяем пути к входному HTML-файлу и выходному PDF-файлу.
// Убедитесь, что эти пути доступны для чтения и записи для процесса 1С-сервера.
ПутьКHTML = "C:\Temp\МойВходящийДокумент.html";
ПутьКPDF  = "C:\Temp\РезультатКонвертации.pdf";

// Формируем параметры командной строки для wkhtmltopdf.
// --enable-local-file-access: Важный параметр, который позволяет wkhtmltopdf
// получать доступ к локальным ресурсам (CSS, JS, изображениям), на которые ссылается HTML-файл.
// Без него HTML может быть отображен некорректно или частично.
// Параметры wkhtmltopdf всегда указываются перед входным и выходным файлами.
// Кавычки вокруг путей обязательны, если пути содержат пробелы.
ПараметрыКоманды = " --enable-local-file-access """ + ПутьКHTML + """ """ + ПутьКPDF + """";

// Исполняемый файл wkhtmltopdf.exe. Если он не в PATH, укажите полный путь.
ИсполняемыйФайл = "wkhtmltopdf.exe"; 
// Пример с полным путем: ИсполняемыйФайл = "C:\Program Files\wkhtmltopdf\bin\wkhtmltopdf.exe";

// Формируем полную команду для выполнения.
Команда = ИсполняемыйФайл + ПараметрыКоманды;

Попытка
    // Выполняем команду системы.
    // КомандаСистемы() является синхронной, т.е. 1С будет ожидать завершения wkhtmltopdf.
    // Для долгоиграющих процессов или если не нужно ждать, можно использовать ЗапуститьПриложение().
    // ЗапуститьПриложение(Команда);
    
    // Получаем код возврата от wkhtmltopdf. Обычно 0 означает успех.
    Результат = КомандаСистемы(Команда);

    Если Результат = 0 Тогда // Обычно код возврата 0 означает успешное выполнение
        Сообщить("HTML документ успешно сконвертирован в PDF: " + ПутьКPDF);
        // Дополнительная проверка на существование файла ПутьКPDF может быть полезна.
    Иначе
        Сообщить("Ошибка при конвертации HTML в PDF. Код возврата wkhtmltopdf: " + Результат);
        Сообщить("Проверьте пути, права доступа и параметры команды. Попробуйте запустить команду вручную в командной строке для отладки.");
    КонецЕсли;
Исключение
    Сообщить("Исключение при вызове wkhtmltopdf: " + ОписаниеОшибки());
    Сообщить("Убедитесь, что файл wkhtmltopdf.exe существует и доступен.");
КонецПопытки;

В одном из сообщений (Сообщение 10) было упомянуто, что wkhtmltopdf "сохраняет пустой пдф". Эта проблема может возникать по нескольким причинам, и мы рассмотрим наиболее частые из них:

  1. Неправильные пути или права доступа: Убедитесь, что пути к входному HTML-файлу и выходному PDF-файлу указаны абсолютно корректно и что у пользователя, под которым запускается процесс 1С-сервера, есть необходимые права на чтение входного файла и запись выходного файла в указанные директории. Ошибки в путях или отсутствие прав — очень частая причина.
  2. Проблемы с HTML-документом: Если HTML-документ содержит синтаксические ошибки, невалидный CSS, ошибки JavaScript, или ссылки на ресурсы, которые недоступны для wkhtmltopdf (например, внешние скрипты, заблокированные фаерволом), это может привести к некорректному рендерингу или пустому выводу. Попробуйте сначала конвертировать простейший HTML-файл (например, <h1>Тест</h1>), чтобы исключить проблемы с самой утилитой.
  3. Отсутствие зависимостей: wkhtmltopdf, как и многие другие консольные утилиты, может требовать определенных системных библиотек или шрифтов, особенно на серверных операционных системах без графического интерфейса (Server Core). Убедитесь, что все необходимые зависимости установлены. В Windows это могут быть Visual C++ Redistributable Package.
  4. Некорректные параметры командной строки: Некоторые параметры могут быть критичны. Например, если HTML-файл ссылается на локальные ресурсы (картинки, CSS, JS), параметр --enable-local-file-access обязателен. Если HTML содержит мета-теги для масштабирования, иногда полезно использовать параметры --enable-smart-shrinking или --disable-smart-shrinking, а также --zoom.
  5. Проблемы с безопасностью или средой: На сервере могут быть активированы строгие политики безопасности (AppLocker, DEP), которые препятствуют запуску внешних процессов или доступу к файловой системе для wkhtmltopdf. Также проверьте переменные среды, которые могут влиять на работу утилиты.

Отладку таких проблем лучше всего начинать с запуска wkhtmltopdf из обычной командной строки на сервере, используя точно те же параметры и пути, что и в коде 1С. Это позволит увидеть любые сообщения об ошибках, которые утилита выводит в консоль, и диагностировать проблему вне контекста 1С.

Заключение и выбор оптимального решения

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

  1. Если вы работаете с табличными документами 1С, то встроенный метод ТабличныйДокумент.Записать() является наиболее простым, надежным и не требующим внешних зависимостей решением. Мы настоятельно рекомендуем использовать его в первую очередь для этой специфической задачи.
  2. Для конвертации произвольных HTML-документов, попытка использовать "Microsoft Print to PDF" через COM-соединение нецелесообразна из-за его интерактивного характера (постоянное появление диалогового окна сохранения). Этот путь практически непригоден для серверной автоматизации без участия пользователя.
  3. Если вы готовы установить сторонний виртуальный PDF-принтер с полноценным COM-интерфейсом (например, PDFCreator), это может быть очень мощным и гибким решением для различных задач печати, включая конвертацию HTML (через механизм печати браузера) или любых других документов, которые можно распечатать. Однако это требует дополнительной установки и обслуживания стороннего ПО на сервере, что может быть ограничением.
  4. Наиболее распространенным и часто рекомендуемым подходом для автоматической конвертации HTML в PDF на сервере является использование внешних консольных утилит, таких как wkhtmltopdf. Несмотря на возможные сложности с настройкой и отладкой (как было замечено с пустыми PDF), при правильной конфигурации они обеспечивают высокую надежность и производительность без участия пользователя, являясь при этом более легковесным решением по сравнению с полнофункциональными виртуальными принтерами.

Мы рекомендуем начать с анализа требований к функционалу (что именно нужно конвертировать), готовности к установке стороннего программного обеспечения и специфике серверной среды. Затем, исходя из этой информации, вы сможете выбрать наиболее подходящий вариант из представленных здесь решений, учитывая их особенности и ограничения, для эффективной и стабильной работы в вашей системе 1С.

← На главную