1. 程式人生 > >Python操作Excel檔案

Python操作Excel檔案

與Python中csv模組不同,Python中沒有處理Excel檔案的標準模組,所有需要xlrd和xlwt擴充套件包,這兩個包的具體安裝過程,請大家自行百度,我就不在這多敘述了,本文主要講的是Python對Excel檔案的幾個簡單操作,由於程式碼裡註釋比較詳細,所以本文文字會相對來說會少一下,如有不懂地方,可以私信我。

一、利用xlrd和xlwt進行簡單讀寫Excel檔案:

import sys
from xlrd import open_workbook
'''
利用xlrd模組讀取excel工作簿三個表的name,行數和列數
'''
input_file="E:\\studytest\\data\\excel\\sales_2013.xlsx"
workbook=open_workbook(input_file)
print("Number of worksheets:",workbook.nsheets)
for worksheet in workbook.sheets():
    print("Worksheet name:",worksheet.name,"\tRows:",worksheet.nrows,"\tColumns:",worksheet.ncols)

二、處理單個檔案:

import sys
from xlrd import open_workbook,xldate_as_tuple
from xlwt import Workbook
'''
處理單個工作表
1、讀寫excel檔案
'''
input_file='E:\\studytest\\data\\excel\\sales_2013.xlsx'
output_file='E:\\studytest\\data\\excel_test\\2output.xlsx'
output_workbook=Workbook()
output_worksheet=output_workbook.add_sheet('jan_2013_output')
with open_workbook(input_file) as workbook:
    #根據工作表名字選區工作表
    worksheet=workbook.sheet_by_name('january_2013')
    for row_index in range(worksheet.nrows):
        for column_index in range(worksheet.ncols):
            output_worksheet.write(row_index,column_index,worksheet.cell_value(row_index,column_index))
output_workbook.save(output_file)

但是需要注意的是,當工作表中存在日期格式的列時,寫入時會變成數字,該數字為時間數值與1900年1月1日之間的天數差,為了保證資料的完整性,我們需要對格式為日期的列進行格式化,程式碼如下:

from datetime import date
input_file='E:\\studytest\\data\\excel\\sales_2013.xlsx'
output_file='E:\\studytest\\data\\excel_test\\2output_date.xlsx'
output_workbook=Workbook()
output_worksheet=output_workbook.add_sheet('jan_2013_output')
with open_workbook(input_file) as workbook:
    worksheet=workbook.sheet_by_name('january_2013')
    #迴圈行
    for row_index in range(worksheet.nrows):
        #用於存放構造好的行資料
        row_list_output = []
        #迴圈列
        for column_index in range(worksheet.ncols):
            #type=3表示該列型別為日期
            #若該列為日期格式,則格式化日期
            if worksheet.cell_type(row_index,column_index) == 3:
                date_cell = xldate_as_tuple(worksheet.cell_value(row_index,column_index),workbook.datemode)
                date_cell = date(*date_cell[0:3]).strftime('%m/%d/%Y')
                row_list_output.append(date_cell)
                output_worksheet.write(row_index,column_index,date_cell)
            #否則直接拼接row_list_output
            else:
                non_date_cell = worksheet.cell_value(row_index,column_index)
                row_list_output.append(non_date_cell)
                output_worksheet.write(row_index,column_index,non_date_cell)
output_workbook.save(output_file)

在處理單個檔案時,我們經常會有篩選特定的行的需求,而篩選特定存在一下三種情況:

1、行中某列數值滿足某個條件;

2、行中某列數值在某個集合裡;

3、行中某列的值匹配於特定的模式。

三種情況程式碼大致相同,本文只列出第一種情況的程式碼,大家可以試著做一下後兩中。

2、篩選特定行
 2、1 行中的值滿足某個條件
 2、2 行中的值屬於某個集合(和上面的差不多,判斷條件改成in A集合)
 2、3 行中的值匹配於特定的模式(和上面的差不多,判斷條件改成pattern.search(數值))
