29

我正在尝试创建一个 Excel 工作簿,我可以在其中自动设置或在保存工作簿之前自动调整列的宽度。

我一直在阅读 Python-Excel 教程,希望能在 xlwt 中找到一些模拟 xlrd 的函数(例如sheet_names()cellname(row, col)cell_typecell_value等等......)例如,假设我有以下内容:

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

wb.get_sheet(0)类似于rb.sheet_by_index(0)xlrd 中提供的功能,只是前者允许您修改内容(前提是用户已设置cell_overwrite_ok = True

假设 xlwt 确实提供了我正在寻找的功能,我计划再次浏览每个工作表,但这次跟踪为特定列占用最多空间的内容,并基于此设置列宽。当然,我也可以在写入工作表时跟踪特定列的最大宽度,但我觉得在所有数据都已经写入之后设置宽度会更干净。

有谁知道我能不能做到这一点?如果没有,您建议如何调整列宽?

4

6 回答 6

48

我刚刚实现了一个包装类,它在您输入项目时跟踪它们的宽度。它似乎工作得很好。

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)

所有的魔法都在John Yeung 的arial10模块中。这对于默认 Excel 字体 Arial 10 具有良好的宽度。如果您想使用其他字体编写工作表,则需要更改 fitwidth 函数,最好考虑style传递给FitSheetWrapper.write.

于 2012-02-04T02:30:13.603 回答
13

如果一个人对使用另一个类(FitSheetWrapper)不感兴趣,那么这可以使用 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)

宽度的默认值为 2962 单位,excel 将其指向为 8.11 单位。因此,我将 367 乘以数据长度。

这是改编自 Kevins FitSheetWrapper。

于 2014-04-16T10:15:40.893 回答
5

在 xlwt 中没有自动功能。您必须遵循您描述的一般模式,在编写时跟踪最大宽度,并在最后设置列宽,有时在您查看所有数据之后但在保存工作簿之前。

请注意,这处理 Excel 文件时可用的最简洁和最有效的方法。如果您的“在数据已经写入之后”的概念是指在您已经提交单元格值(“写入”)之后但在实际保存工作簿之前,那么上述方法就是这样做的。如果您的意思是在您已经保存工作簿之后,您想再次阅读它以获得最大宽度,然后使用新的列宽再次保存,这将慢得多,并且将涉及使用 xlwt 和 xlrd (可能还有 xlutils )。另请注意,当您使用正版 Microsoft Excel 时,没有“更新”文件的概念。从用户的角度来看,这似乎是这样,但幕后发生的事情是,每次您进行保存时,Excel 都会删除现有文件并从头开始编写一个全新的文件。

于 2011-11-03T03:44:46.023 回答
1

FitSheetWrapper 应该在 3.3.4 中使用 xlwt3 进行一些修改

第 19 行:

改变:

width = arial10.fitwidth(label)

到:

width = int(arial10.fitwidth(label))  

原因:\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)

宽度必须是整数。

于 2014-05-30T04:04:45.017 回答
1

这可能有点晚了,但我创建了一个方法,可以一次对整个工作表执行此操作。它很快并且可以完成工作。额外的缓冲参数。仅当您认为 256 计算不准确时才需要(如果您有更长的文本字段)。

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)
于 2015-07-27T17:05:06.713 回答
1

我用这个方法:

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
于 2016-09-13T12:44:15.173 回答