Serien-PDFs mit Inkscape erstellen

Gelegentlich komme ich in Situationen, in denen ich automatisch PDF-Dokumente erzeugen lassen möchte, die sich nur an bestimmten Stellen unterscheiden.

Das können Namensschilder mit Design sein, bei denen lediglich die Namen von Schild zu Schild unterschiedlich sind, oder Preisschildchen, oder Bauchbinden1 und so weiter…

Oft greife ich dann zu einer Kombination aus Inkscape und einer Skriptsprache, um ans Ziel zu kommen. Die Idee funktioniert folgendermaßen:

  • Zunächst wird ein Template mit Platzhaltern erstellt
  • Die Platzhalter werden mit einer Skriptsprache durch die echten Werte ersetzt und dann in einer separaten SVG-Datei gespeichert
  • Diese SVG-Dateien werden schließlich in PDF-Dateien umgewandelt

Warum das Ganze? Nun, PDF-Dateien lassen sich so schwer bearbeiten. SVG-Dateien hingegen bestehen nur aus Text. Buchstaben, Zahlen und Klammern. Darin lässt es sich ganz leicht herumeditieren.

Für alle, die mehr auf grafische Darstellungen stehen:

pdfpipeline

Wir beginnen mit unseren Daten, die wir ins Template einfügen möchten. Als Beispiel nehmen wir hier Deckblätter für Bekanntmachungen in der AKUT extra2. Die benötigen ein Veröffentlichungsdatum, eine laufende Nummer und natürlich einen Titel.

datum;nummer;titel
17. Juli 2016;6/2016;Satzung der Fachschaft … Bonn
11. Juli 2016;5/2016;Wahlordnung für die Wahl …
31. Juni 2016;3/2016;Änderung der Satzung …

Zu Demonstrationszwecken speichern wir diese Daten in einer Datei namens data.csv.

Als nächstes erstellen wir mit Inkscape das SVG-Template, in das die Werte eingefügt werden.

Dort, wo aktuell VARDATUM, VARNUMMER und VARTITEL steht, werden später die echten Werte eingesetzt. Der Rest ist Zierde.

Comic Saaaaaaanns!3

Dort, wo aktuell VARDATUM, VARNUMMER und VARTITEL steht, werden später die echten Werte eingesetzt. Der Rest ist Zierde. Da der Titel auch mal länger als eine Zeile werden kann, nutzen wir einen Textkasten, in dem der Text automatisch umgebrochen wird.

Das Template speichern wir als template.svg.

Als letztes Puzzlestück fehlt nur noch ein Skript, das die Werte aus der CSV-Datei nimmt und sie ins Template einfügt. Ich habe mich hier als Beispiel für Python entschieden, das Prinzip lässt sich aber mit so gut wie jeder anderen Skript- und Programmiersprache umsetzen.

