2013-05-08 61 views
4

我想格式化電子表格(xls或xlsx),以便通過用特定顏色填充背景來格式化包含單詞或以特定字符串結尾的任何單元格。使用python從Excel有條件地格式化文本字符串

例如,如果單元格包含單詞「已刪除」,請將其填充黑色並將文本塗成白色。 如果單元格以'.pf'結尾,則將單元格塗成紅色。

我發現從幾年前類似的疑問,建議如下:

import xlrd 
import xlutils.copy 

inBook = xlrd.open_workbook('input.xls', formatting_info=True) 
outBook = xlutils.copy.copy(inBook) 

def _getOutCell(outSheet, colIndex, rowIndex): 
    """ HACK: Extract the internal xlwt cell representation. """ 
    row = outSheet._Worksheet__rows.get(rowIndex) 
    if not row: return None 
    cell = row._Row__cells.get(colIndex) 
    return cell 

def setOutCell(outSheet, col, row, value): 
    """ Change cell value without changing formatting. """ 
    # HACK to retain cell style. 
    previousCell = _getOutCell(outSheet, col, row) 
    # END HACK, PART I 
    outSheet.write(row, col, value) 
    # HACK, PART II 

    if previousCell: 
     newCell = _getOutCell(outSheet, col, row) 
    if newCell: 
     newCell.xf_idx = previousCell.xf_idx 
    # END HACK 


outSheet = outBook.get_sheet(0) 
setOutCell(outSheet, 5, 5, 'Test') 
outBook.save('output.xls') 

雖然這確實從input.xls到output.xls的值複製,這​​似乎並沒有轉移格式(中當打開output.xls時,input.xls中的測試值不再被格式化,excel中的「管理規則」下也不存在條件格式規則。

數字值的「if」語句似乎可行,但同樣,I我正在尋找一種方法來格式化包含某些字符串的單元格。謝謝!

+0

您是否嘗試在原地更改文件?您可以在腳本運行之前創建文件的備份。 – Alfe 2013-05-08 19:43:53

+0

我不認爲就地編輯是可能的。從我所瞭解的xlutils只允許您複製和修改副本。如果win32com可以做到這一點,這將是一個很酷的嘗試方向,但我不知道這一點。 win32com也不是我的首選策略,因爲我希望這個腳本能夠在未安裝excel的機器上運行(linux)。 – user2363458 2013-05-09 15:00:46

回答

2

保留原始input.xls格式,當你打開它:

from xlrd import open_workbook 

input_wb = open_workbook('input.xls', formatting_info=True) 

創建基於此模板的新工作簿:

from xlutils.copy import copy as copy_workbook 

output_wb = copy_workbook(input_wb) 

定義了一些新的單元格樣式:

from xlwt import easyxf 

red_background = easyxf("pattern: pattern solid, fore_color red;") 
black_with_white_font = easyxf('pattern: pattern solid, fore_color black; font: color-index white, bold on;") 

評估並修改您的單元格:

input_ws = input_wb.sheet_by_name('StackOverflow') 
output_ws = output_wb.get_sheet(0) 

for rindex in range(0, input_ws.nrows): 
    for cindex in range(0, input_ws.ncols): 
     input_cell = input_ws.cell(rindex, cindex) 
     if input_cell.value[ input_cell.value.rfind('.'): ] == 'pf': 
      output_ws.write(rindex, cindex, input_cell.value, red_background) 
     elif input_cell.value.find('deleted') >= 0: 
      output_ws.write(rindex, cindex, input_cell.value, black_with_white_font) 
     else: 
      pass # we don't need to modify it 

保存新的工作簿

output_wb.save('output.xls') 

使用上面的例子,未經修飾細胞應該有自己的原始格式不變。

如果您需要更改單元格的內容,並想保留原來的格式(即不使用自定義easyxf實例),你可以使用這個片段:

def changeCell(worksheet, row, col, text): 
    """ Changes a worksheet cell text while preserving formatting """ 
    # Adapted from https://stackoverflow.com/a/7686555/1545769 
    previousCell = worksheet._Worksheet__rows.get(row)._Row__cells.get(col) 
    worksheet.write(row, col, text) 
    newCell = worksheet._Worksheet__rows.get(row)._Row__cells.get(col) 
    newCell.xf_idx = previousCell.xf_idx 

# ... 

changeCell(worksheet_instance, 155, 2, "New Value") 

對於比較,您可以使用字符串方法findrfind(從右側進行搜索)。它們返回字符串中子字符串位置的索引。如果未找到子字符串,則返回-1。 Ergo,您在input_cell.value.find('deleted') >= 0之上看到以評估子字符串「已刪除」是否存在。對於.pf的比較,我使用了rfind以及Python中的一個名爲slicing的東西。

+0

這將導致以下錯誤:'回溯(最近最後一次通話): 「\ stacksolution.py」 文件,14號線在 input_ws = input.sheet_by_name( '工作表Sheet1')#eval和修改細胞 AttributeError的:'builtin_function_or_method對象沒有屬性'sheet_by_name'' ...另外,我不清楚如何將字符串比較應用到邏輯中。例如,你的'如果input_cell.value =='邏輯在這裏「'部分..這是好的,如果你說」<50 or > 60,但你如何寫它的結尾與.pf「或」包含單詞刪除「 – user2363458 2013-05-09 12:26:15

+1

對於這個錯誤,當它實際上是'input_wb'(與'output_wb'相同)時,我輸入了'input'作爲Workbook實例名 - 確保更新這兩行。在一些情況下顯示條件表達式 – pztrick 2013-05-09 13:26:51

+0

這是迄今爲止最好的結果,通過對input_wb和output_wb的拼寫錯誤更正,腳本現在已成功將input.xls複製到output.xls中,其中包含所有單元格內容。格式化,如字體類型,字體大小,字體顏色它是什麼**不做**,是保留條件格式或我的條件格式化規則(也許這是xlutils.copy的限制)。包含「刪除」這個詞的文件他們,但不是'.pf'。如果我用'.pf'使用'delete'語句,它應該有一些誤報。謝謝! – user2363458 2013-05-09 14:56:31