python處理excel文件


一、簡介

用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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM