现代生活中,咱们很难不与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中标题行有合并居中的话,脚本会报错,一种办法就是去掉合并居中;另外一种就是在原标题行下再插入一行新的行再把原标题行的内容粘贴进去,用插入的这一行做为标题行。
欢迎浏览个人我的博客,https://diwugebingren.github.io