1. 程式人生 > 實用技巧 >【Python3】xlwt/xlrd模組讀取和新建excel並生成直方圖

【Python3】xlwt/xlrd模組讀取和新建excel並生成直方圖

此文轉載自:https://blog.csdn.net/weixin_52855865/article/details/110109460#commentBox

Python-Excel處理

這是一個關於測試報告(Excel)的總結與繪製直方圖的指令碼。指令碼的功能是實現對測試報告中多個工作頁(sheet)提取P/Fp/F的單元格(cell),並分別統計數量,再據此繪製直方圖。

一、模組的安裝

我們需要用到以下幾個模組:
1.pip:該工具包提供了對Python包的查詢、下載、安裝、解除安裝功能。
2.xlrd:讀取excel
3.xlwt:寫入excel
4.matplotlib:Python的2D繪相簿

pip官網:https://pypi.org/project/pip/

為了下載pip.py先安裝wget:

yum -y install wget

下載pip安裝檔案並安裝:

wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py

安裝驅動(ddt)、xlrd和xlwt:

pip install ddt
pip install
xlrd pip install xlwt

安裝matplotlib:

sudo apt-get install python3-matplotlib

二、讀取Excel——xlrd

首先,我們需要理解Excel檔案的三層級物件:workbook、sheet、cell。
即:
workbook = xlrd.*
sheet = workbook.*
cell = sheet.cell*

1.xlrd基礎介面用法

xlrd各介面用法:
(1) 開啟檔案

workbook = xlrd.open_workbook('123.xlsx')

(2) 獲取檔案中包含的所有工作表名稱

sheets =
workbook.sheet_names()

(3) 選定工作表

sheet = workbook.sheets()[0]  #通過索引獲取
sheet = workbook.sheet_by_index(0)  #通過順序獲取
sheet = workbook.sheet_by_name('sheet1')  #通過表名獲取

(4) 獲取行數和列數

nrows = sheet.nrows
ncols = sheet.ncols

(5) 列印“表名”“行數”“列數”

print(sheet.name,sheet.nrows,sheet.ncols)

(6) 獲取全表資料

for i in range(1,nrows+1):  #對於行,從第一行讀取到總行數
  for j in range(1,ncols+1):  #對於列,從第一列讀取到總列數
    data = sheet.cell(i-1,j-1).value

Tips1:

for i in range(1,n)

i 的取值為1,2,3……n-1。
當然也可以寫成:

for i in range(0,nrows):
  for j in range(0,ncols):
    data = sheet.cell(i,j).value

但我個人更傾向於第一種,因為第一種寫法的意義更明確。

Tips2:對於工作表的第一行第一列

data = sheet.cell(0,0).value

Tips3:value表示“值”,是否加value決定輸出格式。

data = sheet.cell(1,2).value

輸出如下:
--------------------------------------------------------------------------

data = sheet.cell(1,2)

輸出如下:

2.迴圈讀取sheet

程式碼如下:

workbook = xlrd.open_workbook(fname)
sheets = workbook.sheet_names()  #獲取所有工作表名稱並形成陣列
nsheets = len(sheets)  #得出陣列長度

for z in range(1,nsheets+1):
  sheet = workbook.sheet_by_index(z-1)

3.在sheet中定位關鍵字

程式碼如下:

global rowst  #定義為全域性變數方便其他函式呼叫
global colst  #定義為全域性變數方便其他函式呼叫

for i in range(1,nrows+1):
  for j in range(1,ncols+1):
    data1 = sheet.cell(i-1,j-1).value
    if (data1=='P')or(data1=='Fp')or(data1=='F'):
      rowst = i
      colst = j
#得到關鍵字所在單元格座標(i,j) 

Tips1:

if (data1==‘P’) or (data1==‘Fp’) or (data1==‘F’):

不能寫成:
if data1 == (‘P’ or ‘Fp’ or ‘F’):

4.在sheet中確定首位關鍵字

在上面的程式碼中獲得的包含關鍵字的單元格有很多個,那麼如何確定滿足條件(所在行列全為P/Fp/F)的首位關鍵字呢?
我們需要以下兩步:
① 判斷是否滿足條件
② 一旦滿足條件立刻退出迴圈

程式碼如下:

count_l = 0
count_col = 0
for l in range(colst,ncols+1):
  data_l = sheet.cell(rowst-1,l-1).value  #讀取關鍵字所在行的資料
  
  if data_l != "":  #如果單元格內容不為空
    count_col+=1  #自加一,統計有資料的單元格個數

    if (data_l=='P') or (data_l=='Fp') or (data_l=='F'):
      count_l+=1  #自加一,統計含有關鍵字的單元格個數