'''
from datetime import date
input_file='E:\\studytest\\data\\excel\\sales_2013.xlsx'
output_file='E:\\studytest\\data\\excel_test\\4output.xlsx'
output_workbook=Workbook()
output_worksheet=output_workbook.add_sheet('jan_2013_output')
#條件:第四列的值
sale_amount_column_index=3
with open_workbook(input_file) as workbook:
    worksheet=workbook.sheet_by_name('january_2013')
    data = []
    #取表頭
    header = worksheet.row_values(0)
    data.append(header)
    #迴圈第1行到最後一行
    for row_index in range(1,worksheet.nrows):
        #用於存放構造好的行資料
        row_list_output = []
        #取出需要判斷列的值,比如某列值大於1400
        sale_amount = worksheet.cell_value(row_index,sale_amount_column_index)
        if sale_amount > 1400.0:
            #迴圈該列
            for column_index in range(worksheet.ncols):
                #type=3表示該列型別為日期
                #若該列為日期格式,則格式化日期
                if worksheet.cell_type(row_index,column_index) == 3:
                    date_cell = xldate_as_tuple(worksheet.cell_value(row_index,column_index),workbook.datemode)
                    date_cell = date(*date_cell[0:3]).strftime('%m/%d/%Y')
                    row_list_output.append(date_cell)
                #否則直接拼接row_list_output
                else:
                    non_date_cell = worksheet.cell_value(row_index,column_index)
                    row_list_output.append(non_date_cell)
            if row_list_output:
                data.append(row_list_output)
    #此處用迭代的原因是因為,如果直接寫入的話,會導致索引也寫入到新檔案中,寫入後的檔案會出現空白行的情況
    for list_index,output_list in enumerate(data):
        for element_index,element in enumerate(output_list):
            output_worksheet.write(list_index,element_index,element)
output_workbook.save(output_file)

大家可以看一下,上面程式碼倒數第四行用到了迭代,為什麼要用迭代吶,因為直接寫入時會把行的索引也寫入到新檔案中,就會導致檔案出現空白行的現象,如下圖:



所以,為了避免出現這種情況,這裡使用了迭代,後面的所有程式碼中凡是利用迭代實現,都是為了避免這種情況的出現。

當然,除了篩選特定行,我們還會有篩選特定列的需求,篩選特定列存在一下兩種方法:

1、根據列索引來篩選,工作表中每個列都有一個對應的索引值,從0開始;

2、根據列標題來篩選,其中這種篩選方法和1原理一樣,先根據列標題找出對應的索引值,單後根據索引值篩選,好處是不會出錯,只要列標題正確,篩選的結果就不會出錯。

下面是兩種方法的實現程式碼:

'''
3、選取特定的列
 3、1 根據列索引值
'''
from datetime import date
input_file='E:\\studytest\\data\\excel\\sales_2013.xlsx'
output_file='E:\\studytest\\data\\excel_test\\7output.xlsx'
output_workbook=Workbook()
output_worksheet=output_workbook.add_sheet('jan_2013_output')
#條件:只取索引號為1和4的兩列
my_columns = [1,4]
with open_workbook(input_file) as workbook:
    worksheet=workbook.sheet_by_name('january_2013')
    data = []
    for row_index in range(worksheet.nrows):
        #用於存放構造好的行資料
        row_list = []
        #迴圈滿足條件的列
        for column_index in my_columns:
            cell_value = worksheet.cell_value(row_index,column_index)
            cell_type = worksheet.cell_type(row_index,column_index)
            #type=3表示該列型別為日期
            #若該列為日期格式,則格式化日期
            if cell_type == 3:
                date_cell = xldate_as_tuple(cell_value,workbook.datemode)
                date_cell = date(*date_cell[0:3]).strftime('%m/%d/%Y')
                row_list.append(date_cell)
            #否則直接拼接row_list_output
            else:
                row_list.append(cell_value)
        data.append(row_list)
    #此處用迭代的原因是因為,如果直接寫入的話,會導致索引也寫入到新檔案中,寫入後的檔案會出現空白行的情況
    for list_index,output_list in enumerate(data):
        for element_index,element in enumerate(output_list):
            output_worksheet.write(list_index,element_index,element)
output_workbook.save(output_file)
'''
 3、2 根據列標題選取(同上,先根據標題選出列索引值,然後再使用列索引值)
