python對excel文件的處理


python處理excel文件有很多方法,最開始接觸的是xlrd、xlsxwriter模塊,分別用於excel文件的讀、寫。后來又學習了openpyxl模塊,可以同時完成excel文件的讀、寫。再后來,接觸了大牛pandas,這是python中專門用於數據分析的模塊,有更加強大的功能。

本文嘗試梳理一下這幾個方法,以實際案例來對比各種方法的優劣。

1. xlrd、xlsxwriter模塊

 1 import xlrd  #讀取excel文件
 2 import xlsxwriter  #寫入excel文件
 3 file_name = r'C:/2020/python-exer/excel_doc/time_fmt.xls'  #存在一個excel文件,用於讀
 4 file_name1 = r'C:/2020/python-exer/excel_doc/time_fmt_output.xls'  #新建一個excel文件,用於寫
 5 # 讀取excel文件,按行讀取數據,每行數據對應一個列表元素
 6 def excel_lines():
 7    wb = xlrd.open_workbook(file_name)
 8    # 打開Excel文件
 9    sheet1 = wb.sheet_by_name('Sheet1')  # 通過excel表格sheet名稱獲取工作表
10    dat = []  # 創建空list
11    Max_lines = sheet1.nrows  # sheet1數據最大行數,即便每列元素不同。
12    print(Max_lines)
13    for a in range(Max_lines):
14       cells = sheet1.row_values(a)  # 每行數據賦值給cells
15       dat.append(cells)
16    return dat
View Code

 

#>>>[['序號', '時間格式定義'], [1.0, '%a    Locale’s abbreviated weekday name.     '], 
[2.0, '%A    Locale’s full weekday name.     '],
……
從輸出內容看出,得到的是一個嵌套list,每行數據對應着一個list元素。
# 讀取excel文件,按列讀取數據,每列數據對應一個列表元素
 1 def excel_cols():
 2    wb = xlrd.open_workbook(file_name)
 3    # 1 打開Excel文件,按照名字獲取第一個工作表
 4    # sheet1 = wb.sheet_by_name('Sheet1')  # 通過excel表格sheet名稱獲取工作表
 5    # 2 Excel的所有sheet是個列表,通過索引獲取第一個工作表
 6    sheet1 = wb.sheets()[0]
 7    # 3 通過索引獲取第一個工作表,這種方法有明顯優勢,不需要知道excel的sheet名稱。與#3方法相同
 8    #   最大的優勢能用for循環,遍歷所有的sheet。
 9    # sheet1 =  wb.sheet_by_index(0)
10    # sheet_2= wb.sheets()[1]
11    # print(sheet_2.col_values(0))
12 
13    dat = []  # 創建空list
14    global Max_rows
15    Max_cols = sheet1.ncols  # sheet1數據最大列數
16    Max_rows = sheet1.nrows  # sheet1數據最大行數
17    print("Max_rows:", Max_rows)
18    print("Max_cols:", Max_cols)
19    for a in range(Max_cols):
20       cells = sheet1.col_values(a)  # 每列數據賦值給cells
21       dat.append(cells)  # 每列數據追加到列表dat,那么dat就是以列數據為元素的列表
22    return dat
View Code

 

