2013-07-30 4 views
10

Ich arbeite mit Pivot-tabelled XLSX-Dateien und schreibe ein Skript, um sie in eine neue Datei pro Registerkarte zu analysieren.openpyxl python3 - Formatierung ganze Zeilen ellicits seltsames Verhalten

Da openpexl standardmäßig keine Pivot-Tabellen unterstützt, muss ich etwas arbeiten, um den Pivot-Stil, der beim Kopieren verloren gegangen ist, wieder einzufügen.

Um dies zu tun bin ich durch jede Zeile und Spalte, Suche nach dem Wert Total in Spalte 0. Sobald gefunden, sollte die Zeile geändert werden, um alle bold=True.

Stattdessen erhalte ich unregelmäßiges Verhalten, das manchmal alle Zellen nach dem ersten None fett schreibt. Meine print('bolding totals') Nachricht zeigt, dass es jede Zeile/Zelle richtig bewertet. Bin ich knochenköpfig und vermassele vielleicht meine Gedanken an den Schleifen?

from openpyxl import Workbook 
from openpyxl import load_workbook 
from copy import deepcopy 

wb = load_workbook(filename=r'input.xlsx') 

# Print 1 
sheetlist = wb.get_sheet_names() 
print(sheetlist) 

for i in range(len(sheetlist)-1): 
    dest_filename = r''+sheetlist[i]+'.xlsx' 
    new_wb = Workbook() 
    ws = wb.get_sheet_by_name(sheetlist[i]) 
    new_wb.add_sheet(ws, 0) 

    for k in range(0, new_wb.worksheets[0].get_highest_row()): 
     print(new_wb.worksheets[0].cell(row=k, column=0).value) 
     # ignore empty cells 
     if new_wb.worksheets[0].cell(row=k, column=0).value is not None: 
      if 'Total' in new_wb.worksheets[0].cell(row=k, column=0).value: 
       for j in range(0, new_wb.worksheets[0].get_highest_column()): 
        print('bolding totals, '+str(k), str(j)) 
        new_wb.worksheets[0].cell(
         row=k, column=j).style.font.bold = True 
      elif 'Total' not in new_wb.worksheets[0].cell(row=k, column=0).value: 
       for j in range(0, new_wb.worksheets[0].get_highest_column()): 
        print('not bolding anything') 
        new_wb.worksheets[0].cell(
         row=k, column=j).style.font.bold = False 

    # remove the blank sheet created in new_wb by openpyxl 
    new_wb.remove_sheet(new_wb.get_sheet_by_name('Sheet')) 
    print(new_wb.get_sheet_names()) 
    new_wb.save(dest_filename) 
    break # set to break after one sheet for testing 

print('finished') 

An dieser Stelle ich vermuten, dass dies ein Fehler in der openpyxl Umgang mit Stilen ist. Ich habe einen weiteren sehr einfachen Schnitt gemacht und seltsames Verhalten bekommen.

Wenn wir ein einfaches Layout mit fett/nichtbold Zellen haben. Dann haben wir diese einfache Befehl ausführen eine Zelle zu ändern:

>>> new_wb.worksheets[0].cell(row=10,column=0).style.font.bold = False 

Der Ausgang ändert sich für die gesamte Spalte, nicht die Zelle allein.

+0

Hallo, Fehler in 'arbeiten openpyxl' mir nicht sehr schockierend sind. Ich hatte vorher Probleme damit. Es war einfacher für mich, die gesamte Anwendung neu zu schreiben, um Excel direkt zu verwenden, indem ich es über die COM-Ports steuerte, als "openpyxl" zu reparieren. Hier ist mein Post mit einer Antwort; hoffe es hilft: http://stackoverflow.com/questions/18145313/openpyxl-highlighting-multiple-cells-when-one-of-them-is-selected-up-closing-t –

+1

Ich stimme für das Schließen dieser Frage obwohl es gut geschrieben und interessant ist, weil: (a) es keine Antworten hat, akzeptiert oder nicht; (b) die Verbindungen zu tatsächlicher und gewünschter Ausgabe sind tot; c) das OP hat SO seit fast zwei Jahren nicht mehr besucht; (d) ein damit zusammenhängender openpyx-Fehler wurde wahrscheinlich inzwischen behoben; und (e) es erscheint immer noch als eine offene Frage, obwohl es jetzt tatsächlich nicht zu beantworten ist. –

+0

@AleksanderLidtke Ich erinnere mich nicht an einen Fehlerbericht darüber. Ihr Kommentar scheint zu implizieren, dass openpyx sehr fehlerhaft ist, was ich nicht für eine faire Darstellung halte. Natürlich ist die direkte Arbeit mit Excel großartig, wenn Sie können. Sie können auch xlwings betrachten, um dies zu tun. –

Antwort

7

Vor openpyxl 2.0 Zellenstile wurden zwischen Zellen geteilt: Dies war ein Holdover von der Implementierung mit Zeigern in der Quell-XML: zwei (oder mehr) Zellen würden beide Stil "1" verwenden. Eine Änderung dieses Stils für eine Zelle würde bedeuten, sie für alle Zellen zu ändern, was sich wie das hier beobachtete Verhalten anhört.

Seither gibt es verschiedene Änderungen in der Implementierung, aber es gibt keine Nebenwirkungen mehr, wenn der Stil für eine Zelle geändert wird. Eine wichtige Änderung besteht darin, dass Formatierungsobjekte wie Font direkt verfügbar sind und nicht in einem Stil eingebettet werden müssen.

Es gab noch einige andere Änderungen: Arbeitsblätter können nicht zwischen Arbeitsmappen kopiert werden, da sie von Daten abhängen, die in der übergeordneten Arbeitsmappe gespeichert sind.

Ohne die Original-Datei sicher zu sein, es ist schwierig, aber der folgende Code sollte mit openpyxl> = 2,2

from openpyxl import Workbook 
from openpyxl import load_workbook 

wb = load_workbook(filename='input.xlsx', read_only=True) 

for sheet in wb.sheetnames: 

    dest_filename = '{0}.xlsx'.format(sheet) 
    new_wb = Workbook() 
    del new_wb["Sheet"] 

    ws1 = wb[sheet] 
    ws2 = new_wb.create_sheet(sheet) 

    for row in ws1: 
     ws2.append([c.value for c in row]) 
     first = row[0] 
     if first.data_type == "s" and "Total" in first.value: 
      for idx in range(len(row)): 
       cell = ws2.cell(row=ws2.max_row, column=idx+1) 
       bolded = cell.font.copy(bold=True) 
       cell.font = bolded 

    new_wb.save(dest_filename) 
    print("saving {0}".format(dest_filename)) 

print('finished')