作为一个生产型企业,其产品种类繁多。按照客户要求,每种产品在出货时都需要在包装上贴上如下信息标签,以便识别。 标签上需要包含6种信息,原始资料内容如下: 我们注意到原始信息中的品牌,有些是大写,有些是小写,而标签要求全部大写,因此在填入之前需要先做处理。公司的常规做法是充分发挥人海战术,安排一个小组的人一哄而上,先手动将小写字母替换为大写,然后开始一系列的'复制'加'粘贴'。通常完成一个物料的标签信息需要35秒,100个物料就需要约1小时。可怜那些操作人员,除了手酸,脖子硬,眼睛疼,再加上键盘上的“ctrl,C,V”三个键像光头一样光滑外,还容易出错。如果原始信息有误,部分标签还得小心翼翼、如履薄冰地重新复制粘贴来修正。有时候,操作人员一走神,复制或者粘贴错了,还会被客户投诉,继而被老板训斥,整个心情都不好了。 通常一个订单有上百种物料,每天需要处理约30个订单,需要4个人全职处理这些信息。使用Python, 只需要很少量代码即可轻松搞定,运行只需几秒钟时间。只要原始信息没问题,Python会保质保量完成任务。 首先,我们需要将空白标签的格式复制足够多个。为方便打印,本例是在A4纸上每排放3个标签。也可让Python去自动填写标签第一列的信息,但涉及格式操作,还不如在Excel内直接设置方便。 以上操作完成后,就可以开始后续的信息读取和填写了,步骤如下:
下面我们需要将自然语言翻译成计算机能理解的语言,以便它按我们的指令执行: # 从“info”工作表读取并处理信息,存入列表 from openpyxl import load_workbook def get_info(path): wb = load_workbook(path) ws = wb['info'] info=[] for row in range(2, ws.max_row+1): brand = ws['A' + str(row)].value if brand: # 判断“品牌”是否为空值,若为空值则不进行小写字母的转换 # 若无这行,当遇到“品牌”为空值时,程序会报错,因为空值无法进行大小写转换 brand=brand.upper() #将“品牌”中的小写字母全部转换成大写字母 typ = ws['B' + str(row)].value # 获取单元格中的数据 pn = ws['C' + str(row)].value lotno = ws['D' + str(row)].value date = ws['E' + str(row)].value if date: # 判断“日期时间”是否为空值,若为空值则不进行日期获取 # 若无这行,当遇到“日期时间”为空值时,程序会报错,因为空值无法进行日期获取 date=date.date() #只获取日期时间中的日期,比如2019-2-20,不需要具体时间 quantity = str(ws['F' + str(row)].value)+' pcs' # 在数量后面加上“pcs”字样 data={ 'brand':brand, 'typ':typ, 'pn':pn, 'lotno':lotno, 'date':date, 'quantity':quantity } info.append(data) return info
>>finished
>>Wall time: 79 ms 我们首先导入 此处我们先定义一个函数,取名为 我们使用
但是我们并不需要整个Excel文件的内容,只需要其中一个名叫“info”的工作表的内容,因此我们再定义一个变量(容器) In [4]: ws=wb['info'] type(ws) Out[4]: openpyxl.worksheet.worksheet.Worksheet 然后我们建立了一个空列表
In [6]: for i in range(2,5):# 从2-5范围内逐个取值,但不包含5 print(i) 2 3 4 数据提取完成后,我们就可以检查我们的数据是否有问题。 {'brand': 'ABC1', 字典里的键对应的是“品牌、型号、物料编号、批次号、生成日期、数量”,值正好是Excel表中第2行的数据。 In [7]: info[0] Out[7]: {'brand': 'ABC1', 'typ': '11X11-XX761X8', 'pn': '011-0076108', 'lotno': 'Q19H023994901', 'date': datetime.date(2019, 2, 20), 'quantity': '300 pcs'} 在
此时,我们成功获取了所有产品的数据,并存进了列表容器 # 将处理好的信息逐个写入到“label”工作表并保存 def write_info(path,info): wb = load_workbook(path) ws = wb['label'] k=0 for i in range(2,9,3): #列遍历 for j in range(1,round(len(info)*7/3),7): #行遍历 if k < len(info): #当数据条数不是3的整数倍时,计数器k会超出列表info的范围,后续代码只有在k < len(info)的情况下执行 ws.cell(row=j, column=i).value = info[k]['brand'] ws.cell(row=j+1, column=i).value = info[k]['typ'] ws.cell(row=j+2, column=i).value = info[k]['pn'] ws.cell(row=j+3, column=i).value = info[k]['lotno'] ws.cell(row=j+4, column=i).value = info[k]['date'] ws.cell(row=j+5, column=i).value = info[k]['quantity'] k+=1 #k是列表info的索引,此处加一以便获取下一条数据 wb.save(path) #保存Excel文件
此处我们定义了第二个函数 我们的目的是将 随后我们进行行遍历,由于每个标签有6个信息,加上1个空行,因此每个标签总共占用了7行。 因为数据可能不是3的整数倍,此时计数器
以上是处理单个订单的标签,对于多个订单的标签,我们可以用类似的方法一次完成。我们只需要将所有订单的Excel文件放入一个文件夹,然后就可以批量操作。此时,需要引入 In [11]: import os def file_name(file_dir): names=[] for file in os.listdir(file_dir): if '.xlsx' in file: # 只处理该路径下的Excel文件 names.append(file_dir+file) return names file_dir='data/' pathess=file_name(file_dir) pathess Out[11]: ['data/label_info - 1.xlsx', 'data/label_info - 2.xlsx', 'data/label_info - 3.xlsx', 'data/label_info - 4.xlsx', 'data/label_info - 5.xlsx', 'data/label_info.xlsx', 'data/label_info_nan.xlsx'] In [12]: %%time for path in pathess: info=get_info(path) write_info(path,info) print('Finished!') Finished! Wall time: 1.93 s 因为不同的客户,我们的文件夹可能还包含子文件夹,那要一次获取母文件夹中的所有Excel文件,需要应用到 我们在
由于我们需要获得文件的完整路径,但以上 path = [os.path.join(root, name) for name in files] 这可以让程序变得非常简洁,也节省运算时间。通过看下面这个小例子就可以知道其原理: a=[i for i in range(10)] a >>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 如果文件夹内还有除Excel之外的文件,需要将其从文件路径列表中剔除,然后再传入信息读取和写入的函数。
所有源代码和说明都在Jupyter notebook上完成,所用到的Excel 资料已上传GitHub, 欢迎Fork或下载到本地随意玩。。。转载请注明出处,谢谢。 |
|
来自: Four兄 > 《Python办公》