#>>> [['序號', 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, 
20.0, 21.0, 22.0, 23.0, 24.0, '', ''], ['時間格式定義', '%a    Locale’s abbreviated weekday name.     ', ……

從上面的輸出結果看,按照excel文件的列讀取數據,生成嵌套list,每一列對應一個list元素
#寫入excel文件,新建sheet用於保存數據
 1 def write_excel():
 2    a = excel_cols()
 3    excel_cols = []  # 保存列值的列表
 4    excel_cols_comment = []  # 保存列注釋的列表
 5 
 6    for i in range(Max_rows):
 7       if i == 0:
 8          # square_col.append(a[1][0])      #專門取列的頭,實際上為了方便以后的數據處理。
 9          print("列的名字:", a[1][0])
10       else:
11          excel_cols.append(a[1][i][:3])  #:2只取該元素的前2位,去掉后面的注釋。
12          excel_cols_comment.append(a[1][i][5:])  # 上面列的注釋,取字符串5:
13 
14    print("獲取格式化time參數: \n", excel_cols)
15    print("獲取time參數的說明: \n", excel_cols_comment)
16 
17    workbook_w = xlsxwriter.Workbook(file_name1)
18    sheet2 = workbook_w.add_worksheet("output_sheet")
19    for i in range(Max_rows):  # 因列名單獨處理了,所以真正的列元素數要比總數-1
20       # strf_time = time.strftime(excel_cols[i])  # 調用時間模塊函數,參數為每列的值
21       # comment = excel_cols_comment[i]
22       if i == 0:  # 每個列的第一行,列名。i代表行號,如果是很多列,也可以再增加j循環,表示列號
23          sheet2.write(i, 0, f"格式化時間參數:time.strftime")
24          sheet2.write(i, 1, f"執行結果") 
25          sheet2.write(i, 2, f"注釋")
26       else:  # 每個列,從第二行開始循環寫入
27          ##下面的i-1,原因在於i是人為的把列頭編寫輸出。而對於列表元素來說,索引從0開始。
28          strf_time = time.strftime(excel_cols[i - 1])  # 調用時間模塊函數,參數為每列的值
29          comment = excel_cols_comment[i - 1]
30          sheet2.write(i, 0, f"({repr(excel_cols[i - 1])})")
31          # 注意這里的i-1,前面的i與excel表格相關,后面的i-1是因為列的元素還是從0開始。
32 
33          sheet2.write(i, 1, f"{strf_time}")
34          sheet2.write(i, 2, f"{comment}")
35    print("寫入成功")
36    workbook_w.close()
View Code

 

以上的程序,實際的關鍵點在於sheet.write函數的參數處理,第一個參數是行,第二個參數是列,第三個參數是寫入的數據。其他的語句都是針對數據的具體化處理。

2.openpyxl模塊,既可以讀、也可以寫
import openpyxl
from openpyxl import load_workbook

# 1.載入已存在的Excel
filename = r'C:\2020\python-exer\excel_doc\test.xlsx'
wb = load_workbook(filename)
# 注意load_workbook只能打開已經存在的Excel,不能創建新的工作簿
# 2.根據名稱獲取工作表
# Workbook對象屬性(工作簿操作)
# sheetnames:獲取工作簿中的表(列表)
# active:獲取當前活躍的Worksheet
# worksheets:以列表的形式返回所有的Worksheet(表格)
# read_only:判斷是否以read_only模式打開Excel文檔
# encoding:獲取文檔的字符集編碼
# properties:獲取文檔的元數據,如標題,創建者,創建日期等
 1 def get_properties():  ##獲取excel的sheet屬性函數
 2    print(wb.sheetnames)  # >>>['Sheet1', '2表單12']
 3    print(wb.active)  # >>><Worksheet "2表單12">
 4    print(wb.worksheets)  # >>>[<Worksheet "Sheet1">, <Worksheet "2表單12">]
 5    print(wb.read_only)  # >>>False
 6    print(wb.encoding)  # >>>utf-8
 7    print(wb.properties)  # 獲取文檔的元數據,如標題,創建者,創建日期等
 8    print(wb.properties.creator, wb.properties.title)  # >>>openpyxl None
 9    wb.properties.title = 'test-openpyxl'  # >>>修改屬性中的title
10    print(wb.properties.title)
11    print(wb.properties)  # 確實修改了titile。
12 # 3.Worksheet,Cell對象(工作表操作,單元格)。獲取execl的sheet一般信息的函數
13 def get_sheet_info():  
14    global sheet
15    sheet = wb['Sheet1']
16    # 獲取工作表的名稱
17    print(sheet.title)  # >>>Sheet1
18    # 獲取工作表中行和列的最值
19    print(sheet.max_column)  # >>>2
20    print(sheet.max_row)  # >>>27
21    print(sheet.min_column)  # >>>1
22    print(sheet.min_row)  # >>>1
23    ##修改表的名稱
24    sheet.title = '時間參數'
25    print(sheet.title)  # >>>時間參數
26    # 返回指定行指定列的單元格信息
27    print(sheet.cell(row=1, column=2).value)  # >>>時間格式定義
28    cell = sheet['B1']
29    print(cell)  # >>><Cell '時間參數'.B1>。注意cell是對象,下面是具體的屬性:
30    print(cell.row, cell.column, cell.value, cell.coordinate)
31    # >>>1 2 時間格式定義 B1
32    # sheet的屬性,sheet是一個類:
33    print("sheet:", sheet, type(sheet))
34 # 4.訪問單元格的所有信息,rows是sheet的一個屬性。該sheet的所有行信息。
35 def get_sheet_rows():
36    print(sheet.rows)  ##是一個生成器
37    ##<generator object Worksheet._cells_by_row at 0x000001806C22D820>
38    for row in sheet.rows:
39       # 循環遍歷每一個單元格
40       for cell in row:
41          # 獲取單元格的內容
42          print(cell.value, end=',')
43       print()
View Code

 

#>>>

序號,時間格式定義,
1,%a Locale’s abbreviated weekday name. ,
2,%A Locale’s full weekday name. ,
3,%b Locale’s abbreviated month name. ,
4,%B Locale’s full month name. ,……

通過以上輸出,按照excel的每行輸出內容。

#5openpyxl寫入excel
 1 def save_to_excel(data, wbname, sheetname='Sheet1'):
 2    """
 3    將以下信息保存到excel表中;
 4    [[' BOOK', 50, 3], ['APPLE', 100, 1], ['BANANA', 200, 0.5]]
 5    """
 6    print("寫入Excel[%s]中......." % (wbname))
 7    # 打開excel表, 如果文件不存在, 自己實例化一個WorkBook對象
 8    wb = openpyxl.Workbook()
 9    # 獲取當前工作表
10    sheet = wb.active
11    # 修改工作表的名稱
12    sheet.title = sheetname
13 
14    data.insert(0,head_line)        #重新插入表頭。
15    for row, item in enumerate(data):  # 0 [' BOOK', 50, 3]
16       ##使用枚舉函數的好處,不用求元素總數len了。
17       for column, cellValue in enumerate(item):  # 0 ' BOOK'
18          sheet.cell(row=row + 1, column=column + 1, value=cellValue)
19 
20    # ** 往單元格寫入內容
21    # sheet.cell['B1'].value = "value"
22    # sheet.cell(row=1, column=2, value="value")
23 
24    # 保存寫入的信息
25    wb.save(filename=wbname)
26    print("寫入成功!")
View Code

 

小結:通過對xlrd、xlswriter及openpyxl的應用案例,本質上都是把excel當做一個數據文件進行讀寫。只不過openpyxl既能讀又能寫罷了。而pandas是把excel當做
數據塊或者說是矩陣來處理。如同處理csv一樣,讀入的數據認為是dataframe,可以有更多的數據分析功能。

3.pandas對excel文件的處理,可以同時寫入多個sheet數據。
 1 import pandas as pd
 2 from pandas import DataFrame
 3 filename = r'C:\2020\python-exer\excel_doc\pandas_excel.xlsx'
 4 write_filename = r'C:\2020\python-exer\excel_doc\pandas_excel_1.xlsx'
 5 csv_file=r'C:\2020\python-exer\excel_doc\pandas_excel_1.csv'
 6 def pandas_write_excel():
 7    # 創建新的Excel文件。如果是已有的Excel文件,見下面的read函數。
 8    # 准備字典數據,之所以引入list_dict[],為了實現同一個excel表同時寫入多個sheet(可以是不同數據)。
 9    # 字典的鍵會被當做列索引。行索引自動增加1個序號數字列。如果是1個嵌套列表,DF會自動加上序號行作為列的索引。也會增加序號列作為行的索引。
10    list_dict = []
11    dict1 = {'標題列1': ['張三', '李四'],
12             '標題列2': [80, 90],
13             '標題列3': [30, 40],
14             '標題列4': [50, 70],
15             }
16    dict2 = {'姓名': ['張三', '李四', '王五'],
17             '數學': [80, 90, 70],
18             '語文': [30, 40, 89],
19             '英語': [50, 70, 76],
20             }
21 
22    for i in range(5):
23       list_dict.append(dict1)  # 生成1個大列表,每個元素都是1個dict。
24    # df = DataFrame(dict1)
25    # print(df)
26    '''#>>>在原始數據前面加入序號列。
27    標題列1  標題列2  標題列3  標題列4
28 0   張三    80        30    50
29 1   李四    90        40    70
30    '''
31    ##1pandas的df就是一個數據矩陣,天生與excel同構。所以可以直接寫入excel:
32    # df.to_excel(filename, index=False)  ##只寫入1個sheet,不需要save、close。
33    writer = pd.ExcelWriter(filename)
34    ##2 如果需要同時寫入多個sheet,引入writer。而#1只是寫入一個sheet。
35    for i in range(4):
36       df = DataFrame(list_dict[i])
37       df.to_excel(excel_writer=writer, sheet_name=f"班級{i}", index=False)
38    df = DataFrame(dict2)
39    # DataFrame可以把dict轉變為寫入的格式,如果index=True增加了第一列序號。如果index為False寫入的excel沒有序號
40    print(df)
41    df.to_excel(excel_writer=writer, sheet_name="高級班", index=True)
42    # 按列寫入字典,index為True,寫入的excel有序號。
43    writer.save()
44    # writer.close()      #這個比較奇葩,打開excel根本無法寫入。關閉狀態下這條語句會有警告。到底是否需要關閉?
45    print('寫入成功!')
46 # 寫入單個sheet函數,當打開一個文件的時候,如果有多個sheet,用這個函數只保留1個sheet。
47 # 如果想同時寫入多個sheet用前面的函數。
48 def write_sheet(write_filename, Sheet_data, Sheet_name):
49    with pd.ExcelWriter(write_filename) as writer:
50       df = DataFrame(Sheet_data)
51       # #這里data是一個列表,而之前的函數是寫入字典,所以會有問題。而且data並不完全是原始數據。增加了序號列。
52       df.to_excel(excel_writer=writer, sheet_name=Sheet_name, index=False)
53       # index為False不寫入序號。否則,寫入序號。
54       writer.save()
55       print('寫入成功!')
View Code

 

下面比較一下讀寫excel文件和csv文件的異同:
 1 def write_read_csv(data):
 2    ##csv文件的寫入、讀取。感覺比excel簡單,至少沒有多個sheet的情況。
 3    #而且,csv文件打開的時候也是可以進行寫操作的。而Excel文件不可以。
 4    data_df = DataFrame(data)
 5    # print(data_df)
 6    data_df.to_csv(csv_file,index=False)
 7    #index=False,不寫序號列。
 8    print("寫入csv成功")
 9    data=pd.read_csv(csv_file)
10    print("讀取csv文件數據:\n",data)
11    #讀出的結果與上面讀取excel一致,原始數據前面加上了序號列。
12    print("讀取csv成功")
View Code

 


小結:對於pandas來說,有了DataFrame,寫入Excel和寫入CSV可以根據需求可以同時進行,只是對應pandas模塊不同的讀寫函數而已。

總結上述,對於python來說,處理excel文件有很多的方法,但感覺pandas方法是更方便的,更接近數據處理,有更豐富的處理技巧。而其他模塊都是取出excel的行或者列數據,
再依照python的語言功能對這些數據進行進一步處理。
 


免責聲明!

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



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