Archive for the ‘Programmierung’ Category.

Excel-Dateien schreiben mit Openpyxl: (Bedingte) Formatierung

This entry is part 6 of 6 in the series Openpyxl

Mit Openpyxl lassen sich auch Zellformatierungen und bedingte Formatierungen setzen. Das folgende Beispiel formatiert die ersten beiden Spalten grün, wenn der Zellwert „1“ beträgt und rot für alle anderen Inhalte. Die dritte Spalte wird mit blauem Hintergrund formatiert, hier jedoch ohne Bedingung.

import pandas as pd
import numpy as np
from openpyxl import Workbook
from openpyxl.utils.cell import get_column_letter
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.worksheet.table import Table, TableStyleInfo
 
from openpyxl.styles import Color, PatternFill, Font, Border
from openpyxl.formatting.rule import ColorScaleRule, CellIsRule, FormulaRule, Rule
 
 
dataframe = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c'])
rows = dataframe_to_rows(dataframe, index=False, header=True)
 
wb = Workbook()
ws = wb.active
 
for r_idx, row in enumerate(rows, 1):
    for c_idx, value in enumerate(row, 1):
        ws.cell(row=r_idx, column=c_idx, value=value)
 
# Set column widths based on title width or fixed number
widths = {}
for column in ws.columns:
    if column[0].value is None: # no column header => Fixed with
        widths[column[0].column] = 10.5
    else: # if column header is present => min width resp. maximum
        widths[column[0].column] = max(len(str(column[0].value)) * 1.45, 10.5)
 
ws.column_dimensions[get_column_letter(column[0].column)].width = widths[column[0].column]
 
# Insert formatted table from A1 to max column/max row
tab = Table(displayName="MeineTabelle", ref='A1:' + get_column_letter(ws.max_column) + str(ws.max_row))
style = TableStyleInfo(name="TableStyleLight9", showFirstColumn=False,
                       showLastColumn=False, showRowStripes=True, showColumnStripes=True)
tab.tableStyleInfo = style
ws.add_table(tab)
 
# conditional formatting
redFill = PatternFill(start_color='EE1111',end_color='EE1111',fill_type='solid')
greenFill = PatternFill(start_color='EE1111',end_color='11EE11',fill_type='solid')
ws.conditional_formatting.add('A2:B'+str(ws.max_row),CellIsRule(operator='equal', formula=[1], stopIfTrue=True, fill=greenFill))
ws.conditional_formatting.add('A2:B'+str(ws.max_row),CellIsRule(operator='notEqual', formula=[1], stopIfTrue=True, fill=redFill))
 
lightbluefill = PatternFill(start_color='CCCCFF',end_color='CCCCFF',fill_type='solid')
 
for rowNum in range(2, ws.max_row + 1):
    ws.cell(row=rowNum, column=3).fill = lightbluefill
 
wb.save('07.xlsx')
wb.close()

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Excel-Dateien schreiben mit Openpyxl: Kalkulationstabelle erstellen

This entry is part 5 of 6 in the series Openpyxl

Mit Openpyxl lassen sich auch einfach Excel-Daten in Kalkulationstabellen umwandeln, die eine ansprechende Formatierung, Unterstützung bei Formeln und Filter mitbringen. Im folgenden Beispiel nutzen wir noch die Hilfsfunktion get_column_letter(ws.max_column) aus dem utils.cell Modul, um den Excel-Spaltenname für die entsprechenden Spalten zu bestimmen.

import pandas as pd
import numpy as np
from openpyxl import Workbook
from openpyxl.utils.cell import get_column_letter
from openpyxl.utils.dataframe import dataframe_to_rows
from openpyxl.worksheet.table import Table, TableStyleInfo
 
 
dataframe = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c'])
rows = dataframe_to_rows(dataframe, index=False, header=True)
 
wb = Workbook()
ws = wb.active
 
for r_idx, row in enumerate(rows, 1):
    for c_idx, value in enumerate(row, 1):
        ws.cell(row=r_idx, column=c_idx, value=value)
 
