2017-11-16 1 views
1

Daten werden in der rechten unteren Ecke einer Zelle aufgefunden, anscheinend ignoriert Ausrichtung Einstellungen von xlsxwriter. A MWE:python xlsxwriter wird keine Daten ausrichten

import pandas 

df = pandas.DataFrame(
    { 
     "ints": [1, 2, 3] 
     , 'primes': [2, 3, 5] 
     , 'odds': [1, 3, 5] 
     , 'fechas': ['2017-04-07', '2017-05-09', '2017-11-30'] 
    } 
) 

df['fechas'] = pandas.to_datetime(df['fechas']).dt.date 

print(df) 

xlsx_writer = pandas.ExcelWriter(
    'test.xlsx' 
    , engine='xlsxwriter' 
    , date_format='mm/dd/yyyy' 
) 

df.to_excel(xlsx_writer, sheet_name='Sheet1', index=False) 
wb = xlsx_writer.book 
ws = xlsx_writer.sheets['Sheet1'] 


dollar_format = '_($* #,##0.00" "_);_($* (#,##0.0);_($* "-"??_);_(@_)' 
dollar_format_wb = wb.add_format({'num_format': dollar_format, 'valign': 'vcenter'}) 
centre_format_wb = wb.add_format({'align': 'center', 'valign': 'vcenter'}) 

ws.set_column('A:A', 25, centre_format_wb) 
ws.set_column('B:B', 20, centre_format_wb) 
ws.set_column('C:C', 15, centre_format_wb) 
ws.set_column('D:D', 10, dollar_format_wb) 

# The code below was included to generate the screenshot, but isn't 
# strictly necessary for the MWE 
shadedrow_format_wb = wb.add_format(
    { 
     'bg_color': '#EEEEEE' 
     , 'left': 1 
     , 'left_color': '#FFFFFF' 
    } 
) 

for r in range(0, 2 + df.shape[0]): 
    ws.set_row(r + 1, 45) 
    print(r) 
    if r % 2 == 0: 
     # a kludge as we can't change cell range formats after the fact without re-entering cell contents 
     ws.conditional_format('A{:}:D{:}'.format(r, r), {'type': 'no_errors', 'format': shadedrow_format_wb}) 
     print("\t", r) 

xlsx_writer.save() 

Spalten A, B und C sollten horizontal werden, und alle Zeilen mit Ausnahme der Header sollte Höhe 45, wobei alle Zellinhalte zentrierten vertikal zentriert.

excel screen shot

Alles funktioniert wie es sollte, mit Ausnahme der Datumsspalte. Gibt es einen guten Grund, dass dies nicht funktionieren sollte? Gibt es eine korrekte Methode, das Datum zentriert zu bekommen? Ist es ein Fehler? Gibt es einen Workaround?

Ich habe auch versucht, zuerst das Blatt zu formatieren und die df.to_excel() zuletzt, ohne Wirkung durchzuführen.

Vielen Dank!

+0

Entschuldigungen - ich vernachlässigt zu sagen, dass Änderungen für eine bessere Moll waren Verständnis (und den Titel genauer gemacht) – GoneAsync

Antwort

1

Ich habe ein Beispiel dafür geliefert, wie Sie Ihre gewünschte Datumsformatierung in einer .xlsx-Ausgabe mit Pandas erreichen können. Außerdem müsste das datetime-Modul hinzugefügt werden.

Als @jmcnamara erwähnt, denke ich, die beste und flexibelste Lösung wäre, xlsxwriter direkt zu verwenden.

Hier ist eine link to another SO answer, die einen weiteren Hintergrund zum Excel "serial date" -Format liefert und es von einem Datetime-Objekt in Python holt. Dies ist im Wesentlichen dasselbe wie das, was ich getan habe, um die Spalte in ein Excel-Datum zu konvertieren. Ich habe auch ein zusätzliches Format hinzugefügt (genannt "centre_date_format_wb").

Hier ist der vollständige Code mit meiner Ergänzungen/Änderungen:

import pandas 
import datetime 

