Archive for the ‘Allgemein’ Category.

Erste Schritte mit Python und Qt 5

Hier ein einfaches Beispiel, wie man mit Python und Qt 5 Desktop-Anwendungen bauen kann. Ich persönlich nutze Anaconda3, hier ist alles bei, was man dafür braucht.

Im Qt Designer (unter Anaconda3\Library\bin) erstellen wir ein neues GUI auf Basis von „Main Window“ und setzen einen Button und ein Label rauf. Das ganze wird dann abgespeichert, anschließend erstellen wir den notwendigen Python-Code.

# -*- coding: utf-8 -*-
import sys
from PyQt5.QtWidgets import QMainWindow, QApplication
from PyQt5 import uic
 
Ui_MainWindow, QtBaseClass = uic.loadUiType('test.ui')
 
class MyApp(QMainWindow):
    def __init__(self):
        super(MyApp, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        self.ui.pushButton.clicked.connect(self.changeLabel)
 
    def changeLabel(self):
        self.ui.label.setText('Hello World')
 
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

Uwe

Uwe Ziegenhagen has been working with LaTeX for more than a decade. Besides TeX/LaTeX he likes to work with Python, Rasberry/Arduino and his digital camera.

More Posts - Website

LaTeX-Dateien vergleich mit latexdiff

latexdiff ist Bestandteil von TeX Live und erlaubt es, die Unterschiede zwischen zwei LaTeX-Dateien hervorzuheben. Hier ein Beispiel mit einem kurzen Textschnipsel aus der Wikipedia:

Das Original (Giraffe1.tex)

\documentclass[12pt,ngerman]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{csquotes}
\begin{document}
 
Die Giraffen (Giraffa) sind eine Gattung der Säugetiere aus der Ordnung der Paarhufer. Ursprünglich wurden ihr mit Giraffa camelopardalis und der Trivialbezeichnung \enquote{Giraffe} nur eine einzige Art zugewiesen. Molekulargenetische Untersuchungen aus dem Jahr 2016 zeigen jedoch, dass die Gattung wenigstens vier Arten mit sieben eigenständigen Populationen umfasst. Die Giraffen stellen die höchsten landlebenden Tiere der Welt. Zur Unterscheidung vom verwandten Okapi (sogenannte \enquote{Waldgiraffe}) werden sie auch als Steppengiraffen bezeichnet.
 
\end{document}

Eine Version mit leichten Änderungen (Giraffe2.tex)

\documentclass[12pt,ngerman]{scrartcl}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{csquotes}
\begin{document}
 
Die Giraffen (Giraffa) sind eine Gattung der Säugetiere aus der Ordnung der Paarhufer. Ursprünglich wurden ihr mit Giraffa camelopardalis und der Trivialbezeichnung \enquote{Giraffe} nur eine einzige Art zugewiesen. Untersuchungen aus dem Jahr 2016 zeigten jedoch, dass die Gattung wenigstens 4 Arten mit 7 eigenständigen Populationen umfasst. Die Giraffen stellen die höchsten landlebenden Tiere der Welt. Zur Unterscheidung vom verwandten Okapi (der sogenannten \enquote{Waldgiraffe}) werden sie auch als Steppengiraffen bezeichnet.
 
\end{document}

Auf der Kommandozeile ruft man jetzt auf latexdiff Giraffe1.tex Giraffe2.tex > Giraffediff.tex und übersetzt die neu erzeugte Datei nach PDF, das dann wie folgt aussieht:

Uwe

Uwe Ziegenhagen has been working with LaTeX for more than a decade. Besides TeX/LaTeX he likes to work with Python, Rasberry/Arduino and his digital camera.

More Posts - Website

Sichere (deutsche) Passwörter mit Python und xkcdpass

Menschen sind schlecht darin, sich gute lange Passwörter zu merken. Computer sind dafür prädestiniert, schlechte (weil kurze) Passwörter zu knacken. Randall Munroe hat das in einem recht bekannten XKCD Comic dargestellt.

Mit xkcdpass (Link) gibt es ein Python-Modul zur Erstellung von Passwörtern nach dem „xkcd-Schema“, das sich mittels pip install xkcdpass einfach installieren lässt.

Startet man xkcdpass ohne weitere Parameter, so spuckt es einfach eine Reihe englischer Wörter aus:

C:\Users\Uwe>xkcdpass
tackle tonsorial satisfied gecko fission decor

Um xkcdpass die Ausgabe deutscher Passwörter beizubringen, geht man wie folgt vor.

1) Mittels --help Parameter kommt man an die Liste aller Optionen, hier ist besonders -w für die Angabe der Wortdatei spannend.

