Tool尖尖

Do it just once!

庆祝中国共产党成立100周年

【Python】实例10:用Python正则表达式从不规则的备注栏获得采购申请单号

| 暂无评论

公司研发部需要常年采购一些新物料,用于新产品开发。每次采购新物料都需要出一份工程采购申请单(EPR:Engineering purchase request),并有一个编号,格式为“EPR-XX-XXXXX”。由于公司的采购系统中没有用于填写EPR编号的栏位,因此采购在系统填单的时候只得填写到备注栏内。备注栏是一个极其不规范的栏位,每个采购员的风格不同,填写方法也是五花八门,比如如下: 

工程部需要每天从系统导出这些物料的采购信息,然后用vlookup函数跟其内部登记的表格进行匹配,以了解物料交期,制定新产品开发进度。但是这个采购信息表里的EPR编号实在太不规范,很难与自己的记录表匹配,处理起来费时费力。Python正则表达式(规则表达式)可以轻松地处理这类问题,我们只需要设定好规则,可以从一堆乱七八糟的字符串中提取出我们想要的信息。

#1.获取备注栏的所有信息from openpyxl import load_workbook
wb
=load_workbook(“data采购信息表.xlsx”)
ws
=wb[‘Sheet1’]
PR_rawdata
=[]for row in range(2,ws.max_row+1):
PR_rawdata
.append(ws.cell(row=row,column=4).value)
PR_rawdata

>>[‘…ASIA PACIFIC PO CN..EPR-14-X1224……….’,
‘…ASIA PACIFIC PO CN..EPR-14-X1224……….’,
‘…ASIA PACIFIC PO CN..EPR-14-X1224……….’,
‘…ASIA PACIFIC PO CN..EPR-14-X1224……….’,
‘…ASIA PACIFIC PO CN..EPR-14-X1224……….’,
‘…ASIA PACIFIC PO CN..EPR-14-X1224……….’,
‘…ASIA PACIFIC PO CN..EPR-14-X1224……….’,
‘…ASIA PACIFIC PO CN..EPR-14-X1207……….’,
‘…ASIA PACIFIC PO CN..EPR-14-X1207……….’,
‘…ASIA PACIFIC PO CN..EPR-14-X1214……….’,
‘…ASIA PACIFIC PO CN.201.EPR-14-X1164……….’,
‘…ASIA PACIFIC PO CN.201.EPR-14-X1164……….’]


首先,我们导入openpyxl模块的load_workbook方法打开“采购信息表”,获取“Sheet1”工作表。然后建立一个空列表PR_rawdata,以存储备注栏对应列的信息。随后从第二行开始遍历所有行,提取第四列中的信息,使用append方法将其存入空列表PR_rawdata

 

提取完信息后,可通过len()查看PR_rawdata中元素个数,看看是否有遗漏。我们可以看到有1583个元素,妥妥的。

len(PR_rawdata)>>1583

#2.使用正则表达式获取PR编号from re import compile, IGNORECASE
def get_EPR_num(text):
#将问号’?’ 替换成 ‘-‘
changed_question_mark
= text.replace(“?”,“-“)
#获取EPR编号
epr_num
= compile(r‘EPR-d{2}-Xd{3}(d)?’,IGNORECASE)
match
= epr_num.search(changed_question_mark)
#将小写EPR转换为大写并返回
return match.group().upper()

然后我们就开始使用强大的正则表达式。首先导入re模块中的compileIGNORECASEre模块包含正则表达式的所有函数。compile为正则表达式函数,用于匹配所需要的内容;IGNORECASE表示忽略字符串中的大小写。我们先创建一个函数get_EPR_num(),以方便后面反复调用,其中包含一个参数text,用于传入包含EPR编号的字符串,比如“…ASIA PACIFIC PO  CN..EPR-14?X1059……….”。函数要做的事,就是在这个字符串中按照我们设定的规则提取出EPR编号,其结果应该是“EPR-14-X1059”。

 

有些包含EPR编号的字符串是带有问号“?”的,比如“EPR-14?X1059”,因此需要先将其替换成我们想要的“-”。我们使用replace(“?”,”-“)进行替换。然后向compile中传入一个字符串r“S{3}-ddSSd{3}(d)?”,创建正则表达式,并增加参数IGNORECASE忽略大小写。最前面的r表示忽略字符串中的转义字符(此例中的“”是正则表达式规则的一部分,不是转义字符,若不忽略,将被程序当成转义字符而出错)。其中”S”指除空格外的所有字符,“{3}”指匹配三次。然后是“-”,接着是两个数字“d{2}”。“-X”之后3或4个数字,所以用“d{3}(d)?”,其中“(d)?”表示可选匹配,即“-X”后面是3位数字的话就取3位数字,是4位数字就取4位数字。

 

正则表达式创建好后,我们就去到原始字符串中去搜索符合条件的项,并存入match变量。最后调用Match对象的group()方法,并使用upper()将小写转换为大写,返回匹配到的字符串,即EPR编号。group()是可以截取分组的字符串,分组是通过在正则表达式中加入括号()来操作,此例未分组,即只有1组。正则表达式常用的符号如下:

PR_list_result=[]for PR in PR_rawdata:
PR_list_result
.append(get_EPR_num(PR))
PR_list_result
>>[‘EPR-14-X1224’,
‘EPR-14-X1224’,
‘EPR-14-X1224’,
‘EPR-14-X1224’,
‘EPR-14-X1224’,
‘EPR-14-X1224’,
‘EPR-14-X1224’,
‘EPR-14-X1207’,
‘EPR-14-X1207’,
‘EPR-14-X1214’,
‘EPR-14-X1164’,
‘EPR-14-X1164’,
‘EPR-14-X1209’,
‘EPR-14-X1175’]

提取EPR编号的函数创建好了之后,就可以开始调用它来处理数据了。首先建一个列表PR_list_result来储存处理后的数据,然后遍历PR_rawdata,将其中的每个元素(即包含EPR编号的字符串)传入函数get_EPR_num()提取EPR编号,然后存入列表PR_list_result。我们可以看到列表PR_list_result里面就是很规则的EPR编号了,共有1583个。

len(PR_list_result)>>1583#3.在原工作表新增一列,并写入获取到的PR编号
wb1
=load_workbook(“data采购信息表.xlsx”)
ws1
=wb1[‘Sheet1’]
i
=0 #计数器,用于从包含所有EPR编号的列表PR_list_result中逐个取出数据for row in range(2,ws.max_row+1):
ws1
.cell(row=row,column=5).value=PR_list_result[i]
i
+=1 #计数器加1,以提取下一个数据
wb1
.save(“data采购信息表_新.xlsx”)

数据处理完后,就可以写入到Excel表里面去了。我们在原表中最后一列的后面写入规整的EPR编号。所以还是先打开“采购信息表.xlsx”,获取工作表“Sheet1”。定义一个计数器i,将其作为索引用于从包含所有EPR编号的列表PR_list_result中逐个取出数据,其初始值为0,因为列表的索引是从0开始的。然后建立一个for循环,从Excel表的第二行,第5列开始写入数据,写一个数据,计数器i加上1,以便写入下一个数据。

 

数据写完后,使用新的文件名保存文件。最后得到的结果如下: 

所有源代码和说明都在Jupyter notebook上完成,所用到的Excel 资料已上传GitHub, 欢迎Fork或下载到本地随意玩。。。转载请注明出处,谢谢。

GitHub链接:https://github.com/weidylan/Office_Automation_by_Using_Python

本篇文章来源于微信公众号: Python操作Office软件高效工作 已获作者转载许可。

发表评论

*为必填字段!