df = pandas.DataFrame(
    { 
     "ints": [1, 2, 3] 
     , 'primes': [2, 3, 5] 
     , 'odds': [1, 3, 5] 
     , 'fechas': ['2017-04-07', '2017-05-09', '2017-11-30'] 
    } 
) 

df['fechas'] = pandas.to_datetime(df['fechas']).dt.date 


excel_start_date = datetime.date(1899, 12, 30) 
df['fechas'] = df['fechas'] - excel_start_date 
df.fechas = df.fechas.dt.days 

print(df) 

xlsx_writer = pandas.ExcelWriter(
    'test.xlsx' 
    , engine='xlsxwriter' 
) 

df.to_excel(xlsx_writer, sheet_name='Sheet1', index=False) 
wb = xlsx_writer.book 
ws = xlsx_writer.sheets['Sheet1'] 


dollar_format = '_($* #,##0.00" "_);_($* (#,##0.0);_($* "-"??_);_(@_)' 
dollar_format_wb = wb.add_format({'num_format': dollar_format, 'valign': 'vcenter'}) 
centre_format_wb = wb.add_format({'align': 'center', 'valign': 'vcenter'}) 
#additional format added below 
centre_date_format_wb = wb.add_format({'align': 'center', 'valign': 'vcenter', 'num_format' : 'mm/dd/yyyy' }) 

ws.set_column('A:A', 25, centre_date_format_wb) 
ws.set_column('B:B', 20, centre_format_wb) 
ws.set_column('C:C', 15, centre_format_wb) 
ws.set_column('D:D', 10, dollar_format_wb) 

# The code below was included to generate the screenshot, but isn't 
# strictly necessary for the MWE 
shadedrow_format_wb = wb.add_format(
    { 
     'bg_color': '#EEEEEE' 
     , 'left': 1 
     , 'left_color': '#FFFFFF' 
    } 
) 

for r in range(0, 2 + df.shape[0]): 
    ws.set_row(r + 1, 45) 
    print(r) 
    if r % 2 == 0: 
     # a kludge as we can't change cell range formats after the fact without re-entering cell contents 
     ws.conditional_format('A{:}:D{:}'.format(r, r), {'type': 'no_errors', 'format': shadedrow_format_wb}) 
     print("\t", r) 

xlsx_writer.save() 

und ein Bild des resultierenden Arbeitsblatt:

Solution image

+0

Schöne @ patrickjlong1! Vielen Dank! Excel-Basisdaten machen mir den Kopf - wissen Sie, ob das plattformübergreifend funktioniert? – GoneAsync

+0

@GoneSync, ich denke, das Beispiel sollte keine plattformübergreifenden Probleme haben. Es bleibt weg Verzeichnis/Ordner Pfade, so denke ich, dass es sicher sein sollte für Linux oder Windows. – patrickjlong1

+0

Excel Basisdaten machen meinen Kopf - ich war mehr besorgt über die Unterschiede zwischen Versionen und Plattformen in den Basisdaten - ich * denke * ältere Versionen von Excel waren um einen Tag wegen der absichtlichen Replikation eines Fehlers in Lotus 1- 2-3, und Mac benutzte stattdessen 1904 ... Ich habe das vielleicht falsch, aber das Chaos war etwas, das ich immer vermeiden wollte, indem ich mich auf Entwickler verließ, die mehr Zeit damit verbringen, darüber nachzudenken als ich. Ich habe das als Antwort akzeptiert, obwohl, wie du sagst @ jmcnamaras Vorschlag ein möglicherweise robusterer Fallback ist, wenn ich in Schwierigkeiten auf der Strecke laufe. Danke euch beiden!! – GoneAsync

1

Das Problem ist, dass Pandas ein Zellenformat für das Datum anwendet, und dies überschreibt das Spaltenformat.

Die einzige Möglichkeit zur Problemumgehung wäre die Iteration über den Datenrahmen und das direkte Schreiben in XlsxWriter unter Verwendung aller gewünschten Formate.

+0

Danke @jmcnamara - Ich nehme es mit Pandas auf und benutze deinen Vorschlag in der Zwischenzeit. – GoneAsync