2015-04-05 187 views
13

Ich möchte die Excel-Autofit-Funktion in Python xlsxwriter simulieren. Gemäß dieser URL wird nicht direkt unterstützt: http://xlsxwriter.readthedocs.io/worksheet.htmlAutofit-Spalte in xslxwriter simulieren

Allerdings soll es auf dem Blatt durch jede Zelle in einer Schleife ganz einfach sein und die maximale Größe für die Spalte bestimmt und nur worksheet.set_column (Zeile, Spalte verwenden , Breite), um die Breite einzustellen.

Die Komplikationen, die mich von nur dieses Schreiben hält, sind:

  1. Diese URL ist nicht festgelegt, was die Einheiten für das dritte Argument sind zu set_column.
  2. Ich kann keine Möglichkeit finden, die Breite des Elements zu messen, das ich in die Zelle einfügen möchte.
  3. xlsxwriter scheint keine Methode zum Zurücklesen einer bestimmten Zelle zu haben. Dies bedeutet, dass ich jede Zellenbreite verfolgen muss, während ich die Zelle schreibe. Es wäre besser, wenn ich einfach alle Zellen durchlaufen könnte, so könnte eine generische Routine geschrieben werden.
+1

eine Auto-Breite nicht so einfach ist, zu setzen Versuch. Glyphenbreiten hängen von der Schriftart ab. Und was, wenn Sie Gleichungen in eine Zelle schreiben? Dann können Sie nicht die Breite einer Zelle basierend auf dem, was Sie in es schreiben, sagen. Die Einheiten sind willkürlich, das ist richtig, aber es gibt eine tatsächliche Definition! Eine Einheit nähert die Breite eines Zeichens in der Standardschrift an. Siehe https://support.microsoft.com/en-us/kb/214123 –

+0

Verwandte Frage zu xlwt (der Gesamtansatz wäre für XlsxWriter der gleiche; obwohl Sie wahrscheinlich die Breiten für Calibri 11 anstelle von Arial 10 möchten) : http://stackoverflow.com/questions/6929115/python-xlwt-accessing-existing-cell-content-auto-adjust-column-width/23946840 –

Antwort

2

ich vor kurzem lief in das gleiche Problem, und das ist, was ich kam mit:

r = 0 
c = 0 
for x in list: 
    worksheet.set_column('{0}:{0}'.format(chr(c + ord('A'))), len(str(x)) + 2) 
    worksheet.write(r, c, x) 
    c += 1 

In meinem Beispiel r würde die Zeilennummer werden Sie ausgeben, c würde die Spaltennummer, die Sie sein Ausgabe an (beide 0 indiziert), und x wäre der Wert von list, die Sie in der Zelle sein wollen.

das '{0}:{0}'.format(chr(c + ord('A'))) Stück nimmt die Spaltennummer versehen und wandelt es in dem Brief Spalt von xlsxwriter akzeptiert, also wenn c = 0set_column würde 'A:A' sehen, wenn c = 1 dann wäre es 'B:B' zu sehen, und so weiter.

Das Stück len(str(x)) + 2 bestimmt die Länge der Zeichenfolge, die Sie ausgeben möchten, und fügt 2 hinzu, um sicherzustellen, dass die Excel-Zelle breit genug ist, da die Länge der Zeichenfolge nicht genau mit der Zellenbreite übereinstimmt. Vielleicht möchten Sie eher mit 2 oder möglicherweise mehr spielen, je nach Ihren Daten.

Die Einheiten, die xlsxwriter akzeptiert, sind etwas schwieriger zu erklären. Wenn Sie sich in Excel befinden und den Mauszeiger darüber bewegen, wo Sie die Spaltenbreite ändern können, sehen Sie Width: 8.43 (64 pixels). In diesem Beispiel ist die Einheit, die es akzeptiert, die 8.43, die ich denke, Zentimeter ist? Aber Excel bietet nicht einmal eine Einheit, zumindest nicht explizit.

