一、簡介
用python來自動生成excel數據文件。python處理excel文件主要是第三方模塊庫xlrd、xlwt、xluntils和pyExcelerator,除此之外,python處理excel還可以用win32com和openpyxl模塊。
安裝:
pip install xlutils
二、使用xlrd讀取文件:
import xlrd #打開一個workbook workbook = xlrd.open_workbook('E:\\Code\\Python\\testdata.xls') #抓取所有sheet頁的名稱 worksheets = workbook.sheet_names() print('worksheets is %s' %worksheets) #定位到sheet1 worksheet1 = workbook.sheet_by_name(u'Sheet1') """ #通過索引順序獲取 worksheet1 = workbook.sheets()[0] #或 worksheet1 = workbook.sheet_by_index(0) """ """ #遍歷所有sheet對象 for worksheet_name in worksheets: worksheet = workbook.sheet_by_name(worksheet_name) """ #遍歷sheet1中所有行row num_rows = worksheet1.nrows for curr_row in range(num_rows): row = worksheet1.row_values(curr_row) print('row%s is %s' %(curr_row,row)) #遍歷sheet1中所有列col num_cols = worksheet1.ncols for curr_col in range(num_cols): col = worksheet1.col_values(curr_col) print('col%s is %s' %(curr_col,col)) #遍歷sheet1中所有單元格cell for rown in range(num_rows): for coln in range(num_cols): cell = worksheet1.cell_value(rown,coln) print cell """ #其他寫法: cell = worksheet1.cell(rown,coln).value print cell #或 cell = worksheet1.row(rown)[coln].value print cell #或 cell = worksheet1.col(coln)[rown].value print cell #獲取單元格中值的類型,類型 0 empty,1 string, 2 number, 3 date, 4 boolean, 5 error cell_type = worksheet1.cell_type(rown,coln) print cell_type """
示例:

整體思路為,打開文件,選定表格,讀取行列內容,讀取表格內數據
import xlrd from datetime import date,datetime file = 'test3.xlsx' def read_excel(): wb = xlrd.open_workbook(filename=file)#打開文件 print(wb.sheet_names())#獲取所有表格名字 sheet1 = wb.sheet_by_index(0)#通過索引獲取表格 sheet2 = wb.sheet_by_name('年級')#通過名字獲取表格 print(sheet1,sheet2) print(sheet1.name,sheet1.nrows,sheet1.ncols) rows = sheet1.row_values(2)#獲取行內容 cols = sheet1.col_values(3)#獲取列內容 print(rows) print(cols) print(sheet1.cell(1,0).value)#獲取表格里的內容,三種方式 print(sheet1.cell_value(1,0)) print(sheet1.row(1)[0].value)
運行結果如下:

那么問題來了,上面的運行結果中紅框框中的字段明明是出生日期,可顯示的確實浮點數;同時合並單元格里面應該是有內容的,結果不能為空。
別急,我們來一一解決這兩個問題:
1.Python讀取Excel中單元格內容為日期的方式
Python讀取Excel中單元格的內容返回的有5種類型,即上面例子中的ctype:
ctype : 0 empty,1 string,2 number, 3 date,4 boolean,5 error
即date的ctype=3,這時需要使用xlrd的xldate_as_tuple來處理為date格式,先判斷表格的ctype=3時xldate才能開始操作。
詳細代碼如下:
import xlrd from datetime import date,datetime print(sheet1.cell(1,2).ctype) date_value = xlrd.xldate_as_tuple(sheet1.cell_value(1,2),wb.datemode) print(date_value) print(date(*date_value[:3])) print(date(*date_value[:3]).strftime('%Y/%m/%d'))
運行結果如下:

2.獲取合並單元格的內容
在操作之前,先介紹一下merged_cells()用法,merged_cells返回的這四個參數的含義是:(row,row_range,col,col_range),其中[row,row_range)包括row,不包括row_range,col也是一樣,即(1, 3, 4, 5)的含義是:第1到2行(不包括3)合並,(7, 8, 2, 5)的含義是:第2到4列合並。
詳細代碼如下:
print(sheet1.merged_cells) print(sheet1.cell_value(1,3)) print(sheet1.cell_value(4,3)) print(sheet1.cell_value(6,1))
運行結果如下:

發現規律了沒?是的,獲取merge_cells返回的row和col低位的索引即可! 於是可以這樣批量獲取:
詳細代碼如下:
merge = [] print(sheet1.merged_cells) for (rlow,rhigh,clow,chigh) in sheet1.merged_cells: merge.append([rlow,clow]) for index in merge: print(sheet1.cell_value(index[0],index[1]))
運行結果跟上圖一樣,如下:

