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


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

這是一個關於測試報告(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

輸出如下:
輸出為 P--------------------------------------------------------------------------

data = sheet.cell(1,2)

輸出如下:
輸出為 text:‘P’

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
sheet1 sheet2 …… 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 默認對齊

GENERAL--------------------------------------------------------------------------

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

FILLED--------------------------------------------------------------------------

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

DISTRIBUTED

⑤ 設置背景色

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

blue
下圖是顏色對照表:

顏色對照表

⑥ 設置完成

設置完成后記得:

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~~


免責聲明!

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



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