if count_l == count_col:  #如果兩者的數量相等,則可以確定該關鍵字所在行全為P/Fp/F
#繼續判斷列是否滿足條件
  count_w = 0
  count_row = 0
  for w in range(rowst,nrows+1):
    data_w = sheet.cell(w-1,colst-1).value  #讀取關鍵字所在列的資料
 
    if data_w != "":  #如果單元格內容不為空
      count_row+=1  #自加一,統計有資料的單元格個數
      
      if (data_w=='P' or data_w=='Fp' or data_w=='F'):
        count_w+=1  #自加一,統計含有關鍵字的單元格個數

  if count_w == count_row:  #如果兩者的數量相等,則可以確定該關鍵字所在列全為P/Fp/F
    print (rowst,end=',')
    print (colst)
    return  #確定首位滿足條件的單元格即退出迴圈

Tips1:

if data_l == "":

""表示單元格資料為空,有框線無內容也為空。
如果寫成

if data_l == None:

None也表示單元格內容為空,但是有框線無內容不判定為空。

Tips2:

count_l+=1

表示變數自加一,也可以寫成:

count_l = count_l +1

Tips3:

print (rowst,end=’,’)
print (colst)

end=’'表示輸出結果不換行顯示,‘,’表示用逗號隔開,則輸出結果表示為(rowst,colst)。

5. 統計資料並將結果儲存為陣列

程式碼如下:

global count_P
global count_Fp
global count_F

count_P = 0
count_Fp = 0
count_F = 0

list = []  #建立一個空陣列列表

for m in range(rowst,nrowst+1):
  for n in range(colst,ncols+1):
    data2 = sheet.cell(m-1,n-1).value
    
    if data2 == 'P':
      count_P+=1  #統計P的數量
    elif data2 == 'Fp':
      count_Fp+=1  #統計Fp的數量
    elif data2 == 'F':
      count_F+=1  #統計F的數量
total = count_P + count_Fp + count_F

list.append(count_P)
list.append(count_Fp)
list.append(count_F)
list.append(total)

print (list)

Tips1:append()函式用於在列表末尾新增新的物件。
Tips2:將結果儲存成陣列是為了方便後續將資料寫入新的Excel。

三、寫入新Excel——xlwt

1.目的表格

欲獲得的表格如下:

Bug Summary
sheet1sheet2……sheet n
P
Fp
F
Total

2.建立新Excel並寫入資料

程式碼如下:

workbook = xlwt.Workbook()  #建立空白工作表,注意W大寫
worksheet = workbook.add_sheet('sheet1')  #建立空白工作頁並命名
worksheet.write_merge(0,0,0,nsheets,"Bug Summary",style)  #寫入表頭併合並第一行單元格

i=1
for sheet in sheets:  #對陣列sheets中的資料掃描
  worksheet.write(1,i,sheet,style)  #從第二行第二列開始將資料寫入第二行
  i+=1
worksheet.write(2,0,'P',style)
worksheet.write(3,0,'Fp',style)
worksheet.write(4,0,'F',style)
worksheet.write(5,0,'Total',style)

list1 = list[::4]  #從第一位到最後一位,每隔4位取一個值組成新的陣列,則list1為所有工作頁中P的數量的陣列
list2 = list[1::4]  #從第二位到最後一位,每隔4位取一個值組成新的陣列,則list2為所有工作頁中Fp的數量的陣列
list3 = list[2::4]  #從第三位到最後一位,每隔4位取一個值組成新的陣列,則list3為所有工作頁中F的數量的陣列
list = list[3::4]  #從第四位到最後一位,每隔4位取一個值組成新的陣列,則list4為所有工作頁中Total總數的陣列

#寫入資料
j=1
for num in list1:
  worksheet.write(2,j,num,style)  #在第三行寫入list1
  j+=1

j=1
for num in list2:
  worksheet.write(3,j,num,style)  #在第四行寫入list2
  j+=1

j=1
for num in list3:
  worksheet.write(4,j,num,style)  #在第五行寫入list3
  j+=1

j=1
for num in list4:
  worksheet.write(5,j,num,style)  #在第六行寫入list4
  j+=1

workbook.save('111.xlsx')  #儲存為111.xlsx
print ("Done")  #輸出已完成

Tips1:對於一行資料的陣列,寫入excel時只能按行寫入,所以本程式碼中將陣列進行拆分,按行寫入。
Tips2:

worksheet.write(i,j,num,style)