C:\Users\Uwe>xkcdpass --help
usage: xkcdpass [-h] [-w WORDFILE] [--min MIN_LENGTH] [--max MAX_LENGTH]
                [-n NUM_WORDS] [-i] [-v VALID_CHARS] [-V] [-a ACROSTIC]
                [-c COUNT] [-d DELIM] [--allow-weak-rng]

optional arguments:
  -h, --help            show this help message and exit
  -w WORDFILE, --wordfile WORDFILE
                        Specify that the file WORDFILE contains the list of
                        valid words from which to generate passphrases.
  --min MIN_LENGTH      Generate passphrases containing at least MIN_LENGTH
                        words.
  --max MAX_LENGTH      Generate passphrases containing at most MAX_LENGTH
                        words.
  -n NUM_WORDS, --numwords NUM_WORDS
                        Generate passphrases containing exactly NUM_WORDS
                        words.
  -i, --interactive     Generate and output a passphrase, query the user to
                        accept it, and loop until one is accepted.
  -v VALID_CHARS, --valid-chars VALID_CHARS
                        Limit passphrases to only include words matching the
                        regex pattern VALID_CHARS (e.g. '[a-z]').
  -V, --verbose         Report various metrics for given options.
  -a ACROSTIC, --acrostic ACROSTIC
                        Generate passphrases with an acrostic matching
                        ACROSTIC.
  -c COUNT, --count COUNT
                        Generate COUNT passphrases.
  -d DELIM, --delimiter DELIM
                        Separate words within a passphrase with DELIM.
  --allow-weak-rng      Allow fallback to weak RNG if the system does not
                        support cryptographically secure RNG. Only use this if
                        you know what you are doing.

2) Man besorgt sich eine Datei mit dem deutschen Wortschatz, per Google bin ich auf die folgende Seite der Uni Leipzig gestoßen: http://wortschatz.uni-leipzig.de/html/wliste.html. Hier gibt es Listen für die häufigsten 100, 1000 und 10’000 Wörter der deutschen Sprache (sowie auch für französisch, englisch und niederländisch). Die Liste mit den 10’000 häufigsten Wörtern speichern wir ab.

Ein Hinweis noch zur sprachlichen Einschätzung der 10000 Wörter: Der Duden geht davon aus, dass ein durchschnittlicher Deutsch-Sprecher zwischen 12’000 und 16’000 Wörter spricht, aber rund 50’000 deutsche Worte versteht.

3) Mit der Wortschatzdatei auf der Festplatte können wir jetzt einfach wieder xkcdpass aufrufen und nutzen gleich noch -c 10 für die Erzeugung von 10 Zeilen mit jeweils sechs Passwörtern:

C:\Users\Uwe>xkcdpass -c 10 -w e:\top10000de.txt
Munition Alexander Bernhard Wissen Erstmals geraumer
wissen genießt wenigen Verlierer wunderbar Teufel
Wiesen Hartmut länger römische älter Stimme
irgendwie Monitor operative läuft Vertrieb Optionen
Stahl Brust Polizei Hoffnung Verlauf runden
Ärzte Mafia Dieter Pakistan Systems Areal
trieb hinweg Kanzlers unterlag zweimal zuviel
vollzogen Sparen zwölf verlieren Dutzende Länge
Infotyp beliebten gewisser Malerei gefunden Blätter
Peking äußerten fährt Einblick Interesse schwach