Hinweis: Ich habe diese Antwort nur auf Excel-Dateien versucht, die 1 Zeile Daten enthalten. Wenn Sie mehrere Zeilen haben, müssen Sie einen Weg finden, um zu bestimmen, welche Zeile die 'längste' Information hat und nur diese Zeile auf diese Zeile anwenden. Aber wenn jede Spalte unabhängig von der Zeile etwa die gleiche Größe hat, sollte das für Sie gut funktionieren.

Viel Glück und ich hoffe, das hilft!

10

Als allgemeine Regel möchten Sie die Breite der Spalten ein wenig größer als die Größe der längsten Zeichenfolge in der Spalte. Die Breite von 1 Einheit der xlsxwriter-Spalten entspricht ungefähr der Breite eines Zeichens. So können Sie Autofit simulieren, indem Sie jede Spalte auf die maximale Anzahl von Zeichen in dieser Spalte einstellen.

Pro Beispiel verwende ich den Code unten, wenn ich mit pandas dataframes und xlsxwriter arbeite.

Es findet zuerst die maximale Breite des Index, der immer die linke Spalte für einen Pandas ist, um gerenderten Datenrahmen zu übertreffen. Dann gibt es das Maximum aller Werte und den Spaltennamen für jede der verbleibenden Spalten zurück, die sich von links nach rechts bewegen.

Es sollte nicht zu schwierig sein, diesen Code für die von Ihnen verwendeten Daten anzupassen.

def get_col_widths(dataframe): 
    # First we find the maximum length of the index column 
    idx_max = max([len(str(s)) for s in dataframe.index.values] + [len(str(dataframe.index.name))]) 
    # Then, we concatenate this to the max of the lengths of column name and its values for each column, left to right 
    return [idx_max] + [max([len(str(s)) for s in dataframe[col].values] + [len(col)]) for col in dataframe.columns] 

for i, width in enumerate(get_col_widths(dataframe)): 
    worksheet.set_column(i, i, width) 
+0

Was ist Metriken? –

+0

sorry metrics war der Name des Datenrahmens. aktualisierte Antwort, um Datenrahmen für Klarheit zu sagen. –

4

Ich stimme mit Cole Diamond überein. Ich musste etwas sehr ähnliches machen, es funktionierte gut für mich. wo self.columns meine Liste der Spalten ist

def set_column_width(self): 
    length_list = [len(x) for x in self.columns] 
    for i, width in enumerate(length_list): 
     self.worksheet.set_column(i, i, width) 
1

Es gibt eine andere Abhilfe Autofit zu simulieren, die ich Github site of xlsxwriter gefunden habe. Ich habe es modifiziert, um die ungefähre Größe der horizontalen Text (Spaltenbreite) oder 90 ° gedreht Text (Zeilenhöhe) zurückzukehren:

from PIL import ImageFont 

def get_cell_size(value, font_name, font_size, dimension="width"): 
    """ value: cell content 
     font_name: The name of the font in the target cell 
     font_size: The size of the font in the target cell """ 
    font = ImageFont.truetype(font_name, size=font_size) 
    (size, h) = font.getsize(str(value)) 
    if dimension == "height": 
     return size * 0.92 # fit value experimentally determined 
    return size * 0.13  # fit value experimentally determined 

Diese nicht fett gedruckten Text oder andere Formatelemente nicht adressieren, die den Text, beeinflussen könnten, Größe. Ansonsten klappt es ziemlich gut.

Um die Breite für Spalten für autofit zu finden:

def get_col_width(data, font_name, font_size, min_width=1): 
    """ Assume 'data' to be an iterable (rows) of iterables (columns/cells) 
    Also, every cell is assumed to have the same font and font size. 
    Returns a list with the autofit-width per column """ 
    colwidth = [min_width for col in data[0]] 
    for x, row in enumerate(data): 
     for y, value in enumerate(row): 
      colwidth[y] = max(colwidth[y], get_cell_size(value, font_name, font_size)) 
    return colwidth