Nachahmen der Kopierfunktion von Excel bzw. Libre Office mittels openpyxl (Kopieren samt Eigenschaften an neue Position)

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
AFoeee
User
Beiträge: 11
Registriert: Montag 22. Januar 2018, 07:00

Hallo,
gibt es eine Möglichkeit die Kopierfunktion von "Excel" bzw. "Libre Office" mittels openpyxl nachzuahmen?
Ich möchte einen gewissen Bereich angeben (z.B. "A1:E5") und diesen samt "border", "alignment", "number_format", "value", "merged_cells", ... Eigenschaften an eine beliebige Stelle (eines anderen Worksheets) kopieren können, wobei die verwendeten Formeln automatisch an die neue Position angepasst werden sollen. Die neuen Formeln sollen dabei auf Zellen innerhalb des Ziel-Worksheets verweisen und nicht auf die alten Zellen in der Vorlage.


Mein Projekt:
Ich lege für jeden Monat ein Workbook an. In diesem Workbook befinden sich Ertragsüberwachungstabellen, welche alle Werktage aufführen.
Da die verwendeten Tabellen sich zwar von Monat zu Monat unterscheiden, aber innerhalb eines Workbooks alle den gleichen Aufbau besitzen, möchte ich eine Vorlage erzeugen und diese in die einzelnen Worksheets hinein kopieren.

Das Kopieren des gesamten Worksheets stellt dabei nicht wirklich eine Lösung dar, weil ich ebenfalls die Position der Tabelle im Ziel-Worksheet angeben möchte.


Mein derzeitiger Code (wobei die Formeln nicht aktualisiert werden):

Code: Alles auswählen

import copy

# Der Tuple "topLeftCell" stellt die angenommene neue Position im Ziel-Worksheet dar. Er ist nullbasiert. (z.B. (0,0) oder (7,3))
# "templateSheet" ist die fertige Vorlage aus welcher kopiert werden soll.
# "worksheet" ist das Ziel-Worksheet

# Erstelle die selben "merged_cells" wie in der Vorlage an neuer Position
for cell_range in templateSheet.merged_cells.ranges:
        startCol, startRow, endCol, endRow = cell_range.bounds
        worksheet.merge_cells(start_column=topLeftCell[0] + startCol, 
                              start_row=topLeftCell[1] + startRow, 
                              end_column=topLeftCell[0] + endCol,
                              end_row=topLeftCell[1] + endRow)

colNumber = topLeftCell[0] + 1		# es wird 1 auf addiert, da topLeftCell nullbasiert ist.
rowNumber = topLeftCell[1] + 1		# es wird 1 auf addiert, da topLeftcell nullbasiert ist.

# Kopiere die Eigenschaften der alten Zellen in das Ziel-Worksheet
for row in templateSheet[templateSheet.dimensions]:
        tmpCol = colNumber			# setzt die Spalte wieder zurück auf den Ursprungswert
        for cell in row:
                ws_cell = worksheet.cell(column=tmpCol, row=rowNumber)
                
                ws_cell.alignment = copy.copy(cell.alignment)
                ws_cell.border = copy.copy(cell.border)
                ws_cell.font = copy.copy(cell.font)
                ws_cell.number_format = copy.copy(cell.number_format)
                ws_cell.value = cell.value
                
                tmpCol += 1			# rücke eine Spalte weiter
        rowNumber += 1			# springt in die nächste Zeile
Da das Kopieren von Bereichen eigentlich eine recht häufige Aufgabe ist, hätte ich angenommen, dass openpyxl dafür eine Funktion oder Methode zur Verfügung stellt. Leider konnte ich bis jetzt keine solche finden.

Ich verwende openpyxl Version 2.5.1 (und Python 3.5.2).

Mit freundlichen Grüßen
AFoeee
AFoeee
User
Beiträge: 11
Registriert: Montag 22. Januar 2018, 07:00

Hallo,

da openpyxl keinen allgemeinen Ansatz zu bieten scheint, mit dem ich das oben beschriebene Problem lösen kann, bin ich wie folgt vorgegangen:

ich habe eine Vorlage erstellt in der die Eigenschaften der jeweiligen Zellen gesetzt sind (border, alignment, number_format). Die Formeln werden zwar eingetragen, die Spalten und Zeilen aber durch Platzhalter ersetzt. Diese Platzhalter geben den Versatz zum "Nullpunkt" an.

Der Bereich wird dann wie oben beschrieben zellenweise kopiert, aber "cell.value" wird während des Kopierens modifiziert. Mit den Platzhaltern und dem neuen "Nullpunkt" werden die Positionen errechnet.

Mit freundlichen Grüßen
AFoeee
Benutzeravatar
pixewakb
User
Beiträge: 1411
Registriert: Sonntag 24. April 2011, 19:43

Danke für Deine Lösung!

Ich arbeite selbst auch mit openpyxl, allerdings nutze ich nur wenige Funktionen - mein Eindruck ist, dass hier im Forum wenige mit openpyxl arbeiten und somit wenig helfen können. M. E. ist Charlie Clark, einer der Maintainer der Bibliothek sehr aktiv auf stackoverflow:

https://stackoverflow.com/users/2385133/charlie-clark

Also für den Fall, dass du die Anfrage auch auf Englisch stellen kannst, dort sollte dir wahrscheinlich schnell geholfen werden können.

Schon mal frohe Ostern!
Antworten