(Hinweis: Zeilen mit # am Anfang sind Kommentare, die den Programmfluss nicht beeinflussen.)

#! /usr/bin/env python3

import csv
import subprocess

# csv-Datei einlesen
data = []
with open("data.csv", "r") as csvfile:
    reader = csv.DictReader(csvfile, delimiter=";")
    for row in reader:
        data.append(row)


# Für jede Zeile aus der csv-Datei: 
# - Template laden
# - Variablen ersetzen
# - als neue SVG-Datei output-i.svg speichern

i = 0
for row in data:
    with open("template.svg", "r") as t, open("output-{0}.svg".format(i), "w") as output:
        
        # In jeder Zeile wird die Variable (falls vorhanden) durch den
        # entsprechenden Wert ersetzt
        for line in t:
            line = line.replace("VARDATUM", row["datum"])
            line = line.replace("VARNUMMER", row["nummer"])
            line = line.replace("VARTITEL", row["titel"])
            
            # modifizierte Zeile in output schreiben
            print(line, file=output, end="")
    i += 1


# SVG-Dateien mit Inkscape in PDF-Dateien umwandeln

for k in range(i):
    subprocess.call(["inkscape", 
          "--export-pdf=output-{0}.pdf".format(k), 
          "output-{0}.svg".format(k)])

Oben wird data.csv eingelesen. In der Mitte wird immer wieder template.svg geöffnet und die oben verwendeten Variablen (VAR…) werden durch die echten Werte ersetzt. Natürlich können diese Namen beliebig angepasst werden.

Ganz am Ende konvertiert das Skript alle erzeugten SVG-Dateien mit Inkscape automatisiert in PDF-Dateien.

screenshot-result-svgpdf

Juhu! Drei neue PDF-Dateien!

Und das Ergebnis kann sich sehen lassen:

resultat-svgpdf

Falls die Inhalte komische Sonderzeichen wie z. B. &, ” oder < enthalten, muss das Skript noch so angepasst werden, dass diese durch ihre XML-Repräsentation ersetzt werden. Wie das in Python geht, steht z.B. hier.

  1. Wobei die als png exportiert wurden, nicht als PDF. Funktioniert aber auf die gleiche Art und Weise.
  2. Das hat ja überhaupt gar nichts damit zu tun, dass ich so etwas ähnliches heute implementiert habe.
  3. http://explosm.net/comics/2301/

Favorite & Forget: Minecraft-Command-Fernsteuerung

Manchmal möchte man eine Reihe von Minecraft-Commands hintereinander ausführen, aber das ganze in eine Command-Block-Kette zu packen ist wahlweise

  • zu aufwändig, da alles sowieso nur ein einziges Mal ausgeführt werden soll, oder
  • nicht möglich, da es zu viele Commands sind, und deshalb das Zeichenlimit überschritten würde.

In so einem Fall hilft xdotool weiter. Die auszuführenden Commands liegen zeilenweise in der Datei commands.txt1:

/tp 593 42 -613
/fill 593 40 -613 603 40 -613 gold
/fill 593 40 -612 603 40 -612 gold
/fill 593 40 -611 603 40 -611 gold
/fill 593 40 -610 604 40 -610 gold
/fill 593 40 -609 604 40 -609 gold
/fill 594 40 -608 604 40 -608 gold
/fill 594 40 -607 604 40 -607 gold
/fill 594 40 -606 605 40 -606 gold
/fill 594 40 -605 605 40 -605 gold
/fill 595 40 -604 605 40 -604 gold
/fill 595 40 -603 605 40 -603 gold
/fill 595 40 -602 606 40 -602 gold
/fill 595 40 -601 606 40 -601 gold
/fill 596 40 -600 606 40 -600 gold
/fill 596 40 -599 606 40 -599 gold
/fill 596 40 -598 606 40 -598 gold
/fill 596 40 -597 607 40 -597 gold
/fill 596 40 -596 607 40 -596 gold
/fill 597 40 -595 607 40 -595 gold
/fill 597 40 -594 607 40 -594 gold
/fill 597 40 -593 608 40 -593 gold
[…]

Das folgende Shellscript führt sie mit einem Abstand von circa einer Sekunde aus.

#! /bin/bash

sleep 5

while read LINE
do
    echo "$LINE";
    xdotool type "t"
    sleep 0.3
    xdotool type "$LINE"
    sleep 0.3
    xdotool key KP_Enter
    sleep 0.3
done < commands.txt

Shellscript ausführen, Minecraft-Fenster aktivieren, Kaffee trinken gehen.

  1. Fragt nicht, warum es jetzt genau diese Kommandos sind.

Bonner Linien erkennen

In Bonn fahren einige ÖPNV-Linien. Diese Linien haben auf der Karte recht interessante Formen. Was läge also näher, als daraus ein Spiel zu basteln?

Wir präsentieren: Linien in Bonn – ein Quiz.

Von Alfter bis zur Mondorfer Fähre: Die 605.

Von Alfter Duisdorf bis zur Mondorfer Fähre: Die 605.

Das aufwändigste war die Erstellung der Grafiken. Dabei half mir overpass turbo, mit dem ich die relevanten Strecken in Handarbeit abgerufen und als Geojson exportiert habe.1

Für die Umwandlung der Streckenangaben aus den json-Dateien in PNG-Grafiken konnte ich zum Glück ein altes Skript von mir recyceln, so dass ich da nicht komplett von vorn beginnen musste.

Arg viel mehr steckt eigentlich nicht dahinter. Viel Spaß beim spielen!

  1. Für solche Arbeiten hat man ja normalerweise SHKs…