現代生活中,咱們很難不與excel表打交道,excel表有着易學易用的優勢,只是當表中數據量很大,咱們又須要從其餘表冊中複製粘貼一些數據(好比身份證號)的時候,咱們會愈來愈倦怠,畢竟咱們不是機器,無法長時間作某種重複性的枯燥操做。想象這樣一個場景,咱們有個幾千行的表要填,須要根據姓名輸入其對應的身份證號,但以前咱們已經作過一個相似的表,一樣的一些人的姓名跟身份證號是完整的,那麼咱們就須要經過一個個查找姓名,而後把身份證號碼複製到咱們當前要作的表裏去。html
當我日復一日重複着這些操做的時候,我都很想有一個自動化工具來完成這種操做,把作爲人的我從這種非人的折磨裏解脫出來,最後仍是想到了python,由於這樣我能不多的關注語言內部的一些細節,從而專一於解決這個問題。python
python有不少專門處理excel的第三方庫,我選擇了openpyxl,由於支持微軟最新excel的格式xlsx,其官網地址爲openpyxl.readthedocs.io/en/latest/i…,官網上的教程很全面,有其餘需求的能夠好好研究一番。git
其安裝命令爲 pip install openpyxl
(在線安裝)或者 easy_install openpyxl
。github
openpyxl的操做能夠分四步,第一步載入現有workbook或者建立workbook到內存,分別使用bash
from openpyxl import load_workbook
from openpyxl import Workbook
#載入現有workbook中
wb1=load_workbook('lalala.xlsx')
""" 在源表數據量很大的時候,這裏咱們可使用openpyxl的read_only模式 載入源表,這樣作的好處是不用把整個表都載入內存 """
wb1=load_workbook(filename='lalala.xlsx',read_only=True)
#建立workbook
wb2 = Workbook()
複製代碼
第二步就是操做excel表中的sheet了,經過Workbook()建立的workbook默認活動的sheet名稱爲Sheet,能夠經過python交互命令行進行驗證。編輯器
#獲取活動的sheet
ws = wb.active
#設置sheet的標題
ws.title = "range names"
#建立以Pi爲標題的sheet
ws = wb.create_sheet(title="Pi")
#獲取標題爲Sheet1的sheet
ws=wb['Sheet1']
複製代碼
第三步就是操做sheet中的cell了。須要注意的是,一個cell的位置由它所在的列跟行共同決定,好比一個cell,它在A列,並在第三行,就能夠經過ws['A3']
來訪問。cell還具備row跟column屬性,cell.row跟cell.column的數據類型以下圖所示。 函數
特別注意當用read_only模式載入workbook時,cell.row跟cell.column都是int對象。cell.column記錄的是cell所在列離第一列的偏移數,並不是workbook中真正表明列數的大寫字母,好比「A」。工具
#獲取第一行,數據類型爲tuple
row=ws[1]
#獲取A列,數據類型爲tuple
column=ws['A']
#設置F5的值
ws['F5']='sfs'
#設置cell的值
ws['F5'].value='hello'
#得到cell的行數
m=ws['F5'].row
#得到cell的列數
n=ws['F5'].column
#得到特定區域的值,好比從F5到F30,數據類型爲tuple
k=ws['F5':'F30']
#得到特定區域的值,好比從F5到G30,數據類型爲tuple
j=ws['F5':'G30']
#獲取sheet的最大行數
row_count=ws.max_row
#獲取sheet的最大列數
column_count=ws.max_column
複製代碼
最後一步把更改保存,這裏要注意,當要保存的表在別的軟件(microsoft office或者wps)中打開時,保存操做會報錯。測試
wb1.save('empty_book.xlsx')
wb2.save(filename='other_book.xlsx')
複製代碼
新建一個get_info_from_excel.py文件,用你習慣的編輯器來編輯,首先須要引入openpyxl庫中的load_workbook模塊。可使用load_workbook載入已經存在的excel表。ui
from openpyxl import load_workbook
複製代碼
咱們的目的是從源excel表中提取信息並批量複製到目標excel表中,因此咱們首先定義一些變量。
#源表名稱
source_file_name='lalala.xlsx'
#目標表名稱
target_file_name='lelele.xlsx'
#源表中要提取信息的sheet
source_sheet_name='Sheet2'
#目標表中要批量複製信息的sheet
target_sheet_name='Sheet2'
#源表中的標題行在哪一行
source_header_row=3
#目標表中的標題行在哪一行
target_header_row=2
#源表中要根據哪一列數據提取信息,根據源表標題行
source_cell_condition='姓名'
#目標表中要根據哪一列數據複製信息,根據目標表標題行
target_cell_condition='姓名'
#源表中要提取信息的列
source_cell_filled='身份證號'
#目標表中要複製信息的列
target_cell_filling='身份證號'
複製代碼
將源表跟目標表載入內存,方便下一步操做這兩個表。
#在源表數據量很大的時候,這裏咱們可使用openpyxl的read_only模式載入源表,這樣作的好處是不用把整個表都載入內存
#wb_w=load_workbook(source_file_name)
wb_r=load_workbook(filename=source_file_name,read_only=True)
wb_w=load_workbook(target_file_name)
複製代碼
從前面已經定義的sheet名稱跟標題行數獲取源表跟目標表的標題行:
ws_r=wb_r[source_sheet_name]
ws_w=wb_w[target_sheet_name]
header_row_r=ws_r[source_header_row]
header_row_w=ws_w[target_header_row]
複製代碼
操做源表標題行,獲取咱們想要的信息:
""" openpyxl用read_only模式載入workbook時,獲取到的cell不是通常的cell, 通過測試cell.column變成偏移了幾列的整數,因此這裏咱們定義一個函數來處理, 把整數轉換成excel真正的列數,好比「A」、「BB」等。 """
def readOnly_offsetColunmNumber_toRealColumn(number):
column=''
if number<=26:
column=chr(number+ord('A')-1)
else:
number1=number//26
column1=chr(number1+ord('A')-1)
number2=number%26
column2=chr(number2+ord('A')-1)
column=column1+column2
return column
#初始化兩個變量,分別是源表的條件列,要複製的列
source_condition_column=''
source_filled_column=''
""" 循環源表的標題列,獲得條件列的位置以及要複製列的位置, 再經過內嵌的循環獲得條件列的最大行數 """
for cell in header_row_r:
if cell.value==source_cell_condition:
source_condition_column=readOnly_offsetColunmNumber_toRealColumn(cell.column)
elif cell.value==source_cell_filled:
source_filled_column=readOnly_offsetColunmNumber_toRealColumn(cell.column)
複製代碼
操做目標表標題行,獲取咱們想要的信息:
#初始化兩個變量,分別是目標表的條件列,要粘貼的列
target_condition_column=''
target_filling_column=''
""" 循環目標表的標題列,獲得條件列的位置以及要粘貼列的位置, 再經過內嵌的循環獲得條件列的最大行數 """
for cell_j in header_row_w:
if cell_j.value==target_cell_condition:
target_condition_column=cell_j.column
elif cell_j.value==target_cell_filling:
target_filling_column=cell_j.column
複製代碼
如今咱們已經獲得全部須要的信息,該到實際粘貼數據的時候了。
""" 循環目標表的條件列,內部嵌套循環源表的條件列,一旦目標表條件列的某個cell 與源表條件列某個cell的值相同,咱們就把源表要複製列的同一行的cell的值 賦予目標表要粘貼列的同一行的cell。 """
for cell_m in ws_w[target_condition_column+str(target_header_row+1):target_condition_column+str(ws_w.max_row)]:
for cell_n in ws_r[source_condition_column+str(source_header_row+1):source_condition_column+str(ws_r.max_row)]:
if cell_m[0].value==cell_n[0].value:
ws_w[target_filling_column+str(cell_m[0].row)].value=ws_r[source_filled_column+str(cell_n[0].row)].value
複製代碼
最後保存目標workbook就能夠了。
wb_w.save(target_file_name)
複製代碼
注意:若是excel中標題行有合併居中的話,腳本會報錯,一種辦法就是去掉合併居中;另外一種就是在原標題行下再插入一行新的行再把原標題行的內容粘貼進去,用插入的這一行做爲標題行。