引言
我們在做接口測試,經常會用到excel去管理測試數據,對Excel的操作比較頻繁,那么使用python如何操作Excel文件的讀與寫呢?由於之前講的都是大的框框,沒有講這么小的模塊使用,現在就化整為0的講解。
讀寫模塊介紹
python有三個模塊是對Excel文件的操作,分別是:openpyxl,xlrd和xlwt。下面簡單的介紹一下各個模塊的特點及使用案例。
xlrd
xlrd是用來從Excel中讀寫數據的,但我平常只用它進行讀操作,寫操作會遇到些問題。用xlrd進行讀取比較方便,流程和平常手動操作Excel一樣,打開工作簿(Workbook),選擇工作表(sheets),然后操作單元格(cell)。下面舉個例子,例如要打開當前目錄下名為”data.xlsx”的Excel文件,選擇第一張工作表,然后讀取第一行的全部內容並打印出來。Python代碼如下:
import os
import xlrd
from xlutils.copy import copy
# 獲取當前文件的絕對路徑
curPath = os.path.abspath(os.path.dirname(__file__))
print(curPath)
# 獲取項目根目錄
rootPath = os.path.abspath(os.path.dirname(curPath))
print(rootPath)
# 獲取文件路徑
file_path = r'APItest_ddt\data\data.xls'
file_path = os.path.join(rootPath,file_path)
print(file_path)
#打開excel文件
data=xlrd.open_workbook(file_path)
#獲取第一張工作表(通過索引的方式)
table=data.sheets()[0]
#data_list用來存放數據
data_list=[]
#將table中第一行的數據讀取並添加到data_list中
data_list.extend(table.row_values(0))
#打印出第一行的全部數據
for item in data_list:
print(item)
# 寫入數據
copy_data = copy(data)
# 讀取復制的excel的sheet頁
copy_data_to_sheet = copy_data.get_sheet(0)
# 通過get_sheet()獲取的sheet有write()方法,寫入數據
copy_data_to_sheet.write(5,5,"這是我寫入的測試數據:哈哈")
# 保存數據
copy_data.save(file_path)
運行結果:
C:\Users\Administrator\Desktop\APItest_ddt C:\Users\Administrator\Desktop C:\Users\Administrator\Desktop\APItest_ddt/data/data.xls 地址
打開data.xls文件:

在處理excel數據時發現了xlwt的局限性–不能寫入超過65535行、256列的數據(因為它只支持Excel 2003及之前的版本,在這些版本的Excel中行數和列數有此限制),這對於實際應用還是不夠的。為此經過一番尋找發現了一個支持07/10/13版本Excel的openpyxl,雖然功能很強大,但是操作起來感覺沒有xlwt方便。以上是xlrd的幾個簡單操作,並且可以發現,xlrd可以讀,也可以寫的。只是寫的話,沒那么方便。
xlwt
如果說xlrd不是一個單純的Reader(如果把xlrd中的后兩個字符看成Reader,那么xlwt后兩個字符類似看成Writer),那么xlwt就是一個純粹的Writer了,因為它只能對Excel進行寫操作。xlwt和xlrd不光名字像,連很多函數和操作格式也是完全相同。下面簡要歸納一下常用操作。
import xlwt
# 新建一個Excel文件(只能通過新建寫入)
data=xlwt.Workbook()
# 新建一個工作表
table=data.add_sheet('name')
# 寫入數據到A1單元格
table.write(0,0,u'呵呵')
# 注意:如果對同一個單元格重復操作,會引發overwrite Exception,想要取消該功能,需要在添加工作表時指定為可覆蓋,像下面這樣
table=data.add_sheet('sheet1',cell_overwrite_ok=True)
# 保存
data.save('test.xls')
查看結果:

