2011-08-03 256 views
23

我想創建一個Excel工作簿,可以在保存工作簿之前自動設置或自動調整列的寬度。Python xlwt - 訪問現有的單元格內容,自動調整列寬

我一直在閱讀的Python的Excel的教程在模仿xlrd那些在xlwt找到了一些功能的希望(如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)類似於xlrd提供的rb.sheet_by_index(0)功能,不同之處在於前者允許你修改的內容(前提是用戶已經設置cell_overwrite_ok = True

假設xlwt DOES關閉呃我正在尋找的功能,我計劃再次通過每個工作表,但是這次跟蹤了爲特定列佔用大部分空間的內容,並基於此設置了列寬。當然,我也可以在寫入表單時跟蹤特定列的最大寬度,但我覺得在所有數據寫入完畢後設置寬度會更清晰。

有誰知道我能否做到這一點?如果不是,那麼爲了調整列寬,你建議做什麼?

回答

43

我剛剛實現了一個包裝類,跟蹤輸入項目的寬度。它似乎工作得很好。

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's arial10 module。 Arial 10的寬度很好,這是默認的Excel字體。如果要使用其他字體編寫工作表,則需要更改fitwidth函數,理想情況下會考慮傳遞給FitSheetWrapper.writestyle參數。

+5

很不錯的解決方案。我必須用'int(..)'包裝'width = arial10.fitwidth(label)',否則xlwt-0.7.5會引發ValueError。如果你的單元格寬度稍小於所需的單元格寬度,請嘗試'math.ceil(int(..))'。 – dset0x

+7

鏈接到arial10模塊對我來說是打破了。但我發現它在github上:https://github.com/GeekPeduli/Sahana-Eden/blob/master/modules/arial10.py – Humphrey

+0

不幸的是,這將不適用於較長的標籤,因爲總寬度可以高於65535(其中是最好的) – Jerzyk

4

在xlwt中沒有這個自動設施。您必須遵循您描述的一般模式,在寫作時跟蹤最大寬度,並在結束時設置列寬,有時在看完所有數據之後但保存工作簿之前。

請注意,這個是處理Excel文件時最乾淨和最有效的方法。如果您已經提交單元格值(「寫入」)但在實際保存工作簿之前,您的「數據寫入後」的意思是,那麼上述方法正是這樣做的。如果你的意思是已經保存工作簿後,你想再次讀取它以獲得最大寬度,然後再次以新的列寬保存它,這將會慢得多,並且將涉及使用xlwt和xlrd(也可能是xlutils)。另請注意,當您使用真正的Microsoft Excel時,沒有「更新」文件的概念。從用戶的角度來看,這似乎是這樣的,但幕後發生的情況是,每次你進行保存時,Excel都會將現有文件從頭開始寫出一個全新的文件。

4

如果對使用另一個類(FitSheetWrapper)不感興趣,則可以使用WorkSheet列的Method實現。

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。

1

FitSheetWrapper應該有一點點修改與xlwt3 3.3.4

線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) 

寬度必須是整數。

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) 
0

我用這個方法:

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 
相關問題