三、使用xlwt生成Excel文件(可以控制Excel中單元格的格式):
import xlwt #創建workbook和sheet對象 workbook = xlwt.Workbook() #注意Workbook的開頭W要大寫 sheet1 = workbook.add_sheet('sheet1',cell_overwrite_ok=True) sheet2 = workbook.add_sheet('sheet2',cell_overwrite_ok=True) #向sheet頁中寫入數據 sheet1.write(0,0,'this should overwrite1') sheet1.write(0,1,'aaaaaaaaaaaa') sheet2.write(0,0,'this should overwrite2') sheet2.write(1,2,'bbbbbbbbbbbbb') """ #-----------使用樣式----------------------------------- #初始化樣式 style = xlwt.XFStyle() #為樣式創建字體 font = xlwt.Font() font.name = 'Times New Roman' font.bold = True #設置樣式的字體 style.font = font #使用樣式 sheet.write(0,1,'some bold Times text',style) """ #保存該excel文件,有同名文件時直接覆蓋 workbook.save('E:\\Code\\Python\\test2.xls') print '創建excel文件完成!'
示例:
import xlwt #設置表格樣式 def set_style(name,height,bold=False): style = xlwt.XFStyle() font = xlwt.Font() font.name = name font.bold = bold font.color_index = 4 font.height = height style.font = font return style #寫Excel def write_excel(): f = xlwt.Workbook() sheet1 = f.add_sheet('學生',cell_overwrite_ok=True) row0 = ["姓名","年齡","出生日期","愛好"] colum0 = ["張三","李四","戀習Python","小明","小紅","無名"] #寫第一行 for i in range(0,len(row0)): sheet1.write(0,i,row0[i],set_style('Times New Roman',220,True)) #寫第一列 for i in range(0,len(colum0)): sheet1.write(i+1,0,colum0[i],set_style('Times New Roman',220,True)) sheet1.write(1,3,'2006/12/12') sheet1.write_merge(6,6,1,3,'未知')#合並行單元格 sheet1.write_merge(1,2,3,3,'打游戲')#合並列單元格 sheet1.write_merge(4,5,3,3,'打籃球') f.save('test.xls') if __name__ == '__main__': write_excel()
結果圖:

在此,對write_merge()的用法稍作解釋,如上述:sheet1.write_merge(1,2,3,3,'打游戲'),即在四列合並第2,3列,合並后的單元格內容為"合計",並設置了style。其中,里面所有的參數都是以0開始計算的。
四、使用xluntils模塊修改文件:
import xlrd import xlutils.copy #打開一個workbook rb = xlrd.open_workbook('E:\\Code\\Python\\test1.xls')
#復制的Excel是沒有格式的,要保留原格式需要使用:rb = xlrd.open_workbook('E:\\Code\\Python\\test1.xls',formatting_info=True) wb = xlutils.copy.copy(rb) #獲取sheet對象,通過sheet_by_index()獲取的sheet對象沒有write()方法 ws = wb.get_sheet(0) #寫入數據 ws.write(1, 1, 'changed!') #添加sheet頁 wb.add_sheet('sheetnnn2',cell_overwrite_ok=True) #利用保存時同名覆蓋達到修改excel文件的目的,注意未被修改的內容保持不變 wb.save('E:\\Code\\Python\\test1.xls')
在修改的過程中,使用ws.write()被修改的單元格會清空格式,若要保留原格式,需要使用以下函數:
#本文重點,該函數中定義:對於沒有任何修改的單元格,保持原有格式。 def setOutCell(outSheet, col, row, value): """ Change cell value without changing formatting. """ 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 # 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 # 使用函數setOutCell代替ws.write() setOutCell(ws,col,row,"寫入內容")
五、pyExcelerator模塊與xlwt類似,也可以用來生成excel文件
讀:
import pyExcelerator #parse_xls返回一個列表,每項都是一個sheet頁的數據。 #每項是一個二元組(表名,單元格數據)。其中單元格數據為一個字典,鍵值就是單元格的索引(i,j)。如果某個單元格無數據,那么就不存在這個值 sheets = pyExcelerator.parse_xls('E:\\Code\\Python\\testdata.xls') print sheets
寫:
import pyExcelerator #創建workbook和sheet對象 wb = pyExcelerator.Workbook() ws = wb.add_sheet(u'第一頁') #設置樣式 myfont = pyExcelerator.Font() myfont.name = u'Times New Roman' myfont.bold = True mystyle = pyExcelerator.XFStyle() mystyle.font = myfont #寫入數據,使用樣式 ws.write(0,0,u'ni hao 帕索!',mystyle) #保存該excel文件,有同名文件時直接覆蓋 wb.save('E:\\Code\\Python\\mini.xls') print '創建excel文件完成!'
六、報錯:
但是我們會發現在讀取xlsx格式的Excel時,傳入formatting_info會直接拋出異常,而讀取xls類型的文件時不存在此問題。
raise NotImplementedError("formatting_info=True not yet implemented")
不難推斷,拋異常的原因是formatting_info還沒有對新版本的xlsx的格式完成兼容。
那么如果我們要操作的文件剛好是xlsx格式,又想保存其原有的格式該怎么辦呢?
1、修改為xlsx為xls(推薦)
將xlsx另存為xls,然后再進行后續操作,親測有效,能正常保存Excel原有格式, 不用修改代碼。

2、改用 openpyxl
coding嘗試讀取文件,處理速度真的很慢...而且規則和宏全部丟失。
3、使用pywin32
這是用於Win32 (pywin32)擴展的Python擴展庫,它提供了對許多來自Python的Windows api的訪問。
4、使用老舊的版本 xlrd-0.6.1
使用xlrd-0.6.1可以讀取,沒有異常拋出。直到我傳入其他幾個xls文件,出現Expected BOF record; found 0x4b50 錯誤,原因是xlrd-0.6.1不支持office2007
參考:
https://www.cnblogs.com/Detector/p/8709362.html
https://www.cnblogs.com/songdanqi0724/p/8145455.html
https://blog.csdn.net/qq_33683032/article/details/79027811
https://blog.csdn.net/csdnnews/article/details/80878945