openpyxl
該模塊支持最新版的Excel文件格式,對Excel文件具有響應的讀寫操作,對此有專門的Reader和Writer兩個類,便於對Excel文件的操作。雖然如此,但我一般還是用默認的workbook來進行操作。常用操作歸納如下:
from openpyxl.reader.excel import load_workbook
wb=load_workbook(filename=r"openpyxl_test.xlsx")
import openpyxl
if __name__ == '__main__':
wb = load_workbook(filename=r"openpyxl_test.xlsx")
# 顯示所有工作表的名字
sheet_name = wb.get_sheet_names()
print(sheet_name)
# 取第一張表
sheetnames = wb.sheetnames
ws = wb[sheetnames[0]]
# 顯示表名,表行數,表列數
print("Work Sheet Title:", ws.title)
print("Work Sheet Rows:", ws.max_row)
print("Work Sheet Cols:", ws.max_column)
# 獲取指定行的值,如第三行
row3_values = []
row3_cell_list = list(ws.rows)[2]
for cell in row3_cell_list:
row3_values.append(cell.value)
print(row3_values) # output:['A3', 'B3', 'C3', 'D3']
# 獲取所有行的數據
# 建立存儲數據的字典
data = {}
# 獲取表格所有值
# 法1:
for i in range(0, ws.max_row):
every_row_values = []
every_row_cell_list = list(ws.rows)[i]
for cell in every_row_cell_list:
every_row_values.append(cell.value)
data[i + 1] = every_row_values
print(data)
# {1: ['A1', 'B1', 'C1', 'D1'], 2: ['A2', 'B2', 'C2', 'D2'], 3: ['A3', 'B3', 'C3', 'D3'], 4: ['A4', 'B4', 'C4', 'D4'], 5: ['A5', 'B5', 'C5', 'D5'],
# 6: ['A6', 'B6', 'C6', 'D6'], 7: ['A7', 'B7', 'C7', 'D7'], 8: ['A8', 'B8', 'C8', 'D8'], 9: ['A9', 'B9', 'C9', 'D9'], 10: ['A10', 'B10', 'C10', 'D10'],
# 11: ['A11', 'B11', 'C11', 'D11']}
# 法2
for row in ws.rows:
line = [cell.value for cell in row]
print(
line) # output:['A1', 'B1', 'C1', 'D1'],['A2', 'B2', 'C2', 'D2'], ['A3', 'B3', 'C3', 'D3'],['A4', 'B4', 'C4', 'D4'], ['A5', 'B5', 'C5', 'D5'],['A6', 'B6', 'C6', 'D6'],['A7', 'B7', 'C7', 'D7'],['A8', 'B8', 'C8', 'D8'],['A9', 'B9', 'C9', 'D9'],['A10', 'B10', 'C10', 'D10'],['A11', 'B11', 'C11', 'D11']
# 獲取某個區間的值,例:獲得了以A3為左上角,C6為右下角矩形區域的所有單元格
# 法1:使用range
data1 = {}
for i in range(2, 6):
every_row_values = []
every_row_cell_list = list(ws.rows)[i]
for cell in every_row_cell_list:
every_row_values.append(cell.value)
data1[i + 1] = every_row_values
print(data1)
# output{3: ['A3', 'B3', 'C3', 'D3'], 4: ['A4', 'B4', 'C4', 'D4'], 5: ['A5', 'B5', 'C5', 'D5'], 6: ['A6', 'B6', 'C6', 'D6']}
# 法2:使用切片
data_list = []
for row_cell in ws['A3':'C6']:
every_row_value = []
for cell in row_cell:
every_row_value.append(cell.value)
data_list.append(every_row_value)
print(data_list) # output:[['A3', 'B3', 'C3'], ['A4', 'B4', 'C4'], ['A5', 'B5', 'C5'], ['A6', 'B6', 'C6']]
# 測試寫入數據:
wb = load_workbook(filename=r"openpyxl_test.xlsx")
ws = wb.active
# 第一個sheet是ws
ws = wb.worksheets[0]
# 設置ws的名稱
ws.title = "range names"
# 向某個單元格中寫入數據
ws.cell(11,11).value = u'Test write data!!!'
# 最后保存文件
wb.save(filename=r"openpyxl_test.xlsx")
結果如下:


