2013-07-30 53 views
10

我正在處理pivot-tabled XLSX文件並編寫一個腳本來將它們解析爲每個選項卡的新文件。openpyxl python3 - 格式化整行ellicits奇怪的行爲

由於openpyxl在默認情況下不支持數據透視表,因此我需要做一些工作來重新插入在複製期間丟失的數據透視「樣式」。

爲此,我遍歷每行和每列,在列0中查找值Total。一旦找到,該行應更改爲全部爲bold=True

相反,我收到了不規則的行爲,有時在第一個None之後加粗所有單元格。我的print('bolding totals')消息顯示它正在評估每個行/單元格。我是否有骨頭並將我的縮進旋到環上?也許?

from openpyxl import Workbook 
from openpyxl import load_workbook 
from copy import deepcopy 

wb = load_workbook(filename=r'input.xlsx') 

# Print 1 
sheetlist = wb.get_sheet_names() 
print(sheetlist) 

for i in range(len(sheetlist)-1): 
    dest_filename = r''+sheetlist[i]+'.xlsx' 
    new_wb = Workbook() 
    ws = wb.get_sheet_by_name(sheetlist[i]) 
    new_wb.add_sheet(ws, 0) 

    for k in range(0, new_wb.worksheets[0].get_highest_row()): 
     print(new_wb.worksheets[0].cell(row=k, column=0).value) 
     # ignore empty cells 
     if new_wb.worksheets[0].cell(row=k, column=0).value is not None: 
      if 'Total' in new_wb.worksheets[0].cell(row=k, column=0).value: 
       for j in range(0, new_wb.worksheets[0].get_highest_column()): 
        print('bolding totals, '+str(k), str(j)) 
        new_wb.worksheets[0].cell(
         row=k, column=j).style.font.bold = True 
      elif 'Total' not in new_wb.worksheets[0].cell(row=k, column=0).value: 
       for j in range(0, new_wb.worksheets[0].get_highest_column()): 
        print('not bolding anything') 
        new_wb.worksheets[0].cell(
         row=k, column=j).style.font.bold = False 

    # remove the blank sheet created in new_wb by openpyxl 
    new_wb.remove_sheet(new_wb.get_sheet_by_name('Sheet')) 
    print(new_wb.get_sheet_names()) 
    new_wb.save(dest_filename) 
    break # set to break after one sheet for testing 

print('finished') 

在這一點上,我懷疑這是在風格openpyxl處理的錯誤。我跑了另一個非常簡單的編輯,並得到奇怪的行爲

如果我們有一個粗體/非粗體單元格的簡單佈局。 然後我們運行這個簡單的命令來更改一個單元:

>>> new_wb.worksheets[0].cell(row=10,column=0).style.font.bold = False 

整個列輸出的變化,而不是單獨的細胞。

+0

嗨,錯誤。我以前遇到過問題。我更容易重寫整個應用程序直接使用Excel,通過COM端口驅動它,而不是修復'openpyxl'。這是我的帖子,有一個答案。希望它有助於:http://stackoverflow.com/questions/18145313/openpyxl-highlighting-multiple-cells-when-one-of-them-is-selected-upon-closing-t –

+1

我投票結束這個問題,儘管它寫得很好,而且很有趣,因爲:(a)它沒有答案,被接受或以其他方式; (b)與實際和期望產出的聯繫已經死亡; (c)OP近兩年未訪問SO; (d)現在可能已經修復了任何相關的openpyxl錯誤; (e)它仍然顯示爲一個開放的問題,即使它現在是無法迴避的。 –

+0

@AleksanderLidtke我不記得有關這方面的錯誤報告。您的評論似乎意味着openpyxl是非常錯誤的,我認爲這不是一個公平的表示。當然,如果可以的話,直接使用Excel是非常好的。你可能也想看看xlwings這樣做。 –

回答

7

在單元格之間共享openpyxl 2.0單元格樣式之前:這是使用源XML中的指針實現的保留:兩個(或更多)單元格都將使用樣式「1」。改變一個單元格的這種風格意味着改變它的所有單元格,這聽起來像在這裏觀察到的行爲。

從那時起,雖然實施過程中有各種變化,但在更改一個單元的樣式時不再有任何副作用。一個重要的變化是格式化對象,如Font可以直接使用,不需要用風格包裝。

還有一些其他更改:無法在工作簿之間複製工作表,因爲它們依賴於存儲在父工作簿中的數據。

沒有原始文件是很難確定,但下面的代碼應與openpyxl工作,`openpyxl`不是很讓我震驚> = 2.2

from openpyxl import Workbook 
from openpyxl import load_workbook 

wb = load_workbook(filename='input.xlsx', read_only=True) 

for sheet in wb.sheetnames: 

    dest_filename = '{0}.xlsx'.format(sheet) 
    new_wb = Workbook() 
    del new_wb["Sheet"] 

    ws1 = wb[sheet] 
    ws2 = new_wb.create_sheet(sheet) 

    for row in ws1: 
     ws2.append([c.value for c in row]) 
     first = row[0] 
     if first.data_type == "s" and "Total" in first.value: 
      for idx in range(len(row)): 
       cell = ws2.cell(row=ws2.max_row, column=idx+1) 
       bolded = cell.font.copy(bold=True) 
       cell.font = bolded 

    new_wb.save(dest_filename) 
    print("saving {0}".format(dest_filename)) 

print('finished')