Zusätzliche PDF-Tools machen es möglich, PDFs auch ohne Adobe Acrobat Pro zu bearbeiten. Dieser Artikel stellt eine weitere Lösung vor, über die sich Text in PDF-Dateien einbauen lässt, beispielsweise für eine Fußzeile.
Es gibt einige Open-Source-Tools, mit denen sich PDFs bearbeiten lassen. Eins davon ist die Bibliothek pypdf (https://pypdf.readthedocs.io/en/latest/). Sie ermöglicht, PDF-Dateien aufzuteilen, zusammenzufügen oder umzuwandeln. Ein weiteres ist PyPDFForm (https://chinapandaman.github.io/PyPDFForm/), mit dem sich PDF-Formulare ausfüllen und Formularfelder einfügen lassen. Mit beiden zusammen kann man Fußzeilen beziehungsweise Text oder Bilder an beliebigen Positionen in PDF-Dateien einbauen, was wir mit dem Kommandozeilentool pdf_text_inserter realisiert haben. Das Python-Tool habe ich für Windows kompiliert um die Verwendung so einfach wie möglich zu machen. Der Quelltext ist unten zu sehen. Dazu gibt es noch das grafische Frontend pdfInsertText, über das sich das Tool steuern lässt. Alternativ verwenden Sie pdf_text_inserter unter Windows in einer Batchdatei.
Eine alternative Lösung für Besitzer von Adobe Acrobat Pro habe ich im Artikel „Adobe Acrobat Pro: Fußzeilen mit Javascript-Aktion erstellen“ vorgestellt. Wer Fußzeilen über den kostenlosen Acrobat Reader in einzelne PDF-Dateien einsetzen will, liest den Artikel „Adobe Reader: Dateinamen in PDF-Dokumenten auf jede Seite drucken“.
pdfInsertText 1.1
Lizenz: GNU Lesser General Public License
pdfInsertText Linux-Version 1.1
Lizenz: GNU Lesser General Public License
Wenn nicht vorhanden, bitte unter Ubuntu/Linux Mint mit sudo apt install libgtk2.0–0 das fehlende Paket installieren.
pdfInsertText konfigurieren und nutzen
Entpacken Sie das Archiv und starten Sie pdfInsertText.exe. In das Feld links oben können Sie PDF-Dateien per Drag & Drop vom Dateimanager aus hineinziehen. Oder Sie verwenden die Schaltfläche „Dateien hinzufügen“. Mit „Ordner hinzufügen“ geben Sie einen Ordner an, aus dem alle PDF-Dateien hinzugefügt werden.
![pdfTextInserter setzt Fußzeilen in PDF-Dateien ein.](https://www.myria.de/wp-content/uploads/2024/07/pdfInsertText.jpg)
Konfigurieren Sie hinter „Ausgabeordner“ eine Zielordern, in dem Sie die bearbeiteten PDF-Datei speichern wollen. Der Ordner sollte leer sein. Alle enthaltenen PDF-Dateien mit dem gleichen Name werden ohne Rückfrage überschrieben, wenn ein Häkchen vor „Dateien im Ausgabeverzeichnis überschreiben (Vorsicht!)“ gesetzt ist. Andernfalls werden die Dateien übersprungen.
Hinter „Text für Fußzeile“ gehen Sie Texte ein, der in der Fußzeile enthalten sein soll. Darunter können Sie Platzhalter wählen, um beispielsweise das Datum, den Dateinamen oder Seitenzahlen in den Fußzeilentext einzubauen.
Mit den Einstellungen unter „Optionen“ ändern Sie das Verhalten des Tools. Ist „Nur erste Seite“ aktiv, wird die Fußzeile nur ein die erste Seite eingesetzt. Die anderen Optionen bestimmen das Aussehen der Fußzeile, beispielsweise Schriftgröße und Schriftfarbe (in Hex).
Intern lassen sich die PDF-Standardfonts Font Helvetica und Courier verwenden. Helvetica ist der Standard, Courier können Sie hinter „Schriftname“ eintragen. Für andere Schriftarten erwartet „Schriftname“ den Dateinamen einer ttf-Datei, die im Ordner „Tools\Fonts“ liegen muss.
Da PyPDFForm keine Option für zentrierten Text besitzt, muss die Breite des Textes in der Fußzeile berechnet werden. Der Standard für „Laufweite“ ist „0.2“, was für den Font Helvetica meist passen sollte. Wenn andere Fonts zu weit links oder rechts erscheinen, verwenden Sie einen anderen Wert, was Sie ausprobieren müssen.
„Y‑Versatz“ und „X‑Versatz“ bestimmen die Position des Textes auf der Seite. Das Koordinatensystem auf einer einzelnen Seite einer PDF-Datei beginnt am linken unteren Rand der Seite als Ursprung. Die Einheit der Koordinaten wird „Punkte“ genannt und es gibt 72 Punkte/Zoll. PyPDFForm nutzt dieses Koordinatensystem in einigen seiner APIs, so dass Widgets, Texte oder Bilder in einem PDF erstellt werden können. Der Standard von pdf_text_inserter ist jeweils 30 Punkte, wobei „X‑Versatz“ nur berücksichtigt wird, wenn bei „Ausrichtung“ etwas anderes als „center“ (zentriert) eingestellt ist. Über den Parameter „Y‑Versatz“ lässt sich der Text auch am oberen Seitenrand für eine Kopfzeile positionieren.
Nachdem alles konfiguriert ist, klicken Sie auf „Start“. Die Dateien mit den eingefügten Fußzeilen liegen danach im Ausgabeordner.
pdf_text_inserter für die Batch-Verarbeitung nutzen
Wenn Sie die Verarbeitung von PDF-Dateien automatisieren wollen, verwenden Sie pdf_text_inserter.exe in einer Batch-Datei. Die möglichen Parameter sind diese:
usage: pdf_text_inserter.exe [-h] [-f FILENAME] [-o OUTFILENAME] [-t TEXT] [-s FONT_SIZE] [-c FONT_SCALE]
[-n FONT_NAME] [-l FONTCOLOR] [-y MARGIN_Y] [-x MARGIN_X] [-a {center,left,right}] [-p]
[-b]
options:
-h, –help show this help message and exit
-f FILENAME PDF-Dateiname (erforderlich)
-o OUTFILENAME Name der Ausgabedatei (erforderlich)
-t TEXT Fußzeilentext (erforderlich)
-s FONT_SIZE Optional: Schriftgröße in pt
-c FONT_SCALE Optional: Faktor für Font-Laufweite
-n FONT_NAME Optional: Name der Font-Datei
-l FONTCOLOR Optional: Schriftfarbe in Hex
-y MARGIN_Y Optional: Y‑Versatz
-x MARGIN_X Optional: X‑Versatz (not centered)
-a {center,left,right} Optional: Textausrichtung
-p Optional: Fußzeile nur auf der ersten Seite
-b Keine Farben im Terminal
Eine Batchdatei kann so aussehen (im Download-Archiv enthalten):
@echo off
setlocal enabledelayedexpansion
chcp 1252>nul
REM Verzeichnis mit Quelldateien
set SOURCE=In
REM Zielverzeichnis
set TARGET=OUT
REM Zieldateien überschreiben OVERWRITE=True
REM set OVERWRITE=False
set OVERWRITE=True
REM Datum
set dt=%DATE:~6,4%-%DATE:~3,2%-%DATE:~0,2%
REM Datum und Uhrzeit
REM dt=%DATE:~6,4%-%DATE:~3,2%-%DATE:~0,2%--%TIME:~0,2%-%TIME:~3,2%-%TIME:~6,2%
set dt=%dt: =0%
for %%a in (%SOURCE%\*.pdf) do (
REM Nur Dateiname
set TEXT=%%~nxa
REM Datum und Dateiname
REM set TEXT=%dt%-%%~nxa
REM Pfad und Dateiname der Quelldatei
REM set TEXT=%%~dpa%%~nxa
REM echo %%~nxa
if %OVERWRITE%==False (
if exist %TARGET%\%%~nxa (
echo Zieldatei !TARGET!\%%~nxa bereits vorhanden
) else (
REM call with source path and file name
call :insert "%%~nxa"
)
) else (
REM Überschreiben
REM call with file name
call :insert "%%~nxa"
)
REM end for
)
goto :eof
:insert
echo Füge ein Fußzeile: %TEXT%
TOOLS\pdf_text_inserter.exe -b -f %SOURCE%\%~1 -o %TARGET%\%~1 -t %TEXT%
goto :eof
Python-Quellcode von pdf_text_inserter
import argparse
import sys
import os.path
from PyPDFForm import PdfWrapper
from pypdf import PdfReader
parser = argparse.ArgumentParser()
parser.add_argument("-f", dest="filename", help = "PDF-Dateiname (erforderlich)")
parser.add_argument("-o", dest="outfilename", help = "Name der Ausgabedatei (erforderlich)")
parser.add_argument("-t", dest="text", type=str, help = "Fußzeilentext (erforderlich)")
parser.add_argument("-s", dest="font_size", type=int, default=12, help = "Optional: Schriftgröße in pt")
parser.add_argument("-c", dest="font_scale", type=float, default=0.2, help = "Optional: Faktor für Font-Laufweite")
parser.add_argument("-n", dest="font_name", default="Helvetica", help = "Optional: Name der Font-Datei")
parser.add_argument("-l", dest="FontColor", default="000000", help = "Optional: Schriftfarbe in Hex")
parser.add_argument("-y", dest="margin_y", type=int, default=30, help = "Optional: Y-Versatz")
parser.add_argument("-x", dest="margin_x", type=int, default=30, help = "Optional: X-Versatz (not centered)")
parser.add_argument("-a", choices=["center","left","right"], default="center", dest="align", help = "Optional: Textausrichtung")
parser.add_argument("-p", dest="FirstPageOnly", action="store_true", default=False, help = "Optional: Fußzeile nur auf der ersten Seite")
parser.add_argument("-b", dest="NoColors", action="store_false", default=True, help = "Keine Farben im Terminal")
args=parser.parse_args()
if sys.platform == 'win32':
os.system('color')
class bcolors:
OKGREEN = "\033[92m"
FAIL = "\033[91m"
ENDC = "\033[0m"
if not (args.filename):
print("")
if args.NoColors:
print ("Fehler: Name der PDF-Datei fehlt.")
else:
print (f"{bcolors.FAIL}Fehler: Name der PDF-Datei fehlt.{bcolors.ENDC}")
print("")
parser.print_help()
sys.exit()
if not (args.outfilename):
print("")
if args.NoColors:
print ("Fehler: Name der Ausgabedatei fehlt.")
else:
print (f"{bcolors.FAIL}Fehler: Name der Ausgabedatei fehlt.{bcolors.ENDC}")
print("")
parser.print_help()
sys.exit()
if not (args.text):
print("")
if arg.NoColors:
print ("Fehler: Text für die Fußzeile fehlt.")
else:
print (f"{bcolors.FAIL}Fehler: Text für die Fußzeile fehlt.{bcolors.ENDC}")
print("")
parser.print_help()
sys.exit()
if not os.path.isfile(args.filename):
if args.NoColors:
print("Fehler: Datei " +args.filename + " ist nicht vorhanden.")
else:
print(f"{bcolors.FAIL}Fehler: Datei " +args.filename + " ist nicht vorhanden."+ f"{bcolors.ENDC}")
sys.exit(1)
# convert font color hex to RGB
FontColor=tuple(int(args.FontColor[i:i+2], 16) for i in (0, 2, 4))
reader = PdfReader(args.filename)
number_of_pages = reader.get_num_pages()
print("Seitenanzahl: " + str(number_of_pages))
myText=args.text.replace('%%total-pages%%',str(number_of_pages))
if (args.font_name=="Helvetica"):
myFont="Helvetica"
if (args.font_name=="Courier"):
myFont="Courier"
if not (args.font_name =="Helvetica" or args.font_name =="Courier"):
if not os.path.isfile('Tools/fonts/' +args.font_name):
if args.NoColors:
print("Fehler: Tools/fonts/" +args.font_name + " ist nicht vorhanden.")
else:
print(f"{bcolors.FAIL}Fehler: Tools/fonts/" +args.font_name + " ist nicht vorhanden."+ f"{bcolors.ENDC}")
sys.exit(1)
PdfWrapper.register_font("myFont", "Tools/fonts/" + args.font_name)
pdf = PdfWrapper(args.filename,global_font="myFont")
myFont="myFont"
else:
pdf = PdfWrapper(args.filename)
if args.NoColors:
print ("Verarbeite: " + args.filename)
else:
print (f"{bcolors.OKGREEN}Verarbeite: " + args.filename +f"{bcolors.ENDC}")
pages=reader.pages
j=1
# Pages loop
for page in pages:
aRect=page.cropbox
myText=myText.replace('%%cur-page%%',str(j))
myText_len=len(myText)
# calculate text adjustment, factor font_scale depends on the used font
if (args.align=="center"):
new_text_pos=((aRect.width-30)/2)-(myText_len*(args.font_size*args.font_scale))
if (args.align=="left"):
new_text_pos=(args.margin_x)
if (args.align=="right"):
new_text_pos=(args.margin_x)
pdf.draw_text(
text=myText,
page_number=j,
x=new_text_pos,
y=args.margin_y,
font_size=args.font_size,
font=myFont, # optional
font_color=FontColor # optional
)
print("Verarbeite Seite: " + str(j))
if (args.FirstPageOnly==True):
break
j+=1
with open(args.outfilename, "wb+") as output:
output.write(pdf.read())
if args.NoColors:
print ("Fertig: Datei " + args.outfilename + " gespeichert.")
else:
print (f"{bcolors.OKGREEN}Fertig: Datei " + args.outfilename + " gespeichert."+f"{bcolors.ENDC}")
Schreibe einen Kommentar