# Set column widths based on title width or fixed number
widths = {}
for column in ws.columns:
    if column[0].value is None: # no column header => Fixed with
        widths[column[0].column] = 10.5
    else: # if column header is present => min width resp. maximum
        widths[column[0].column] = max(len(str(column[0].value)) * 1.45, 10.5)
 
ws.column_dimensions[get_column_letter(column[0].column)].width = widths[column[0].column]
 
# Insert formatted table from A1 to max column/max row
tab = Table(displayName="MeineTabelle", ref='A1:' + get_column_letter(ws.max_column) + str(ws.max_row))
style = TableStyleInfo(name="TableStyleLight9", showFirstColumn=False,
                       showLastColumn=False, showRowStripes=True, showColumnStripes=True)
tab.tableStyleInfo = style
ws.add_table(tab)
 
wb.save('05.xlsx')
wb.close()

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Excel-Dateien schreiben mit Openpyxl: Spaltenbreiten errechnen

This entry is part 4 of 6 in the series Openpyxl

Wir im letzten Teil erwähnt, lassen sich die Spaltenbreiten beim Export nach Excel auch errechnen. Dazu dient der Schnipsel von stackoverflow im folgenden Code. Ich habe den Code noch so abgewandelt, dass — wenn eine Spaltenüberschrift vorhanden ist — das Maximum aus dem Produkt der errechneten Breite und einem händisch festgelegten Faktor und einer fixen Zahl genutzt wird.

import pandas as pd
import numpy as np
from openpyxl import Workbook
from openpyxl.utils.dataframe import dataframe_to_rows
 
dataframe = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c'])
rows = dataframe_to_rows(dataframe, index=False, header=True)
 
wb = Workbook()
ws = wb.active
 
for r_idx, row in enumerate(rows, 1):
    for c_idx, value in enumerate(row, 1):
        ws.cell(row=r_idx, column=c_idx, value=value)
 
# Set column widths based on title width or fixed number
widths = {}
for column in ws.columns:
    if column[0].value is None: # no column header => Fixed with
        widths[column[0].column] = 10.5
    else: # if column header is present => min width resp. maximum
        widths[column[0].column] = max(len(str(column[0].value)) * 1.45, 10.5)
 
ws.column_dimensions[get_column_letter(column[0].column)].width = widths[column[0].column]
 
wb.save('04.xlsx')
wb.close()

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Excel-Dateien schreiben mit Openpyxl: Spaltenbreiten manuell setzen

This entry is part 3 of 6 in the series Openpyxl

Mit openpyxl lassen sich auch die Spaltenbreiten für einzelne Spalten explizit festlegen. Dazu liefert das worksheet Objekt die Eigenschaft column_dimensions mit, die man einfach setzen kann. Dieses manuelle Setzen kann man auch weglassen, wenn man die Spaltenbreite errechnen lässt, dazu mehr im nächsten Teil.

import pandas as pd
import numpy as np
from openpyxl import Workbook
from openpyxl.utils.dataframe import dataframe_to_rows
 
dataframe = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c'])
rows = dataframe_to_rows(dataframe, index=False, header=True)
 
wb = Workbook()
ws = wb.active
 
for r_idx, row in enumerate(rows, 1):
    for c_idx, value in enumerate(row, 1):
        ws.cell(row=r_idx, column=c_idx, value=value)
 
ws.column_dimensions['A'].width = 5
ws.column_dimensions['B'].width = 10
ws.column_dimensions['C'].width = 15
 
wb.save('03.xlsx')
wb.close()

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Excel-Dateien schreiben mit Openpyxl: Pandas Dataframes exportieren

This entry is part 2 of 6 in the series Openpyxl

Wichtiger als das manuelle Schreiben von Excel-Dateien ist für mich das Umwandeln von pandas Dataframes in Excel-Dateien.

Hier das passende Beispiel dazu, wie man einen Dataframe in eine Excel-Datei exportiert.

