Editing PDFs in PowerShell

iText is an excellent library for editing PDFs, available for both Java and .NET. PowerShell is capable of loading and using .NET libraries, so with a little magic, we can utilize the .NET iText library (licensed under AGPL) to edit PDFs in PowerShell

Add-Type -Path "$PSScriptRoot\Common.Logging.Core.dll"
Add-Type -Path "$PSScriptRoot\Common.Logging.dll"
Add-Type -Path "$PSScriptRoot\itext.io.dll"
Add-Type -Path "$PSScriptRoot\itext.kernel.dll"
Add-Type -Path "$PSScriptRoot\itext.forms.dll"
Add-Type -Path "$PSScriptRoot\itext.layout.dll"
Add-Type -Path "$PSScriptRoot\BouncyCastle.Crypto.dll"

The above DLLs include the iText libraries and dependencies. Here is a convenient ZIP file with the required DLL files:

There are additional iText DLLs you may want to load for additional features. The full AGPL iText library and links to dependencies are available at the following URL:

https://www.nuget.org/packages/itext7/

The full documentation is available at the following URL:

https://itextpdf.com/en/resources/api-documentation/itext-7-net

I won’t go into full detail on how to use this library in this post, but I will cover some basics and give a few examples to show how to use a .NET library in a PowerShell script.

First, we initialize a PdfReader object for accessing the PDF:

$Reader = [iText.Kernel.Pdf.PdfReader]::new("C:\temp\example.pdf")

Optionally, if you want to ignore password protection on a PDF, you can add the following line after:

$Reader.SetUnethicalReading($True)

Next, we initialize a PdfWriter object to write our modified PDF to:

$Writer = [iText.Kernel.Pdf.PdfWriter]::new("C:\example\new_example.pdf")

Now we generate a PdfDocument object to tie our PdfReader and PdfWriter together and allow us to start our work:

$PdfDoc = [iText.Kernel.Pdf.PdfDocument]::new($Reader, $Writer)

For this example, let’s find a form field and fill it with data. The PdfAcroForm class works with static PDF forms. We’ll start by collecting the form and all of the fields that belong to it:

$Form = [iText.Forms.PdfAcroForm]::getAcroForm($PdfDoc, $True)
$Fields = $Form.getFormFields()

getFormFields() returns a dictionary where the key is the name of the field and the value is the actual PdfFormField object. If we want to work with the field named “EmployeeName”, we can easily do so:

$Field = ($Fields | Where-Object {$_.key -eq "EmployeeName"}).Value

Now that we have the field object, we can easily set its value with the SetValue function:

$Field.SetValue("DOE, JOHN")

Once we’re done working with the document, committing our changes is as simple as calling the Close function on the PdfDocument object:

$PdfDoc.Close()

The file opened with the PdfWriter object will now exist with the changes.