封裝讀寫
上面已經介紹了三個模塊的使用,那么在搭建接口測試框架的時候,不可能這樣寫,一方面不利於代碼可讀性與維護,另一方面不雅觀。所以,要對零散的代碼進行二次封裝,一下就是針對常用方法進行二次封裝:
import xlrd
from xlutils.copy import copy
import os
# 獲取當前文件的絕對路徑
curPath = os.path.abspath(os.path.dirname(__file__))
print(curPath)
# 獲取項目根目錄
rootPath = os.path.abspath(os.path.dirname(curPath))
print(rootPath)
# 類中使用裝飾器 @classmethod定義方法,是類方法
# 類中使用裝飾器 @staticmethod定義方法,是靜態方法
class Operate_Excel(object):
"""
操作excel類
"""
# 定義構造函數,創建對象自動執行
def __init__(self,file_path=None,sheet_id=None):
"""
:param file_path:如果沒傳值,默認為excel路徑
:param sheet_id:如果沒傳值,默認為第一個sheet頁
"""
if file_path:
# 成員變量
self.file_path = file_path
self.sheet_id = sheet_id
else:
self.file_path = r'data/util_data/operate_excel.xls'
# 將文件目錄拼接成絕對路徑
self.file_path = os.path.join(rootPath,self.file_path)
print(self.file_path)
if sheet_id:
self.sheet_id = sheet_id
else:
self.sheet_id = 0
# 調用成員方法
self.sheet_table = self.get_sheet()
"""成員方法"""
# 獲取sheet頁操作對象
def get_sheet(self):
data = xlrd.open_workbook(self.file_path)
sheet_table = data.sheets()[self.sheet_id]
return sheet_table
# 獲取sheet頁的行數和列數,返回的是一個元組
def get_sheet_nrows_ncols(self):
return self.sheet_table.nrows,self.sheet_table.ncols
# 獲取sheet頁的行數
def get_sheet_nrows(self):
return self.sheet_table.nrows
# 獲取sheet頁的列數
def get_sheet_ncols(self):
return self.sheet_table.ncols
# 獲取具體單元格的數據
def get_sheet_cell(self,row,col):
"""
:params row: 單元格行值
:params col: 單元格列值
:return: cell_data
"""
cell_data = self.sheet_table.cell_value(row,col)
return cell_data
# 寫入數據到excel中
def write_to_excel(self,row,col,values):
# 打開excel文件讀取數據句柄
data = xlrd.open_workbook(self.file_path)
# 復制excel
copy_data = copy(data)
# 讀取復制的excel的sheet頁
copy_data_to_sheet = copy_data.get_sheet(0)
# 通過get_sheet()獲取的sheet有write()方法,寫入數據
copy_data_to_sheet.write(row,col,values)
# 保存數據
copy_data.save(self.file_path)
if __name__ == '__main__':
read_xls = Operate_Excel()
print("獲取excel表的行數與列數,返回元組格式: ",read_xls.get_sheet_nrows_ncols())
print("獲取excel表的行數: ",read_xls.get_sheet_nrows())
print("獲取excel表的列數: ",read_xls.get_sheet_ncols())
print("獲取excel表的單元格(1,1)的值: ",read_xls.get_sheet_cell(1,1))
print("獲取excel表的單元格(1,2)的值: ",read_xls.get_sheet_cell(1,2))
print("獲取excel表的單元格(2,2)的值: ",read_xls.get_sheet_cell(2,2))
print("寫入excel表的單元格(2,2)的值: ",read_xls.write_to_excel(8,8,'test'))
運行結果:
獲取excel表的行數與列數,返回元組格式: (18, 9) 獲取excel表的行數: 18 獲取excel表的列數: 9 獲取excel表的單元格(1,1)的值: case_name01 獲取excel表的單元格(1,2)的值: case_method01 獲取excel表的單元格(2,2)的值: case_method02 寫入excel表的單元格(2,2)的值: None
excel文件:

總結
到此,Excel讀寫功能已經介紹完,以上功能大部分滿足日常使用,當然你也可以深入研究,繼續加入其它方法進來。以上源碼,已上傳到群文件中,可以加入QQ測試開發交流群:696400122索取。