如果未定義格式,則style可省略,按預設格式錄入。
需要注意的是,帶格式寫入只有以上一種寫法,以下寫法是錯誤的:
worksheet.write(0,0,label=“Bug Summary”,style)

而對於不帶格式寫入,以下兩種寫法都是正確的:

worksheet.write(0,0,label=“Bug Summary”)
worksheet.write(0,0,“Bug Summary”)

Tips3:注意 j+=1,不然會報錯重複寫入。
Tips4:

for num in list

num不需要定義,表示對陣列內容按位讀取。

3.自定義表格樣式

先定義一個空style,再定義字型、邊框。
這是一個設定好格式但允許改變顏色的style,程式碼如下:

① 新建一個style

def set_color(color):
#新建一個style
  style = xlwt.XFStyle()

② 設定字型樣式

font = xlwt.Font()  #新建一個字型樣式
font.name = 'Arial'  #字型
font.bold = True  #黑體加粗
font.colour_index = color  #允許自定義顏色,注意介面中的拼寫為colour
font.underline = True  #下劃線
font.italic = True  #斜體
style.font = font

③ 設定邊框

borders = xlwt.Borders()  #新建一個邊框樣式
borders.left = xlwt.Borders.THIN  #設定左邊框為實線
borders.right = xlwt.Borders.THIN
borders.top = xlwt.Borders.THIN
borders.bottom = xlwt.Borders.THIN
style.borders = borders

Tips: 其他樣式

borders.top = xlwt.Borders.DASHED  #虛線
borders.top = xlwt.Borders.NO_LINE  #無框線

④ 設定對齊方式

alignment = xlwt.Alignment()  #新建一個對齊模板
alignment.horz = xlwt.Alignment.HORZ_CENTER  #水平方向居中對齊
#alignment.horz = xlwt.Alignment.HORZ_LEFT 左對齊
#alignment.horz = xlwt.Alignment.HORZ_RIGHT 右對齊
alignment.vert = xlwt.alignment.VERT_CENTER
#alignment.vert = xlwt.Alignment.VERT_TOP 上對齊
#alignment.vert = xlwt.Alignmnet.VERT_BOTTOM 下對齊
style.alignment = alignment

Tips:其他對齊

#alignment.horz = xlwt.Alignment.HORZ_GENERAL 預設對齊

--------------------------------------------------------------------------

#alignment.horz = xlwt.Alignment.HORZ_FILLED 填滿對齊

--------------------------------------------------------------------------

#alignment.horz = xlwt.Alignment.HORZ_DISTRIBUTED 分散式對齊

⑤ 設定背景色

pattern = xlwt.Pattern()
pattern.pattern = xlwt.Pattern.SOLID_PATTERN  #實填充
pattern.pattern_fore_color = 4  #填充為藍色
style.pattern = pattern


下圖是顏色對照表:

⑥ 設定完成

設定完成後記得:

return style

四、繪製直方圖

繪製直方圖需要用到以下幾個模組

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

1.在直方圖上標註資料

先定義一個在直方圖上標註資料的函式

def autolabel(rects):
  for rect in rects:
    height = rect.get_height()  #獲取高度
    plt.text(rect.get_x() + rect.get_width()/2,height,height)  #標註點的位置為(x的座標+直方的寬度)/2 取中

2.繪製直方圖

程式碼如下:

df = pd.read_excel('111.xlsx','sheet1')  #讀取111.xlsx的sheet1工作頁
fig = plt.figure()

x = np.arange(1,nsheets)  #定義橫座標x的取值陣列,必須為陣列
list1 = list[::4]
list2 = list[1::4]
list3 = list[2::4]  #在其他函式裡需要再取一遍

t0 = plt.bar(x,list1,width=0.3,label='P',fc='b')  #畫出P的直方圖,表示為藍色
t1 = plt.bar(x+0.3,list2,width=0.3,label='Fp',fc='r')  #畫出Fp的直方圖,表示為紅色
t2 = plt.bar(x+0.6,list3,width=0.3,label='F',fc='g')  #畫出F的直方圖,表示為綠色

autolabel(t0)
autolabel(t1)
autolabel(t2)  #用autolabel函式進行標註

plt.legend(['P','Fp','F'])  #繪製右上角的註釋圖
plt.xlabel('case')  #設定橫軸
plt.ylabel('amount')  #設定縱軸
plt.title('summary')  #設定標題
plt.show()  #繪製圖象

繪製的直方圖如下:

五、其他

以下這篇文章對糾錯很有幫助:python操作excel中遇到的錯誤

希望這篇文章對正在學習的你也有幫助,如有疑問歡迎留言o(≧v≦)o~~