Uwe

Uwe Ziegenhagen has been working with LaTeX for more than a decade. Besides TeX/LaTeX he likes to work with Python, Rasberry/Arduino and his digital camera.

More Posts - Website

Example for pandas Merge

Here’s an example for the merge capabilities of pandas, which allow the user to work with DataFrames just like in SQL.

import pandas as pd
 
dfA = pd.DataFrame({'A': ['A0','A1','A2','A3'], 'Key': ['K0','K1','K2','K4']})
dfB = pd.DataFrame({'B': ['B0','B1','B2','B3'], 'Key': ['K0','K1','K2','K5']})
 
print('\nDaten\n')
print(dfA,'\n')
 
print(dfB,'\n')
 
dfInner = dfA.merge(dfB,how='inner',left_on='Key',right_on='Key')
 
print('Inner:\n', dfInner, '\n')
 
dfLeft = dfA.merge(dfB,how='left',left_on='Key',right_on='Key')
 
print('Left:\n', dfLeft, '\n')
 
dfRight = dfA.merge(dfB,how='right',left_on='Key',right_on='Key')
 
print('Right:\n', dfRight, '\n')
 
dfOuter = dfA.merge(dfB,how='outer',left_on='Key',right_on='Key')
 
print('Outer:\n', dfOuter, '\n')

Uwe

Uwe Ziegenhagen has been working with LaTeX for more than a decade. Besides TeX/LaTeX he likes to work with Python, Rasberry/Arduino and his digital camera.

More Posts - Website

Lineare Gleichungen lösen mit numpy

Hier ein kurzes Beispiel aus der numpy-Dokumentation, wie man mit Hilfe von numpy lineare Gleichungssysteme lösen kann:

Zu lösen sind folgende Gleichungen:

  • 3 * x0 + 1 * x1 = 9
  • 1 * x0 + 2 * x1 = 8

Die Koeffizienten kommen in die entsprechenden numpy-Arrays, dann ruft man linalg.solve auf:

import numpy as np
 
a = np.array([[3,1], [1,2]])
b = np.array([9,8])
x = np.linalg.solve(a, b)
print(x) # gibt [ 2.  3.]

pff

Den Plot habe ich mit LaTeX erstellt, siehe http://uweziegenhagen.de/?p=3516.

Uwe

Uwe Ziegenhagen has been working with LaTeX for more than a decade. Besides TeX/LaTeX he likes to work with Python, Rasberry/Arduino and his digital camera.

More Posts - Website

Plots mit pgfplots

Hier ein kleines Beispiel für pgfplots, das ich aus diversen TSX Beiträgen für einen Python Artikel zusammengebaut habe:

\documentclass[12pt,english]{standalone}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\pagestyle{empty}
 
\begin{document}
\begin{tikzpicture}
\begin{axis}[
    domain=0:9,
    axis lines = center,
    xlabel = {$x$},
    ylabel = {$y = f(x)$},
    height=8cm, width=11cm, grid=major,grid style={dashed, gray!30},
    xmin=-1, xmax=10, ymin=-1, ymax=7,xtick={1,2,...,10},ytick={1,2,...,6}]
 
\addplot[draw=red,domain=0:8]{-0.5*x+4};
\addplot[draw=blue,domain=1:3]{-3*x+9};
\end{axis}
\end{tikzpicture}
\end{document}

pff

Uwe

Uwe Ziegenhagen has been working with LaTeX for more than a decade. Besides TeX/LaTeX he likes to work with Python, Rasberry/Arduino and his digital camera.

More Posts - Website

Luftfeuchtigkeits-Ampel mit dem Arduino

Vor ein paar Tagen habe ich ein kleines Projekt mit dem Arduino abgeschlossen. Eine LED sollte — ähnlich wie eine Ampel — über die aktuelle Luftfeuchtigkeit Auskunft geben. Dazu habe ich einen DHT 22 Sensor und eine 5mm Full-RGB LED an einen USB-Boarduino angeschlossen.

