Как изменить PDF-документы из 1С, включая заполнение полей и редактирование произвольного текста?

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

При работе с 1С часто возникает задача по взаимодействию с внешними файлами, и PDF-документы не исключение. В частности, мы столкнулись с необходимостью изменять существующие PDF-файлы, которые содержат как заполняемые поля (формы), так и статический текст, который требуется программно дополнить или заменить информацией из 1С. Такая задача может быть осложнена требованиями к работе на сервере и вопросами лицензирования используемого программного обеспечения. Рассмотрим подробнее возможные подходы и их особенности.

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

1. Использование Adobe Acrobat Pro через OLE-автоматизацию

Первый, и наиболее очевидный, путь — это использование COM-объектов Adobe Acrobat Pro, если он установлен на клиентской машине или сервере. Этот подход позволяет обращаться к функционалу Adobe Acrobat через 1С и манипулировать элементами PDF-документа, в частности, его заполняемыми полями.

Принцип работы:

  1. Мы создаем COM-объекты, представляющие приложение Adobe Acrobat (AcroExch.App) и сам PDF-документ (AcroExch.PDDoc).
  2. Открываем необходимый PDF-файл.
  3. Через объект формы (AFormAut.App) получаем доступ к коллекции полей документа.
  4. Итерируем по этим полям, находим нужные по имени и присваиваем им значения из 1С.
  5. После внесения изменений сохраняем документ.

Рассмотрим пример кода, который демонстрирует заполнение полей формы в PDF-документе из 1С с использованием Adobe Acrobat Pro:


// Создаем COM-объект для документа PDF
doc = Новый COMОбъект("AcroExch.PDDoc");

// Открываем временный файл PDF. Предполагается, что ИмяВременногоФайла уже содержит путь к PDF.
// Для серверного или цикличного использования, возможно, потребуется каждый раз записывать исходный макет во временный файл.
ВременныйФайлДляРедактирования = ПолучитьИмяВременногоФайла("pdf");
// ДвоичныеДанныеМакета - это ДвоичныеДанные вашего исходного PDF-макета
ДвоичныеДанныеМакета.Записать(ВременныйФайлДляРедактирования); 

doc.Open(ВременныйФайлДляРедактирования);

// Создаем COM-объект для приложения Adobe Acrobat.
// Обратите внимание, что AcroExch.App является приложением, которое может быть скрыто или видимо.
AcroExchApp = Новый COMОбъект("AcroExch.App");
AcroExchApp.Hide(); // Скрываем окно приложения Adobe Acrobat, если оно появляется

// Для работы с формами также может потребоваться объект AVDoc
AcroExchAVDoc = Новый COMОбъект("AcroExch.AVDoc");
// Открываем документ через AVDoc. Это может быть необходимо для доступа к некоторым функциям.
// doc.OpenAVDoc(ВременныйФайлДляРедактирования); - этот вызов может быть избыточен или конфликтовать, если doc уже открыт.
// Более корректно использовать метод OpenFromPDDoc для AVDoc, если уже есть PDDoc.
// Однако, в примере выше использовано прямое открытие, что также может работать в зависимости от версии.
// Пусть avDoc будет результатом doc.OpenAVDoc(ВременныйФайлДляРедактирования) или создадим AVDoc и свяжем с PDDoc.
// В данном случае, изначальный код использовал avDoc = doc.OpenAVDoc(ИмяВременногоФайла);
// Придерживаемся логики автора:
avDoc = AcroExchAVDoc.Open(ВременныйФайлДляРедактирования, ""); // Открываем AVDoc, связывая его с файлом.

// Создаем COM-объект для работы с формами PDF
form = Новый COMОбъект("AFormAut.App");
// Получаем коллекцию полей формы документа
Fields = form.Fields;