import pandas as pd
import numpy as np
from openpyxl import Workbook
from openpyxl.utils.dataframe import dataframe_to_rows
 
dataframe = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c'])
rows = dataframe_to_rows(dataframe, index=False, header=True)
 
wb = Workbook()
ws = wb.active
 
for r_idx, row in enumerate(rows, 1):
    for c_idx, value in enumerate(row, 1):
        ws.cell(row=r_idx, column=c_idx, value=value)
 
wb.save('02.xlsx')
wb.close()

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Formatierte Excel-Dateien schreiben mit Openpyxl: „Hello World“ Beispiel

This entry is part 1 of 6 in the series Openpyxl

Üblicherweise exportiere ich meine pandas Dataframes mit der df.to_excel() Funktion. Diese hat leider den Nachteil, dass sie keine Formatierungen im Excel-Dokument unterstützt. Mit der Openpyxl Bibliothek gibt es genau diese Unterstützung. In dieser Post-Reihe beschreibe ich die wesentlichen Funktionen, die man zum Erzeugen formatierter Excel-Dateien benötigt.

Hier das obligatorische „Hello World“ Beispiel, das in die Zelle A1 einer Excel-Datei „Hallo Welt“ schreibt.

from openpyxl import Workbook
 
wb = Workbook()
ws = wb.active
ws['A1'] = 'Hallo Welt'
 
 
wb.save('01.xlsx')
wb.close()

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Excel Sylk Dateien parsen mit Python

Vor ein paar Wochen hatte ich das erste Mal mit Microsoft Sylk Dateien zu tun. SLK ist ein Microsoft Format, das von Excel gelesen werden kann, mehr dazu im entsprechenden Wikipedia-Artikel. Ein Vorteil dieses Formats ist es, dass auch gewisse Formatierungen und verbundene Zellen unterstützt werden. Leider gibt es keine offizielle API dafür, das Format unterstützt anscheinend auch nur Windows-Encoding.

In meinem konkreten Fall sah der Input so aus:

ID;PWXL;N;E
P;PGeneral
P;P0
P;P0.00
P;P0.000
P;P0.0000
P;P0.00000
P;P0.000000
P;Pdd.mm.yyyy
C;Y1;X1;K"Inhalt der Zelle A1"
C;Y1;X2;K"Inhalt der Zelle B1"
C;Y2;X1;K"Inhalt der Zelle A2"
C;Y2;X2;K"Inhalt der Zelle B2"
E

In den ersten Zeilen standen irgendwelche Format-Anweisungen, die mich glücklicherweise nicht interessieren mussten. Mir waren nur die Zeilen wichtig, die mit „C“ begannen.

Das folgende Python-Programm habe ich dann genutzt, um die Inhalte zu extrahieren.

import pandas as pd
 
 
def get_sylk_dimension(file):
        """
        Suche die maximale Zeile und Spalte mit Inhalt
        das ist die letzte Zeile mit einem 'C' am Anfang
        gib Tupel aus X und Y-Koordinate zurück
        """
 
        with open(file, 'r', encoding="latin-1") as input:
            for line in input:
                if line[0] in ('E', 'F', 'I','K', 'P'):
                    pass # nicht verarbeiten
                else:
                    contentline = line
                    contentlist = contentline.split(';')
            return int(contentlist[2][1:]), int(contentlist[1][1:])
 
 
def sylk2df(file):
    """
        Wandelt MS SYLK Datei in DataFrame um
    """
 
    x, y = get_sylk_dimension(file)
    df = pd.DataFrame(index=range(y),columns=range(x))
 
    with open(file, 'r', encoding="latin-1") as input:
        for line in input:
            # filtere non-C Zellen raus
            if line[0] in ('E', 'F', 'I','K', 'P'):
                pass
            else:
                columns = line.split(';')
 
                # Erstelle die Koordinaten
                columns[1] = int(columns[1].lstrip('Y'))
                columns[2] = int(columns[2].lstrip('X'))
 
                # bereinige den eigentlichen Inhalt
                columns[3] = columns[3].lstrip('K')
                columns[3] = columns[3].strip().replace('"','')
                columns[3] = columns[3].strip().replace('\n','')
 
                # trage die Inhalte ein
                df.at[columns[1]-1, columns[2]-1] = columns[3]
    return df
 
 
