Python xlwt-accès au contenu cellulaire existant, ajustement automatique de la largeur de la colonne

je suis en train d'essayer de créer un classeur Excel où je peux Auto-Définir, ou auto-ajuster les largeurs des colonnes avant de sauvegarder le classeur.

j'ai lu le Python-Excel tutoriel dans l'espoir de trouver certaines fonctions dans xlwt qui émulent xlrd (comme sheet_names(),cellname(row, col), cell_type,cell_value, et ainsi de suite...) Par exemple, supposons que j'ai ce qui suit:

from xlwt import Workbook    
wb = Workbook()
sh1 = wb.add_sheet('sheet1' , cell_overwrite_ok = True)    
sh2 = wb.get_sheet(0)

wb.get_sheet(0) est similaire au rb.sheet_by_index(0) fonction offerte dans xlrd, sauf que la première permet vous pouvez modifier le contenu (à condition que l'utilisateur a défini cell_overwrite_ok = True)

en supposant que xlwt offre les fonctions que je cherche, j'avais l'intention de passer en revue chaque feuille de travail à nouveau, mais cette fois en gardant la trace du contenu qui prend le plus d'espace pour une colonne particulière, et en réglant la largeur de la colonne sur cette base. Bien sûr, je peux également garder la trace de la largeur maximale pour une colonne spécifique pendant que j'écris à la feuille, mais je pense qu'il serait plus propre de définir les largeurs après toutes les données a déjà été écrit.

est ce que quelqu'un sait si je peux le faire? Dans la négative, que recommandez-vous de faire pour ajuster la largeur des colonnes?

25
demandé sur NorthCat 2011-08-03 19:33:39

6 réponses

je viens d'implémenter une classe wrapper qui suit les largeurs des articles quand vous les entrez. Il semble fonctionner assez bien.

import arial10

class FitSheetWrapper(object):
    """Try to fit columns to max size of any entry.
    To use, wrap this around a worksheet returned from the 
    workbook's add_sheet method, like follows:

        sheet = FitSheetWrapper(book.add_sheet(sheet_name))

    The worksheet interface remains the same: this is a drop-in wrapper
    for auto-sizing columns.
    """
    def __init__(self, sheet):
        self.sheet = sheet
        self.widths = dict()

    def write(self, r, c, label='', *args, **kwargs):
        self.sheet.write(r, c, label, *args, **kwargs)
        width = arial10.fitwidth(label)
        if width > self.widths.get(c, 0):
            self.widths[c] = width
            self.sheet.col(c).width = width

    def __getattr__(self, attr):
        return getattr(self.sheet, attr)

la magie est dans John Yeung arial10 module. Cela a de bonnes largeurs pour Arial 10, qui est la police Excel par défaut. Si vous voulez écrire des feuilles de travail en utilisant d'autres polices, vous devrez changer la fonction fitwidth, idéalement en prenant en compte le style argument passé à FitSheetWrapper.write.

45
répondu Kevin S 2015-09-30 14:04:57

si l'on n'est pas intéressé à utiliser une autre classe (FitSheetWrapper), alors cela peut être mis en œuvre en utilisant la méthode de la colonne feuille de travail.

work = xlwt.WorkBook()
sheet = work.add_sheet('Sheet1')
for row_index in range(0,max_row):
   for column_index in range(0,max_col) :
      cwidth = sheet.col(column_index).width
      if (len(column_data)*367) > cwidth:  
          sheet.col(column_index).width = (len(column_data)*367) #(Modify column width to match biggest data in that column)

      sheet.write(row_index,column_index,column_data,style)

la valeur par défaut de la largeur est de 2962 unités et excel la pointe à 8.11 unités. Par conséquent, je multiplie 367 à la longueur des données.

ceci est adapté de Kevins FitSheetWrapper.

5
répondu Sravan 2014-04-16 10:15:40

il n'y a pas d'installation automatique pour cela dans xlwt. Vous devez suivre le modèle général que vous décrivez, de garder la trace de la largeur maximale au moment où vous écrivez, et de définir la largeur de la colonne à la fin, parfois après que vous avez vu toutes les données, mais avant que vous avez enregistré le cahier d'exercices.

notez que ceci l'approche la plus propre et la plus efficace disponible pour traiter les fichiers Excel. Si votre notion de "après que les données ont déjà été écrites" signifie après vous avez déjà engagé les valeurs de la cellule ("écriture") mais avant de sauvegarder le classeur, alors la méthode décrite ci-dessus fait exactement cela. Si ce que vous voulez dire est après que vous avez déjà sauvegardé le classeur, vous voulez le lire à nouveau pour obtenir les largeurs max, et puis le sauvegarder à nouveau avec de nouvelles largeurs de colonne, ce sera beaucoup plus lent, et nécessitera l'utilisation à la fois xlwt et xlrd (et peut-être aussi xlutils). Notez également que lorsque vous utilisez le véritable Microsoft Excel, il n'y a pas de notion de "mise à jour" d'un fichier. Il peut sembler comme cela du point de vue de l'utilisateur, mais ce qui se passe dans les coulisses est que chaque fois que vous faites une sauvegarde, Excel souffle loin le fichier existant et écrit un tout nouveau à partir de zéro.

4
répondu John Y 2011-11-03 03:44:46

FitSheetWrapper devrait avoir une petite modification avec xlwt3 dans 3.3.4

ligne 19:

modifier:

width = arial10.fitwidth(label)

à:

width = int(arial10.fitwidth(label))  

raison: *Python\3.3.3\Lib\site-packages\xlwt3\biffrecords.py

1624 def __init__(self, first_col, last_col, width, xf_index, options):
1625        self._rec_data = pack('<6H', first_col, last_col, width, xf_index, options, 0)

la largeur doit être entière.

1
répondu phiree 2014-05-30 04:04:45

C'est peut-être un peu tard, mais j'ai créé une méthode qui fait cela pour l'ensemble feuille à la fois. C'est rapide et fait le travail. Le coussin supplémentaire param. n'est nécessaire que si vous pensez que le calcul 256 ne sera pas exact (si vous avez des champs de texte plus longs).

from xlrd import *
from xlwt import *

def autoAdjustColumns(workbook, path, writerSheet, writerSheet_index, extraCushion):
    readerSheet = open_workbook(path).sheet_by_index(writerSheet_index)
    for row in range(readerSheet.nrows):
            for column in range(readerSheet.ncols):
                    thisCell = readerSheet.cell(row, column)
                    neededWidth = int((1 + len(str(thisCell.value))) * 256) 
                    if writerSheet.col(column).width < neededWidth:
                            writerSheet.col(column).width = neededWidth + extraCushion
    workbook.save(path)
1
répondu Connor 2015-07-27 17:05:06

j'utilise cette méthode:

wb = Workbook()
ws = wb.add_sheet('Sheet1')
columnwidth = {}
row = 0
for rowdata in data:
    column = 0
    for colomndata in rowdata:
        if column in columnwidth:
            if len(colomndata) > columnwidth[column]:
                columnwidth[column] = len(colomndata)
        else:
            columnwidth[column] = len(colomndata)
        ws.write(row, column, colomndata, style0)
        column = column + 1
    row = row + 1
for column, widthvalue in columnwidth.items():
    ws.col(column).width = (widthvalue + 4) * 367
0
répondu lxd235 2017-01-03 15:37:10