// Итерируем по всем полям формы
Для Каждого Field Из Fields Цикл
    // Проверяем имя поля для заполнения данных из 1С
    Если Лев(Field.Name, 21) = "v8Отпуск_планКолДней_" Тогда
        // Заполняем поле формы данными из 1С. 
        // Вместо СлЧисло = ГСЧ.СлучайноеЧисло(1); используем реальные данные.
        Field.Value = "Количество дней отпуска из 1С"; 
    КонецЕсли;
    // Пример, как сделать поле только для чтения, если в его имени есть "IsReadOnly"
    Если СтрНайти(Field.Name, "IsReadOnly") > 0 Тогда 
        Field.IsReadOnly = True;
    КонецЕсли;
КонецЦикла;

// Сохраняем измененный PDF-документ
ResultSave = doc.Save(1, ВременныйФайлДляРедактирования); // 1 означает сохранить как копию, можно сохранить в исходный файл

// Закрываем открытые объекты для освобождения ресурсов
doc.Close();
avDoc.Close(0); // 0 - не сохранять изменения (так как уже сохранили через doc.Save)

// Закрываем все документы в приложении Adobe Acrobat и завершаем работу приложения
AcroExchApp.CLoseAllDocs();
AcroExchApp.Exit();

Ограничения и проблемы:

  1. Лицензирование: Самая существенная проблема с этим подходом — это лицензирование. Adobe Acrobat Pro является коммерческим продуктом. Для автоматизированных серверных процессов (например, формирования файлов регламентным заданием и отправки по почте), требуется отдельное соглашение с Adobe, что часто оказывается сложным и дорогостоящим. Adobe не всегда готов предоставить стандартные лицензии для серверного использования COM-объектов.
  2. Работа с произвольным текстом: Хотя этот метод отлично подходит для заполнения заранее определенных полей формы, он не предоставляет прямого и удобного способа для изменения произвольного "статического" текста в документе (т.е. текста, который не является полем формы). Использование CreateTextSelect и GetNumText позволяет читать текст, но не заменять его напрямую.
  3. Зависимость от клиентского ПО: Наличие установленного Adobe Acrobat Pro на машине, где выполняется код 1С, является обязательным.

2. Использование сторонних PDF-библиотек (Debenu Quick PDF Library, Foxit SDK)

Для обхода лицензионных ограничений Adobe и расширения функциональности по работе с PDF, мы можем рассмотреть сторонние библиотеки, разработанные специально для программного взаимодействия с PDF-файлами. Эти библиотеки часто предоставляют более гибкие возможности, включая изменение произвольного текста, добавление элементов, подпись и т.д.

2.1. Debenu Quick PDF Library (ранее Quick PDF Library)

Debenu Quick PDF Library является одной из популярных библиотек для работы с PDF. Она предоставляет COM-интерфейс, что делает её относительно простой для использования из 1С через Новый COMОбъект(). Эта библиотека предлагает широкий спектр функций для манипуляции PDF-документами.

Возможности Debenu:

Особенности интеграции с 1С:

Библиотека обычно поставляется в виде DLL-файла, который необходимо зарегистрировать в системе (например, с помощью regsvr32). После регистрации мы можем создать объект библиотеки в 1С:


// Создаем COM-объект для Debenu Quick PDF Library. 
// Имя объекта может отличаться в зависимости от версии и способа регистрации.
// Например: "QuickPDF.PDFLibrary" или "Debenu.QuickPDF.Library"
QP = Новый COMОбъект("QuickPDF.PDFLibrary"); 

Далее мы можем использовать методы объекта QP для работы с PDF. Например, для открытия документа, поиска и замены текста, работы с полями форм и сохранения изменений.

Решение проблемы с кириллицей:

При работе с Debenu Quick PDF Library может возникнуть проблема с отображением кириллицы, когда текст исчезает при снятии курсора с поля. Эту проблему можно решить, установив специальное свойство для документа. Мы используем методы GetNeedAppearances() и SetNeedAppearances():


// Получаем текущее значение свойства NeedAppearances
GetNeedAppearances_Result = QP.GetNeedAppearances(); 
// Устанавливаем свойство NeedAppearances в 1. 
// Это свойство указывает, что внешние виды полей формы должны генерироваться автоматически,
// что часто помогает с корректным отображением текста, включая кириллицу.
SetNeedAppearances_Result = QP.SetNeedAppearances(1); 