x = sylk2df('test.slk')
print(x)

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Test-Driven Design mit Python

Am 12.06.2019 habe ich einen kurzen Vortrag zum Thema TDD (Test-Driven Design) bei der PyDDF in Düsseldorf gehalten. Hier die Folien.

PDF

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Python-Skripte per Drag & Drop triggern

Hier ein Beispiel, wie man per Drag & Drop Python-Skripte ausführen kann.

In eine entsprechende Batch-Datei kommt der folgende Aufruf

C:\WinPython-32bit-3.3.5.5\python-3.3.5\python.exe dragdrop.py %1 > error.log 2>&1

In die dragdrop.py kommt dann der eigentliche Python-Code, hier wird die „gedroppte“ Excel-Datei in CSV umgewandelt.

import sys
import os
import pandas as pd

droppedFile = sys.argv[1]
filename = os.path.splitext(droppedFile)[0]

df = pd.read_excel(droppedFile, skiprows=[0,1,2,3])
df.to_csv(filename +'.csv', sep=';', index=False)

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website

Python: Code-Rahmen für Auswertungen mit pandas

Für das „Rahmenwerk“ rund um eine Datenauswertung nutze ich immer den selben Code, der a) die Auswertung von Kommandozeilenparametern b) Zeitstempel und c) das Logging übernimmt. Geloggt wird auf STDOUT und in eine Datei.

import pandas as pd # pandas
import argparse # Kommandozeilenargumente
import logging # Logging
import sys # für das Logging
import time # für den Zeitstempel

# Zeitstempel
timestr = time.strftime('%Y%m%d') # '%Y%m%d-%H%M%S'

# Logger in Datei und auf die Konsole
logger = logging.getLogger("Logfile.log")
logger.propagate = False
logger.setLevel(logging.DEBUG)
 
fileHandler = logging.FileHandler(logger.name + '_' + timestr + ".log",mode='w')
fileHandler_format = logging.Formatter('%(asctime)s_%(levelname)s_%(message)s',datefmt='%H:%M:%S')
fileHandler.setFormatter(fileHandler_format)

consoleHandler = logging.StreamHandler(sys.stdout)
#formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
consoleHandler.setFormatter(fileHandler_format)

if logger.handlers:
    for handler in logger.handlers:
        logger.removeHandler(handler)

logger.addHandler(fileHandler)
logger.addHandler(consoleHandler)

# Zum Auswerten der Kommandozeilenparameter (siehe Aufruf aus Excel)
# Definiere Parameter
parser = argparse.ArgumentParser("Was bin ich")
parser.add_argument('-c','--currentdate',dest='currentdate')
parser.add_argument('-l','--lastdate',dest='lastdate')
parser.add_argument('-o','--outputfile',dest='outputpath')

# verarbeite Kommandozeilenargumente

logger.info('Verarbeite die Kommandozeilenargumente')
args = parser.parse_args()

# no more "A value is trying to be set on a copy of a slice from a DF" warning
pd.options.mode.chained_assignment = None

print('args.currentdate', args.currentdate)
print('args.lastdate', args.lastdate)
print('args.outputpath', args.outputpath)

logging.shutdown()

Uwe

Uwe Ziegenhagen mag LaTeX und Python, auch gern in Kombination. Hat Dir dieser Beitrag geholfen und möchtest Du Dich dafür bedanken? Dann unterstütze doch vielleicht die Dingfabrik Köln e.V. mit einem kleinen Beitrag. Details zur Bezahlung findest Du unter Spenden für die Dingfabrik.

More Posts - Website