'''
from datetime import date
input_file='E:\\studytest\\data\\excel\\sales_2013.xlsx'
output_file='E:\\studytest\\data\\excel_test\\8output.xlsx'
output_workbook=Workbook()
output_worksheet=output_workbook.add_sheet('jan_2013_output')
#條件:只取索引號為1和4的兩列
my_columns = ['Customer ID','Purchase Date']
with open_workbook(input_file) as workbook:
    worksheet=workbook.sheet_by_name('january_2013')
    data = [my_columns]
    #取出列標題行
    header_list=worksheet.row_values(0)
    header_index_list = []
    #迴圈標題列表,找出符合條件列的索引號
    for header_index in range(len(header_list)):
        if header_list[header_index] in my_columns:
            header_index_list.append(header_index)
    for row_index in range(1,worksheet.nrows):
        #用於存放構造好的行資料
        row_list = []
        #迴圈滿足條件的列
        for column_index in header_index_list:
            cell_value = worksheet.cell_value(row_index,column_index)
            cell_type = worksheet.cell_type(row_index,column_index)
            #type=3表示該列型別為日期
            #若該列為日期格式,則格式化日期
            if cell_type == 3:
                date_cell = xldate_as_tuple(cell_value,workbook.datemode)
                date_cell = date(*date_cell[0:3]).strftime('%m/%d/%Y')
                row_list.append(date_cell)
            #否則直接拼接row_list_output
            else:
                row_list.append(cell_value)
        data.append(row_list)
    #此處用迭代的原因是因為,如果直接寫入的話,會導致索引也寫入到新檔案中,寫入後的檔案會出現空白行的情況
    for list_index,output_list in enumerate(data):
        for element_index,element in enumerate(output_list):
            output_worksheet.write(list_index,element_index,element)
output_workbook.save(output_file)

三、處理工作簿中多個Excel工作表

在處理多個Excel檔案時,我們基本的操作和單個相似,有如下三種:

1、選取特定的行;(存在三種情況,請參看二中處理單個檔案)

2、選取特定的列;(存在兩種方法,請參看二中處理單個檔案)

3、選取特定的工作表(一個工作簿中存在多個Excel工作表,有時候我們並不是都需要處理,這個時候我們就可以根據條件來處理相應的檔案)

三種情況程式碼如下:

1、選取特定的行;

'''
讀取工作簿中的所有工作表
1、在所有工作表中篩選特定行
'''
import sys
from datetime import date
from xlrd import open_workbook,xldate_as_tuple
from xlwt import Workbook
input_file='E:\\studytest\\data\\excel\\sales_2013.xlsx'
output_file='E:\\studytest\\data\\excel_test\\10output.xlsx'
output_workbook=Workbook()
output_worksheet=output_workbook.add_sheet('filtered_rows_all_worksheets')
sale_column_index = 3
threshold = 2000.0
first_worksheet = True
with open_workbook(input_file) as workbook:
    data = []
    for worksheet in workbook.sheets():
        if first_worksheet:
            header_row=worksheet.row_values(0)
            data.append(header_row)
            first_worksheet= False
        for row_index in range(1,worksheet.nrows):
            row_list = []
            sale_amount=worksheet.cell_value(row_index,sale_column_index)
            if sale_amount > threshold:
                for column_index in range(worksheet.ncols):
                    cell_value = worksheet.cell_value(row_index,column_index)
                    cell_type = worksheet.cell_type(row_index,column_index)
                    if cell_type == 3:
                        date_cell=xldate_as_tuple(cell_value,workbook.datemode)
                        date_cell=date(*date_cell[0:3]).strftime('%m/%d/%Y')
                        row_list.append(date_cell)
                    else:
                        row_list.append(cell_value)
            if row_list:
                data.append(row_list)
    for list_index,output_list in enumerate(data):
        for element_index,element in enumerate(output_list):
            output_worksheet.write(list_index,element_index,element)
output_workbook.save(output_file)

2、篩選特定列:

'''
2、在所有工作表中篩選特定列
    根據前面操作單工作表的程式碼,我們可以發現這個地方存在兩種方法,一是根據索引值;二是根據列標題。我們以第二種為例。