Преимущества:

2.2. Foxit SDK

Foxit также предлагает свои SDK для работы с PDF, доступные на различных языках программирования: .NET, C, C++, Java. Foxit PhantomPDF, как и Adobe Acrobat Pro, предоставляет богатые возможности редактирования.

Интеграция с 1С:

Прямая интеграция Foxit SDK в 1С может быть более сложной, чем с Debenu, особенно если SDK представлен в виде C++ DLL, не имеющей прямого COM-интерфейса. Попытки использовать ПодключитьВнешнююКомпоненту() или regsvr32 напрямую для таких библиотек могут не увенчаться успехом, так как 1С ожидает определенный интерфейс для внешних компонент.

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

  1. Если Foxit предоставляет COM-интерфейс (подобно Adobe), то используем Новый COMОбъект().
  2. Если Foxit SDK доступен для .NET, мы можем создать .NET-обертку (assembly), которая будет использовать Foxit SDK, а затем интегрировать эту обертку в 1С через .NET Bridge или аналогичные механизмы.
  3. Для Java SDK может потребоваться создание отдельного Java-приложения или микросервиса, который будет взаимодействовать с 1С.

Особенности:

3. Архитектура на основе микросервисов

Для серверных задач, особенно тех, которые требуют высокой гибкости, мультиплатформенности или работы со сложными библиотеками, наиболее надежным и архитектурно правильным решением является создание отдельного микросервиса. Этот микросервис будет заниматься всей логикой работы с PDF, а 1С будет лишь взаимодействовать с ним по стандартным протоколам (например, HTTP).

