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)
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.
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
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)
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
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
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
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')
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)
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