Hier der Code, eine Fritzing-Zeichnung werde ich noch nachliefern.

//
// Basis: dht22_test.ino by Rob Tillaart
#include <dht.h>
dht DHT;
#define DHT22_PIN 2
 
void setup()
{
  Serial.begin(9600);
  pinMode(5, OUTPUT); // Blau
  pinMode(4, OUTPUT); // ROT
  pinMode(3, OUTPUT); // GRÜN
 
  digitalWrite(4, HIGH);
  delay(1000);
  digitalWrite(3, HIGH);
  delay(1000);
  digitalWrite(5, HIGH);
  delay(1000);
 
  digitalWrite(3, LOW);
  digitalWrite(4, LOW);
  digitalWrite(5, LOW);
}
 
void loop()
{
  int chk = DHT.read22(DHT22_PIN);
  float humidity = DHT.humidity;
  float temp = DHT.temperature;
 
  Serial.print("Humidity (%): ");
  Serial.println(humidity);
  Serial.print("Temperature (C): ");
  Serial.println(temp);
 
  if (humidity > 60) // ROT, wenn die L. zu hoch ist.
  {
    digitalWrite(4, HIGH);
    digitalWrite(3, LOW);
    digitalWrite(5, LOW);
  }
 
  if (humidity < 40) // BLAU, wenn L. zu niedrig ist.
  {
    digitalWrite(5, HIGH);
    digitalWrite(4, LOW);
    digitalWrite(3, LOW);
  }
 
  if ((humidity >= 40) && (humidity <= 60) ) // Zwischen 40 und 60 zeige GRÜN
  {
    digitalWrite(3, HIGH);
    digitalWrite(4, LOW);
    digitalWrite(5, LOW);
  }
  delay(5000);
}

Uwe

Uwe Ziegenhagen has been working with LaTeX for more than a decade. Besides TeX/LaTeX he likes to work with Python, Rasberry/Arduino and his digital camera.

More Posts - Website

Daten aggregieren mit pandas

I recently came across a „challenge“ where I needed to combine various rows. Each row was identified by Key1 and Key2 and had two interesting columns, Foo and Bar. For each Key1 there may be a few Key2, for each Key2 n Foo/Bar entries. While all Foos are distinct per Key1 and Key2 the Bar column may appear j times.

The goal was to get a list of unique Bar items for each Key1/Key2 combination.

Key1 Key2 Foo Bar
0 C1 T1 a1 rc-1
1 C1 T1 a2 rc-1
2 C1 T1 a3 rc-1
3 C1 T1 a4 rc-1
4 C2 T2 b1 rc-1
5 C2 T2 b2 rc-2
6 C3 T3 c1 rc-3
7 C4 T4 d1 rc-4
8 C4 T4 d2 rc-5
9 C4 T4 d3 rc-4

The following Python code nicely did the job, thanks to http://stackoverflow.com/questions/17841149/pandas-groupby-how-to-get-a-union-of-strings

# -*- coding: utf-8 -*-
import pandas as pd
 
def unique(liste):
    """ takes a list of elements, separated by comma and returns sorted string of unique items separated by comma """
    a = liste.split(',')
    b = sorted(set(a))
    return ','.join(b)
 
df = pd.read_excel('groupb_Beispiel.xlsx')
print(df)
 
grouped = df.groupby(['Key1','Key2'],as_index=False)['Bar'].agg(lambda col: ','.join(col))
grouped = pd.DataFrame(grouped)
 
grouped['Unique'] = grouped['Bar'].apply(unique)
 
print(grouped)
 
grouped.to_excel('result.xlsx')
Key1 Key2 Bar Unique
0 C1 T1 rc-1,rc-1,rc-1,rc-1 rc-1
1 C2 T2 rc-1,rc-2 rc-1,rc-2
2 C3 T3 rc-3 rc-3
3 C4 T4 rc-4,rc-5,rc-4 rc-4,rc-5