Принцип работы:

  1. 1С подготавливает данные и PDF-файл (в виде двоичных данных).
  2. 1С отправляет эти данные и файл на микросервис (например, POST-запросом).
  3. Микросервис на своем языке программирования (Python, Java, C#, Go и т.д.) получает PDF, обрабатывает его, заполняет необходимые поля и изменяет текст с помощью специализированных библиотек.
  4. Микросервис возвращает измененный PDF-файл обратно в 1С.

Преимущества такого подхода:

Рассмотрим несколько языков и библиотек, подходящих для создания такого микросервиса:

3.1. Java с Apache PDFBox или OpenPDF

Java является отличным выбором для создания микросервисов благодаря своей зрелой экосистеме и производительности. Для работы с PDF в Java доступны мощные открытые библиотеки.

Мы можем использовать фреймворк, такой как Spring Boot, для быстрого создания RESTful-сервиса на Java, который будет принимать PDF-файл и данные от 1С, обрабатывать их с помощью PDFBox и возвращать результат.

3.2. Python с PyPDF2, pikepdf или ReportLab

Python также популярен для автоматизации и создания микросервисов. Для работы с PDF в Python существует несколько библиотек:

С помощью таких фреймворков, как Flask или FastAPI, можно легко создать простой HTTP-сервис на Python.

3.3. C# (ASP.NET Core)

Если инфраструктура в основном Windows, C# и ASP.NET Core являются естественным выбором. Существуют коммерческие (например, Syncfusion PDF, Aspose.PDF) и некоторые бесплатные (например, PdfSharp) библиотеки для работы с PDF в .NET, которые предоставляют все необходимые функции.

3.4. Go с библиотеками, такими как signintech/pdft

Go набирает популярность для создания высокопроизводительных микросервисов. Есть библиотеки для работы с PDF, например, signintech/pdft, которые позволяют выполнять различные операции.

Взаимодействие 1С с микросервисом:

Из 1С мы можем использовать стандартные объекты для HTTP-запросов, например, HTTPЗапрос и HTTPСоединение, чтобы отправить файл и данные на микросервис и получить обратно измененный PDF:


// Пример отправки файла и данных на микросервис
Функция ОтправитьPDFНаСервис(ИмяФайлаPDF, ДанныеДляЗаполнения)

    HTTPСоединение = Новый HTTPСоединение("localhost", 8080); // Адрес и порт вашего микросервиса
    
    // Формируем тело запроса
    ТелоЗапроса = Новый ДвоичныеДанные(ИмяФайлаPDF); // Сам PDF-файл
    // Можно добавить параметры формы, если микросервис ожидает их
    // Например, через ФормаДанных = Новый Соответствие(); ФормаДанных.Вставить("field1", "value1");
    // и затем использовать МногофункциональныйHTTPЗапрос.УстановитьТелоИзФормыДанных()
    
    Заголовки = Новый Соответствие();
    Заголовки.Вставить("Content-Type", "application/pdf"); // Или multipart/form-data если есть доп. параметры
    
    HTTPЗапрос = Новый HTTPЗапрос("/process-pdf", Заголовки); // Путь к эндпоинту сервиса
    HTTPЗапрос.УстановитьТело(ТелоЗапроса);

    Попытка
        Ответ = HTTPСоединение.Отправить(HTTPЗапрос);
        Если Ответ.КодСостояния = 200 Тогда
            // Успешно, получаем измененный PDF
            ИзмененныйPDF = Ответ.ПолучитьТелоКакДвоичныеДанные();
            Возврат ИзмененныйPDF;
        Иначе
            Сообщить("Ошибка обработки PDF: " + Ответ.КодСостояния + " " + Ответ.ПолучитьТелоКакСтроку());
            Возврат Неопределено;
        КонецЕсли;
    Исключение
        Сообщить("Ошибка при отправке запроса: " + ОписаниеОшибки());
        Возврат Неопределено;
    КонецПопытки;
    
КонецФункции

// Пример использования:
// ИзмененныйPDF = ОтправитьPDFНаСервис("C:\Исходный.pdf", Новый Структура("Поле1", "Значение1"));
// Если ИзмененныйPDF <> Неопределено Тогда
//     ИзмененныйPDF.Записать("C:\Измененный.pdf");
// КонецЕсли;

4. Встроенные возможности платформы 1С

Платформа 1С имеет собственные возможности для работы с PDF-документами, но они, как правило, ориентированы на сохранение и просмотр, а не на полноценное редактирование произвольного текста в уже существующем файле.

Таким образом, для решения задачи по изменению содержимого существующего PDF, встроенные средства 1С, скорее всего, будут недостаточны.

5. Общие рекомендации и выводы

При выборе подхода к изменению PDF из 1С, мы рекомендуем учитывать следующие моменты:

  1. Требования к редактированию:
    • Если нужно только заполнять существующие поля форм, и вы готовы работать с Adobe Acrobat Pro на клиентской машине, то OLE-автоматизация может быть простейшим путем. Однако, помним о лицензировании для серверных задач.
    • Если требуется изменять произвольный текст, добавлять новые элементы, или обходить проблемы с лицензированием Adobe, то сторонние библиотеки или микросервис будут предпочтительнее.
  2. Среда выполнения:
    • Клиентская часть: OLE-автоматизация с Adobe или Debenu COM-объекты (при наличии лицензии на библиотеку) могут быть использованы.
    • Серверная часть: Категорически рекомендуем рассмотреть архитектуру на основе микросервисов. Это обеспечивает гибкость, масштабируемость и независимость от специфичных для 1С или Windows решений.
  3. Кириллица и шрифты: Всегда проверяем, как выбранная библиотека или метод справляется с кириллицей. Часто это требует явного указания кодировки или внедрения шрифтов (как в случае с SetNeedAppearances(1) для Debenu).
  4. Бизнес-процесс: Мы также должны анализировать, действительно ли PDF является лучшим форматом для данного бизнес-процесса. В некоторых случаях, когда требуется интерактивное заполнение и последующая цифровая подпись, PDF может быть оправдан. Однако, если это просто печатная форма, которую можно заполнить в 1С или Word, возможно, стоит рассмотреть более простые альтернативы.

В целом, проблема изменения PDF из 1С не имеет универсального "серебряного шара". Мы вынуждены выбирать между простотой реализации (OLE с Adobe), гибкостью сторонних библиотек (Debenu, Foxit) и надежностью архитектурных решений (микросервисы), исходя из конкретных требований проекта и имеющихся ресурсов.

← На главную