web-dev-qa-db-fra.com

openpyxl - ajuste la taille de la colonne

J'ai le script suivant qui convertit un fichier CSV en un fichier XLSX, mais la taille de ma colonne est très étroite. Chaque fois, je dois les faire glisser avec la souris pour lire les données. Est-ce que quelqu'un sait comment définir la largeur de la colonne dans openpyxl?

Voici le code que j'utilise.

#!/usr/bin/python2.6
import csv
from openpyxl import Workbook
from openpyxl.cell import get_column_letter

f = open('users_info_cvs.txt', "rU")

csv.register_dialect('colons', delimiter=':')

reader = csv.reader(f, dialect='colons')

wb = Workbook()
dest_filename = r"account_info.xlsx"

ws = wb.worksheets[0]
ws.title = "Users Account Information"

for row_index, row in enumerate(reader):
    for column_index, cell in enumerate(row):
        column_letter = get_column_letter((column_index + 1))
        ws.cell('%s%s'%(column_letter, (row_index + 1))).value = cell

wb.save(filename = dest_filename)
48
Satish

Vous pouvez estimer (ou utiliser une police mono largeur) pour y parvenir. Supposons que les données sont un tableau imbriqué comme [['' a1 ',' a2 '], [' b1 ',' b2 ']]

Nous pouvons obtenir le maximum de caractères dans chaque colonne. Puis définissez la largeur à cela. La largeur correspond exactement à la largeur d'une police monospace (si vous ne modifiez pas au moins les autres styles). Même si vous utilisez une police à largeur variable, il s'agit d'une estimation décente. Cela ne fonctionnera pas avec des formules.

column_widths = []
for row in data:
    for i, cell in enumerate(row):
        if len(column_widths) > i:
            if len(cell) > column_widths[i]:
                column_widths[i] = len(cell)
        else:
            column_widths += [len(cell)]

for i, column_width in enumerate(column_widths):
    worksheet.column_dimensions[get_column_letter(i+1)].width = column_width

Un peu de bidouille mais vos rapports seront plus lisibles.

64
Bufke

Ma variante de la réponse de Bufke. Évite un peu de branchement avec le tableau et ignore les cellules/colonnes vides.

Maintenant corrigé pour les valeurs de cellules non-chaîne.

ws = your current worksheet
dims = {}
for row in ws.rows:
    for cell in row:
        if cell.value:
            dims[cell.column] = max((dims.get(cell.column, 0), len(str(cell.value))))    
for col, value in dims.items():
    ws.column_dimensions[col].width = value
32
velis

Encore plus de méthode Pythonic pour définir la largeur de toutes les colonnes qui fonctionne au moins dans openpyxl version 2.4.0:

for column_cells in worksheet.columns:
    length = max(len(as_text(cell.value)) for cell in column_cells)
    worksheet.column_dimensions[column_cells[0].column].width = length

La fonction as_text devrait être quelque chose qui convertit la valeur en une chaîne de longueur appropriée, comme pour Python 3:

def as_text(value):
    if value is None:
        return ""
    return str(value)
27
User3759685

J'ai un problème avec merged_cells et autosize ne fonctionne pas correctement, si vous avez le même problème, vous pouvez le résoudre avec le code suivant:

for col in worksheet.columns:
    max_length = 0
    column = col[0].column # Get the column name
    for cell in col:
        if cell.coordinate in worksheet.merged_cells: # not check merge_cells
            continue
        try: # Necessary to avoid error on empty cells
            if len(str(cell.value)) > max_length:
                max_length = len(cell.value)
        except:
            pass
    adjusted_width = (max_length + 2) * 1.2
    worksheet.column_dimensions[column].width = adjusted_width
6
Virako

Une légère amélioration de la réponse acceptée ci-dessus, que je pense être plus pythonique (demander pardon vaut mieux demander l'autorisation)

column_widths = []
for row in workSheet.iter_rows():
    for i, cell in enumerate(row):
        try:
            column_widths[i] = max(column_widths[i], len(cell.value))
        except IndexError:
            column_widths.append(len(cell.value))

for i, column_width in enumerate(column_widths):
    workSheet.column_dimensions[get_column_letter(i + 1)].width = column_width
3
shayst

Je devais changer la réponse ci-dessus @ User3759685 lorsque le fichier openpxyl était mis à jour. Je recevais une erreur. Eh bien, @phihag a également signalé cela dans les commentaires.

for column_cells in ws.columns:
    new_column_length = max(len(as_text(cell.value)) for cell in column_cells)
    new_column_letter = (openpyxl.utils.get_column_letter(column_cells[0].column))
    if new_column_length > 0:
        ws.column_dimensions[new_column_letter].width = new_column_length + 1
1
Monte Jones

Nous pouvons convertir les nombres en leurs valeurs ASCII) et les attribuer au paramètre column_dimension

import openpyxl as xl

work_book = xl.load_workbook('file_location')
sheet = work_book['Sheet1']
column_number = 2
column = str(chr(64 + column_number))
sheet.column_dimensions[column].width = 20
work_book.save('file_location')
1
Prashant Tiwari

Ceci est ma version faisant référence à l'extrait de code de @Virako

def adjust_column_width_from_col(ws, min_row, min_col, max_col):

        column_widths = []

        for i, col in \
                enumerate(
                    ws.iter_cols(min_col=min_col, max_col=max_col, min_row=min_row)
                ):

            for cell in col:
                value = cell.value
                if value is not None:

                    if isinstance(value, str) is False:
                        value = str(value)

                    try:
                        column_widths[i] = max(column_widths[i], len(value))
                    except IndexError:
                        column_widths.append(len(value))

        for i, width in enumerate(column_widths):

            col_name = get_column_letter(min_col + i)
            value = column_widths[i] + 2
            ws.column_dimensions[col_name].width = value

Et comment utiliser est comme suit,

adjust_column_width_from_col(ws, 1,1, ws.max_column)
1
alones

Toutes les réponses ci-dessus génèrent un problème: col [0] .column renvoie un nombre alors que worksheet.column_dimensions [column] n'accepte que les caractères tels que 'A', 'B', 'C' à la place de la colonne. J'ai modifié le code de @ Virako et cela fonctionne bien maintenant.

import re
import openpyxl
..
for col in _ws.columns:
    max_lenght = 0
    print(col[0])
    col_name = re.findall('\w\d', str(col[0]))
    col_name = col_name[0]
    col_name = re.findall('\w', str(col_name))[0]
    print(col_name)
    for cell in col:
        try:
            if len(str(cell.value)) > max_lenght:
                max_lenght = len(cell.value)
        except:
            pass
    adjusted_width = (max_lenght+2)
    _ws.column_dimensions[col_name].width = adjusted_width
1
Ssubrat Rrudra