Uwe

Uwe Ziegenhagen has been working with LaTeX for more than a decade. Besides TeX/LaTeX he likes to work with Python, Rasberry/Arduino and his digital camera.

More Posts - Website

Zeilen kombinieren mit pandas

Vor einiger Zeit hatte ich eine Excel-Datei zu bearbeiten, in der in einer Spalte die Spaltennamen, in einer anderen die korrespondieren Werte standen. Immer drei Zeilen bildeten den eigentlichen Datensatz. Mit wenigen Zeilen Pandas und cleverer Adressierung der Ergebnis-Zelle.

Spaltenname Wert
ColA Andi
ColB Berni
ColC Cesar
ColA Dorian
ColB Ernest
ColC Frank

 

import pandas as pd
 
# Lade die Daten
daten = pd.read_excel('combine.xlsx')
# Erstelle leeren Dataframe mit den Spaltennamen aus den Excelzeilen 
verarbeitet = pd.DataFrame(columns=['ColA','ColB','ColC'])
 
# Iteriere über die Daten
for i, row in daten.iterrows():
    # ganzzahliges Teilen, um die Zeile zu bestimmen
    # in die die Zelle gehört, Spalte ergibt sich aus dem Wert in 'Spalte'
    verarbeitet.loc[i // 3,row['Spalte']] = row['Wert']
 
print(verarbeitet)
ColA ColB ColC
0 Andi Berni Cesar
1 Dorian Ernest Frank

Nachtrag: Stephan vom Kölner Data Science Meetup hat mir noch einen alternativen Weg gezeigt:

import pandas as pd
 
data = {'A': ["cola", "colb", "colc", "cola", "colb", "colc"], "B": [1, 2, 3, 4, 5, 6]}
data = pd.DataFrame(data)
gb = data.groupby('A')
res = pd.DataFrame()
for key in gb.groups:
    res[key] = gb.get_group(key)['B'].values.flatten()
 
print(res)

Uwe

Uwe Ziegenhagen has been working with LaTeX for more than a decade. Besides TeX/LaTeX he likes to work with Python, Rasberry/Arduino and his digital camera.

More Posts - Website

Spendenbescheinigungen erstellen mit LaTeX und pandas

Nach Buchungen auswerten mit Python Pandas hier der zweite Artikel zum Thema pandas.

Ausgangspunkt bilden die Formulare der Finanzdirektion, die ich in LaTeX umgesetzt habe; ihr findet sie unter https://github.com/UweZiegenhagen/spendenquittungen-mit-latex.

Wenn man dieses Formular mit entsprechenden Jinja2 Variablen anreichert (dazu später mehr), erhält man Sammelbestaetigung_Geldzuwendung (PDF) (TeX Code)

Die Aufgabe, die sich jetzt für das automatische Befüllen mittels pandas stellt, ist die folgende:

  1. Lies die Stammdaten ein und bereite sie auf
  2. Lies die Buchungen (aus Quicken 2015) ein und bereite sie auf
  3. Befüll das entsprechende LaTeX-Template
  4. Erzeuge die fertige PDF Datei

Hier der Quellcode nebst Erläuterung:

  • jinja2 nutzen wir als Template-Engine, os für die pdflatex-Aufrufe, codecs für ein wenig UTF8-Gewusel
  • cleanPLZ und prepareAddress sind einfache Hilfsfunktionen. Die erste reinigt die PLZ (pandas nimmt an, das hier Floats drinstehen), die zweite erzeugt den Adressstring für die Ausgabe
  • kardinal erzeugt das Zahlwort, siehe dazu den verlinkten Beitrag vom Finanzamt.
  • Richtig los geht es ab „##################### Prepare Stammdaten #####################“:
    • Ich lade die Stammdaten in einen Dataframe und ersetzte fehlende Werte durch “
    • Die PLZ wird bereinigt (geht sicher auch einfacher), ehemalige Mitglieder (mit Status ‚E‘) werden entfernt
    • Die Buchungen werden geladen, fehlende Werte durch 0 bzw. “ ersetzt.
    • Relevant sind nur Buchungstypen wie Mitgliedsbeitrag und Aufnahmegebühr, alles andere wird entfernt.
    • Die Jinja2 Komponente wird konfiguriert
    • Für jeden Stammdatensatz werden die Stammdaten aufbereitet und die Buchungen eingesammelt.
    • Ein wenig Python/pandas Magie bereitet die daten auf und schreibt alles in das Template
    • Dieses Template wird dann in eine TeX Datei geschrieben und nach PDF übersetzt.

Hier der Link zur Zip-Datei mit allen benötigten Dateien: AlleDateien

import pandas as pd # pandas selbst
 
import jinja2
import os
import codecs
 
def cleanPLZ(stringToClean):
    return stringToClean.replace('.0','')
 
# Eine Funktion, die die Adresse vorbereitet
# keine überflüssigen Leerzeichen, wenn Feld nicht gefüllt ist
def prepareAddress(id, vorname, name, strasse, plz, ort):
    address = '' # + str(id) + ': '
    if len(vorname)==0:
        address = address + name
    else:
        address = address + vorname + ' ' + name
    if len(strasse)>0:
        address = address + ", " + strasse    
    if len(plz)>0:
        address = address + ", " + plz + ' ' + ort
    return address
 
# Zerlege die Gesamtsumme in einzelne Bestandteile, um Zahlwort auszugeben
# Siehe http://www.steuer-schutzbrief.de/fileadmin/downloads/BMF-Schreiben/BMF-Schreiben-Zuwendungsbestaetigung-2012-08-30.pdf
def kardinal(summenstring,separator,indicator):
	zahlen = {"1" : "Eins", "2":"Zwei", "3":"Drei", "4":"Vier","5":"Fünf","6":"Sechs","7":"Sieben","8":"Acht","9":"Neun","0":"Null"}
	zahlwort = ''
	zahl = summenstring.split(',')[0]
	for i in zahl:
		zahlwort = zahlwort + zahlen[i]+ separator
	return indicator + separator + zahlwort + indicator
 
# Diverse Konfigurationsvariablen
# http://chrisalbon.com/python/pandas_list_unique_values_in_column.html
# Set ipython's max row display
pd.set_option('display.max_row', 10000)
# Set iPython's max column width to 50
pd.set_option('display.max_columns', 50)
# A set number format to 2 digits
pd.set_option('display.float_format', lambda x: '%.2f' % x)
# http://stackoverflow.com/questions/20625582/how-to-deal-with-this-pandas-warning
# komische Fehlermeldung beim Drop von Spalten loswerden
pd.options.mode.chained_assignment = None  # default='warn'
 
##################### Prepare Stammdaten ##################### 
# lade Daten
stammdaten = pd.read_excel('Stammdaten.xlsx', 'Tabelle1')
 
# Remove NaN values by " for strings
stammdaten['Vorname'].fillna(value='',inplace=True)
stammdaten['Name'].fillna(value='',inplace=True)
stammdaten['Adresszusatz'].fillna(value='',inplace=True)
stammdaten['Strasse'].fillna(value='',inplace=True)
stammdaten['PLZ'].fillna(value='',inplace=True)
stammdaten['Ort'].fillna(value='',inplace=True)
stammdaten['eMail'].fillna(value='',inplace=True)
stammdaten['Mitgliedsart'].fillna(value='',inplace=True)
 
# convert PLZ to string
# apply str function first, then run cleanPLZ on the string
stammdaten['PLZ']= stammdaten.PLZ.apply(str)
stammdaten['PLZ']= stammdaten.PLZ.apply(cleanPLZ)
 
# entferne ehemalige Mitglieder
stammdaten  = stammdaten[stammdaten.Mitgliedsart != 'E']
 
################################ Prepare Buchungen
# lade die Buchungen
buchungen = pd.read_excel('Buchungen.xlsx', 'Tabelle1')
buchungen[['Klasse']] = buchungen[['Klasse']].astype(str)
buchungen[['Betrag']] = buchungen[['Betrag']].astype(float)
 
# Change format of 'Buchungstag' to datetime
buchungen['Buchungstag'] = pd.to_datetime(buchungen['Buchungstag'],dayfirst=True)
 
# Remove NaN values by " for strings or 0 for numbers 
buchungen['Vorgang'].fillna(value=0,inplace=True)
buchungen['Empfänger'].fillna(value='',inplace=True)
buchungen['Verwendungszweck'].fillna(value='',inplace=True)
buchungen['Kategorie'].fillna(value='',inplace=True)
buchungen['Klasse'].fillna(value='',inplace=True)
buchungen['Relevant']=True
buchungen.Kategorie.str.match('^Aufnahmegebühr|Zweckspende|Mitgliedsbeitrag|Spende$')
 
# entferne irrelevante Buchungen
buchungen = buchungen[buchungen.Relevant != False]
 
# http://stackoverflow.com/questions/20937538/how-to-display-pandas-dataframe-using-a-format-string-for-columns
#pd.options.display.float_format = '{:,.2f} EUR'.format
 
class CommaFloatFormatter:
    def __mod__(self, x):
        return str(x).replace('.',',')
 
latex_jinja_env = jinja2.Environment(
    block_start_string = '\BLOCK{',
    block_end_string = '}',
    variable_start_string = '\VAR{',
    variable_end_string = '}',
    comment_start_string = '\#{',
    comment_end_string = '}',
    line_statement_prefix = '%-',
    line_comment_prefix = '%#',
    trim_blocks = True,
    autoescape = False,
    loader = jinja2.FileSystemLoader(os.path.abspath('.'))
)
 
# Laden des Templates aus einer Datei
template = latex_jinja_env.get_template('Sammelbestaetigung_Geldzuwendung.tex')
 
for index, row in stammdaten.iterrows():
    print("ID:",row["ID"])
    address = prepareAddress(row["ID"],row['Vorname'],row['Name'],row['Strasse'],row['PLZ'],row['Ort'])
    print(address)
    beitraege = buchungen[buchungen.Klasse.str.contains('^' +  str(row["ID"]) + '$')]
    beitraege.drop('Klasse',axis=1,inplace=True)
    beitraege.drop('Verwendungszweck',axis=1,inplace=True)
    beitraege.drop('Relevant',axis=1,inplace=True)
    beitraege.drop('Empfänger',axis=1,inplace=True)
    beitraege.drop('Konto',axis=1,inplace=True)
    beitraege.drop('Vorgang',axis=1,inplace=True)
    gesamtsumme = beitraege.sum()[0]
 
    beitraege['Buchungstag'] = beitraege['Buchungstag'].apply(lambda x: x.strftime('%d-%m-%Y'))
    texbuchungen = beitraege.applymap(lambda x: str(x).replace('.',',0')).to_latex(index=False)    
    texbuchungen = beitraege.to_latex(index=False)    
    summe = str(gesamtsumme).replace('.',',0') + ' EUR'
    # kardinal(summe,'-','xxx')
    dokument = template.render(Spender=address, ID=row['ID'],Summe=summe,kardinal=kardinal(summe,'-','xxx'),Buchungen=texbuchungen)
    with codecs.open(''+str(row['ID']) + ".tex", "w","utf-8") as letter:
        letter.write(dokument);
        letter.close();
        os.system("pdflatex -interaction=batchmode " + str(row['ID']) + ".tex")
 
os.system("del *.log")
os.system("del *.aux")

Uwe

Uwe Ziegenhagen has been working with LaTeX for more than a decade. Besides TeX/LaTeX he likes to work with Python, Rasberry/Arduino and his digital camera.

More Posts - Website