recorrer - Python xlwt: accede al contenido de la celda existente, ajusta automáticamente el ancho de la columna
xlrd python ejemplos (6)
Acabo de implementar una clase de contenedor que rastrea el ancho de los elementos a medida que los ingresas. Parece funcionar bastante 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)
Toda la magia está en el módulo arial10
John Yeung . Esto tiene buenos anchos para Arial 10, que es la fuente predeterminada de Excel. Si desea escribir hojas de trabajo con otras fuentes, deberá cambiar la función fitwidth, idealmente teniendo en cuenta el argumento de style
pasado a FitSheetWrapper.write
.
Estoy tratando de crear un libro de Excel donde pueda configurarlo automáticamente o ajustar automáticamente el ancho de las columnas antes de guardar el libro.
He estado leyendo el tutorial de Python-Excel con la esperanza de encontrar algunas funciones en xlwt que emulen a las de xlrd (como sheet_names()
, cellname(row, col)
, cell_type
, cell_value
, etc.) Por ejemplo, supongamos Tengo los siguientes
from xlwt import Workbook
wb = Workbook()
sh1 = wb.add_sheet(''sheet1'' , cell_overwrite_ok = True)
sh2 = wb.get_sheet(0)
wb.get_sheet(0)
es similar a la función rb.sheet_by_index(0)
ofrecida en xlrd, excepto que la primera le permite modificar el contenido (siempre que el usuario haya configurado cell_overwrite_ok = True
)
Suponiendo que xlwt ofrece las funciones que estoy buscando, planeaba revisar cada hoja de trabajo de nuevo, pero esta vez realizar un seguimiento del contenido que ocupa más espacio para una columna en particular, y establecer el ancho de columna en función de eso. Por supuesto, también puedo hacer un seguimiento del ancho máximo para una columna específica mientras escribo en la hoja, pero creo que sería más limpio establecer los anchos después de que todos los datos ya se hayan escrito.
¿Alguien sabe si puedo hacer esto? Si no, ¿qué recomienda hacer para ajustar los anchos de columna?
Esto puede ser un poco tarde, pero creé un método que hace esto para toda la hoja a la vez. Es rápido y hace el trabajo. El cojín extra param. solo es necesario si cree que el cálculo 256 no será exacto (si tiene campos de texto más largos).
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)
FitSheetWrapper debería tener una pequeña modificación con xlwt3 en 3.3.4
línea 19:
cambio:
width = arial10.fitwidth(label)
a:
width = int(arial10.fitwidth(label))
razón: / 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)
el ancho debe ser entero
No hay facilidad automática para esto en xlwt. Debe seguir el patrón general que describe, hacer un seguimiento del ancho máximo mientras escribe y establecer el ancho de la columna al final, en algún momento después de haber visto todos los datos pero antes de guardar el libro de trabajo.
Tenga en cuenta que este es el enfoque más limpio y eficiente disponible cuando se trata de archivos de Excel. Si su noción de "después de que los datos ya se han escrito" significa que después de haber confirmado los valores de celda ("escribiendo") pero antes de guardar el libro , el método descrito anteriormente está haciendo exactamente esto. Si lo que quiere decir es que después de haber guardado el libro de trabajo, desea leerlo nuevamente para obtener los anchos máximos y luego guardarlo de nuevo con nuevos anchos de columna , esto será mucho más lento e implicará el uso de xlwt y xlrd (y posiblemente también xlutils). También tenga en cuenta que cuando está utilizando Microsoft Excel original, no existe la noción de "actualizar" un archivo. Puede parecer así desde el punto de vista del usuario, pero lo que está sucediendo detrás de la escena es que cada vez que se guarda, Excel elimina el archivo existente y escribe uno nuevo desde cero.
Si uno no está interesado en usar otra clase (FitSheetWrapper), entonces esto puede implementarse usando el método de la columna WorkSheet.
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)
El valor predeterminado de ancho es 2962 unidades y Excel lo apunta a 8.11 unidades. Por lo tanto estoy multiplicando 367 a la longitud de los datos.
Esto es una adaptación de Kevins FitSheetWrapper.
Yo uso este método:
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