'''
import sys
from datetime import date
from xlrd import open_workbook,xldate_as_tuple
from xlwt import Workbook
input_file='E:\\studytest\\data\\excel\\sales_2013.xlsx'
output_file='E:\\studytest\\data\\excel_test\\10output.xlsx'
output_workbook=Workbook()
output_worksheet=output_workbook.add_sheet('selected_columns_all_worksheets')
#條件,取列標題為XX的兩列
my_columns = ['Customer Name','Sale Amount']
first_worksheet = True
with open_workbook(input_file) as workbook:
    data = [my_columns]
    #存放列標題對應的索引值
    index_of_cols_to_keep = []
    for worksheet in workbook.sheets():
        if first_worksheet:
            header_row=worksheet.row_values(0)
            for column_index in range(len(header_row)):
                if header_row[column_index] in my_columns:
                    index_of_cols_to_keep.append(column_index)
            first_worksheet= False
        for row_index in range(1,worksheet.nrows):
            row_list = []
            for column_index in index_of_cols_to_keep:
                cell_value = worksheet.cell_value(row_index,column_index)
                cell_type = worksheet.cell_type(row_index,column_index)
                if cell_type == 3:
                    date_cell=xldate_as_tuple(cell_value,workbook.datemode)
                    date_cell=date(*date_cell[0:3]).strftime('%m/%d/%Y')
                    row_list.append(date_cell)
                else:
                    row_list.append(cell_value)
            data.append(row_list)
    for list_index,output_list in enumerate(data):
        for element_index,element in enumerate(output_list):
            output_worksheet.write(list_index,element_index,element)
output_workbook.save(output_file)

3、選取特定的工作表

'''
3、在excel工作簿中讀取一組工作表
'''
import sys
from datetime import date
from xlrd import open_workbook,xldate_as_tuple
from xlwt import Workbook
input_file='E:\\studytest\\data\\excel\\sales_2013.xlsx'
output_file='E:\\studytest\\data\\excel_test\\11output.xlsx'
output_workbook=Workbook()
output_worksheet=output_workbook.add_sheet('set_of_worksheets')
#條件,取索引號為0和1的兩個工作表
my_sheets = [0,1]
first_worksheet = True
with open_workbook(input_file) as workbook:
    data = []
    #迴圈工作簿中每個工作表
    for sheet_index in range(workbook.nsheets):
        #判斷是否為需要處理的工作表
        if sheet_index in my_sheets:
            # 找到符合要求的工作表,並取出表內容
            worksheet = workbook.sheet_by_index(sheet_index)
            if first_worksheet:
                header_row=worksheet.row_values(0)
                data.append(header_row)
                first_worksheet= False
            for row_index in range(1,worksheet.nrows):
                row_list = []
                for column_index in range(worksheet.ncols):
                    cell_value = worksheet.cell_value(row_index,column_index)
                    cell_type = worksheet.cell_type(row_index,column_index)
                    if cell_type == 3:
                        date_cell=xldate_as_tuple(cell_value,workbook.datemode)
                        date_cell=date(*date_cell[0:3]).strftime('%m/%d/%Y')
                        row_list.append(date_cell)
                    else:
                        row_list.append(cell_value)
                if row_list:
                    data.append(row_list)
    for list_index,output_list in enumerate(data):
        for element_index,element in enumerate(output_list):
            output_worksheet.write(list_index,element_index,element)
output_workbook.save(output_file)

四、處理多個工作簿

1、工作表計數和每個工作表中行列的計數:

'''
處理多個工作簿
1、工作表計數以及每個工作表中的行列計數
'''
import glob
import os
import sys
from xlrd import open_workbook
input_directory = 'E:\\studytest\\data\\excel'
workbook_counter = 0
for input_file in glob.glob(os.path.join(input_directory,'*.xlsx')):
    workbook = open_workbook(input_file)
    print('Workbook:%s'%os.path.basename((input_file)))
    print('Number of worksheets:%d'%workbook.nsheets)
    for worksheet in workbook.sheets():
        print('Worksheet name:',worksheet.name,'\tRows:',worksheet.nrows,'\tColumns:',worksheet.ncols)
    workbook_counter += 1
print('Number of Excel workbooks:%d'%(workbook_counter))

2、從多個工作簿中連線資料:

下面程式碼實現的是將多個工作簿中資料放到一個Excel工作表中

'''
2、從多個工作簿中連線資料
'''
import glob
import os
import sys
from datetime import date
from xlrd import open_workbook,xldate_as_tuple
from xlwt import Workbook
input_directory = 'E:\\studytest\\data\\excel'
output_file = 'E:\\studytest\\data\\excel_test\\13output.xlsx'
output_workbook = Workbook()
output_worksheet = output_workbook.add_sheet('all_data_all_workbooks')
data = []
first_worksheet = True
#迴圈多個工作簿
for input_file in glob.glob(os.path.join(input_directory,'*.xls*')):
   print(os.path.basename(input_file))
   #開啟當前工作簿
   with open_workbook(input_file) as workbook:
       #迴圈當前工作簿的每個工作表
       for worksheet in workbook.sheets():
           if first_worksheet:
               header_row = worksheet.row_values(0)
               data.append(header_row)
               first_worksheet = False
            #迴圈行
           for row_index in range(1,worksheet.nrows):
               row_list = []
               #迴圈列
               for column_index in range(worksheet.ncols):
                    cell_value = worksheet.cell_value(row_index,column_index)
                    cell_type = worksheet.cell_type(row_index,column_index)
                    if cell_type == 3:
                        date_cell = xldate_as_tuple(cell_value,workbook.datemode)
                        date_cell = date(*date_cell[0:3]).strftime('%m/%d/%Y')
                        row_list.append(date_cell)
                    else:
                        row_list.append(cell_value)
               data.append(row_list)
for list_index,output_list in enumerate(data):
    for element_index,element in enumerate(output_list):
        output_worksheet.write(list_index,element_index,element)
output_workbook.save(output_file)

3、為每個工作簿和工作表計算總數和均值

'''
3、為每個工作簿和工作表計算總數和均值
'''
import glob
import os
import sys
from datetime import date
from xlrd import open_workbook,xldate_as_tuple
from xlwt import Workbook
input_directory = 'E:\\studytest\\data\\excel'
output_file = 'E:\\studytest\\data\\excel_test\\14output.xlsx'
output_workbook = Workbook()
output_worksheet = output_workbook.add_sheet('sums_and_averages')
all_data = []
#對索引號為3的列求總值和平均值
sale_column_index = 3
#輸出檔案列標題
header = ['workbook','worksheet','worksheet_total','worksheet_average','workbook_total','workbook_average']
all_data.append(header)
#迴圈多個工作簿
for input_file in glob.glob(os.path.join(input_directory,'*.xls*')):
   #開啟當前工作簿
   with open_workbook(input_file) as workbook:
       #存放當前工作簿所求列的總值
       list_of_totals = []
       # 存放當前工作簿所求列的個數
       list_of_number = []
       workbook_output = []
       #迴圈當前工作簿的每個工作表
       for worksheet in workbook.sheets():
           #當前工作表所求列總值
           total_sales = 0
           #當前工作表所求列個數
           number_of_sales = 0
           #存放當前工作表的名字,總值,平均值
           worksheet_list = []
           worksheet_list.append(os.path.basename(input_file))
           worksheet_list.append(worksheet.name)
            #迴圈行
           for row_index in range(1,worksheet.nrows):
               try:
                   total_sales += float(str(worksheet.cell_value(row_index,sale_column_index)))
                   number_of_sales += 1
               except:
                   total_sales += 0
                   number_of_sales += 0
           average_sales = '%.2f'%(total_sales/number_of_sales)
           worksheet_list.append(total_sales)
           worksheet_list.append(float(average_sales))
           list_of_totals.append(total_sales)
           list_of_number.append(float(average_sales))
           workbook_output.append(worksheet_list)
       workbook_total = sum(list_of_totals)
       workbook_average = sum(list_of_totals)/sum(list_of_number)
       for list_element in workbook_output:
           list_element.append(workbook_total)
           list_element.append(workbook_average)
       all_data.extend(workbook_output)

for list_index,output_list in enumerate(all_data):
    for element_index,element in enumerate(output_list):
        output_worksheet.write(list_index,element_index,element)
output_workbook.save(output_file)

由於程式碼相對基礎,所以我只貼出來比較細節的程式碼結果截圖,其餘的大家可以根據程式碼自己實現一下看看效果,使用以上程式碼只需要修改程式碼前幾號檔案的路徑即可。

如有什麼問題和疑問,請私信我,我會在第一時間幫你解決!謝謝支援