Fußzeilen in PDFs per Batch-Verarbeitung erstellen

Zusätz­li­che PDF-Tools machen es mög­lich, PDFs auch ohne Ado­be Acro­bat Pro zu bear­bei­ten. Die­ser Arti­kel stellt eine wei­te­re Lösung vor, über die sich Text in PDF-Datei­en ein­bau­en lässt, bei­spiels­wei­se für eine Fuß­zei­le.

Es gibt eini­ge Open-Source-Tools, mit denen sich PDFs bear­bei­ten las­sen. Eins davon ist die Biblio­thek pypdf (https://pypdf.readthedocs.io/en/latest/). Sie ermög­licht, PDF-Datei­en auf­zu­tei­len, zusam­men­zu­fü­gen oder umzu­wan­deln. Ein wei­te­res ist PyPDF­Form (https://chinapandaman.github.io/PyPDFForm/), mit dem sich PDF-For­mu­la­re aus­fül­len und For­mu­lar­fel­der ein­fü­gen las­sen. Mit bei­den zusam­men kann man Fuß­zei­len bezie­hungs­wei­se Text oder Bil­der an belie­bi­gen Posi­tio­nen in PDF-Datei­en ein­bau­en, was wir mit dem Kom­man­do­zei­len­tool pdf_text_inserter rea­li­siert haben. Das Python-Tool habe ich für Win­dows kom­pi­liert um die Ver­wen­dung so ein­fach wie mög­lich zu machen. Der Quell­text ist unten zu sehen. Dazu gibt es noch das gra­fi­sche Front­end pdf­Insert­Text, über das sich das Tool steu­ern lässt. Alter­na­tiv ver­wen­den Sie pdf_text_inserter unter Win­dows in einer Batch­da­tei.

Eine alter­na­ti­ve Lösung für Besit­zer von Ado­be Acro­bat Pro habe ich im Arti­kel „Ado­be Acro­bat Pro: Fuß­zei­len mit Java­script-Akti­on erstel­len“ vor­ge­stellt. Wer Fuß­zei­len über den kos­ten­lo­sen Acro­bat Rea­der in ein­zel­ne PDF-Datei­en ein­set­zen will, liest den Arti­kel „Ado­be Rea­der: Datei­na­men in PDF-Doku­men­ten auf jede Sei­te dru­cken“.

Down­load zu die­sem Arti­kel:
pdf­Insert­Text 1.1
Lizenz: GNU Les­ser Gene­ral Public Licen­se
47 Down­loads
Down­load zu die­sem Arti­kel:
pdf­Insert­Text Linux-Ver­si­on 1.1
Lizenz: GNU Les­ser Gene­ral Public Licen­se
Wenn nicht vor­han­den, bit­te unter Ubuntu/Linux Mint mit sudo apt install libgtk2.0–0 das feh­len­de Paket instal­lie­ren.
12 Down­loads

pdfInsertText konfigurieren und nutzen

Ent­pa­cken Sie das Archiv und star­ten Sie pdfInsertText.exe. In das Feld links oben kön­nen Sie PDF-Datei­en per Drag & Drop vom Datei­ma­na­ger aus hin­ein­zie­hen. Oder Sie ver­wen­den die Schalt­flä­che „Datei­en hin­zu­fü­gen“. Mit „Ord­ner hin­zu­fü­gen“ geben Sie einen Ord­ner an, aus dem alle PDF-Datei­en hin­zu­ge­fügt wer­den.

Kon­fi­gu­rie­ren Sie hin­ter „Aus­ga­be­ord­ner“ eine Zielor­dern, in dem Sie die bear­bei­te­ten PDF-Datei spei­chern wol­len. Der Ord­ner soll­te leer sein. Alle ent­hal­te­nen PDF-Datei­en mit dem glei­chen Name wer­den ohne Rück­fra­ge über­schrie­ben, wenn ein Häk­chen vor „Datei­en im Aus­ga­be­ver­zeich­nis über­schrei­ben (Vor­sicht!)“ gesetzt ist. Andern­falls wer­den die Datei­en über­sprun­gen.

Hin­ter „Text für Fuß­zei­le“ gehen Sie Tex­te ein, der in der Fuß­zei­le ent­hal­ten sein soll. Dar­un­ter kön­nen Sie Platz­hal­ter wäh­len, um bei­spiels­wei­se das Datum, den Datei­na­men oder Sei­ten­zah­len in den Fuß­zeil­en­text ein­zu­bau­en.

Mit den Ein­stel­lun­gen unter „Optio­nen“ ändern Sie das Ver­hal­ten des Tools. Ist „Nur ers­te Sei­te“ aktiv, wird die Fuß­zei­le nur ein die ers­te Sei­te ein­ge­setzt. Die ande­ren Optio­nen bestim­men das Aus­se­hen der Fuß­zei­le, bei­spiels­wei­se Schrift­grö­ße und Schrift­far­be (in Hex).

Intern las­sen sich die PDF-Stan­dard­fonts Font Hel­ve­ti­ca und Cou­rier ver­wen­den. Hel­ve­ti­ca ist der Stan­dard, Cou­rier kön­nen Sie hin­ter „Schrift­na­me“ ein­tra­gen. Für ande­re Schrift­ar­ten erwar­tet „Schrift­na­me“ den Datei­na­men einer ttf-Datei, die im Ord­ner „Tools\Fonts“ lie­gen muss.

Da PyPDF­Form kei­ne Opti­on für zen­trier­ten Text besitzt, muss die Brei­te des Tex­tes in der Fuß­zei­le berech­net wer­den. Der Stan­dard für „Lauf­wei­te“ ist „0.2“, was für den Font Hel­ve­ti­ca meist pas­sen soll­te. Wenn ande­re Fonts zu weit links oder rechts erschei­nen, ver­wen­den Sie einen ande­ren Wert, was Sie aus­pro­bie­ren müs­sen.

„Y‑Versatz“ und „X‑Versatz“ bestim­men die Posi­ti­on des Tex­tes auf der Sei­te. Das Koor­di­na­ten­sys­tem auf einer ein­zel­nen Sei­te einer PDF-Datei beginnt am lin­ken unte­ren Rand der Sei­te als Ursprung. Die Ein­heit der Koor­di­na­ten wird „Punk­te“ genannt und es gibt 72 Punkte/Zoll. PyPDF­Form nutzt die­ses Koor­di­na­ten­sys­tem in eini­gen sei­ner APIs, so dass Wid­gets, Tex­te oder Bil­der in einem PDF erstellt wer­den kön­nen. Der Stan­dard von pdf_text_inserter ist jeweils 30 Punk­te, wobei „X‑Versatz“ nur berück­sich­tigt wird, wenn bei „Aus­rich­tung“ etwas ande­res als „cen­ter“ (zen­triert) ein­ge­stellt ist. Über den Para­me­ter „Y‑Versatz“ lässt sich der Text auch am obe­ren Sei­ten­rand für eine Kopf­zei­le posi­tio­nie­ren.

Nach­dem alles kon­fi­gu­riert ist, kli­cken Sie auf „Start“. Die Datei­en mit den ein­ge­füg­ten Fuß­zei­len lie­gen danach im Aus­ga­be­ord­ner.

pdf_text_inserter für die Batch-Verarbeitung nutzen

Wenn Sie die Ver­ar­bei­tung von PDF-Datei­en auto­ma­ti­sie­ren wol­len, ver­wen­den Sie pdf_text_inserter.exe in einer Batch-Datei. Die mög­li­chen Para­me­ter sind die­se:

usa­ge: 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]

opti­ons:
-h, –help show this help mes­sa­ge and exit
-f FILENAME PDF-Datei­na­me (erfor­der­lich)
-o OUTFILENAME Name der Aus­ga­be­da­tei (erfor­der­lich)
-t TEXT Fuß­zeil­en­text (erfor­der­lich)
-s FONT_SIZE Optio­nal: Schrift­grö­ße in pt
-c FONT_SCALE Optio­nal: Fak­tor für Font-Lauf­wei­te
-n FONT_NAME Optio­nal: Name der Font-Datei
-l FONTCOLOR Optio­nal: Schrift­far­be in Hex
-y MARGIN_Y Optio­nal: Y‑Versatz
-x MARGIN_X Optio­nal: X‑Versatz (not cen­te­red)
-a {center,left,right} Optio­nal: Text­aus­rich­tung
-p Optio­nal: Fuß­zei­le nur auf der ers­ten Sei­te
-b Kei­ne Far­ben im Ter­mi­nal

Eine Batch­da­tei kann so aus­se­hen (im Down­load-Archiv ent­hal­ten):

@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}")


Schlagwörter:


Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

Neueste Kommentare


Die Website durchsuchen