提示:通过文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录- 前言
- 一、现有的数据有哪些?
- 二、使用步骤
- 1.引入库
- 2.读入数据
- 总结
前言
通过已有的产品BOM状态,运用python自动整理汇总输出零部件状态至Excel中。
运算逻辑:先通过母件编码状态——确认出料体状态——再通过料体状态确认出原料状态。
确认料体状态时,会存在着同一种同时存在4种状态,原因是一种料体会组装成不同的产品销售。当一种料体存在着1~4种时,需要按照优先顺序选取,分别为正常销售>消耗升级>消耗淘汰>已下架。同理,原材料也会存在相同的问题,筛选方法一样。
提示:以下是本篇文章正文内容,下面案例可供参考
一、现有的数据有哪些?1,BOM表,格式如下:
其中子件编码分为三个等级,分别为半成品,料体,原材料,而我们要输出的时最后一级,原材料的状态
| 母件编码 | 母件名称 | 母件规格 | 子件编码 | 子件名称 | 子件规格 | 子件计量单位 | 使用数量 | 母件存货分类 | 子件存货分类 |
2,产品状态表
二、使用步骤 1.引入库代码如下(示例):
import pandas as pd from pandas import Dataframe from openpyxl import load_workbook,Workbook
#筛选母件编码为1开头的BOM明细
wb=load_workbook('BOM表test.xlsx')
ws=wb.active
# 新建工作簿
new_wb = Workbook()
# 获取新工作簿中的工作表
new_ws = new_wb.active
# 获取表头
late_header = []
for cell in ws[1]:
late_header.append(cell.value)
# 将表头写入新工作簿的工作表中
new_ws.append(late_header)
for row in ws.iter_rows(min_row=2, values_only=True):
name = row[0] #指定栏存货编码
if name.startswith('1'): #筛选存货编码1开头的成品明细
new_ws.append(row)
#print(row)
#筛选存货编码3开头的料体明细
new_ws1=new_wb.create_sheet('配方明细')
# 获取表头
late_header = []
for cell in ws[1]:
late_header.append(cell.value)
# 将表头写入新工作簿的工作表中
new_ws1.append(late_header)
for row in ws.iter_rows(min_row=2, values_only=True):
name = row[0] #指定栏存货编码
if name.startswith('3'): #筛选存货编码3开头的明细,如果用母件分类为料体筛选会遗漏
new_ws1.append(row)
new_wb.save('管理状态表test.xlsx')
#导入数据
data1=pd.read_excel('成品状态表1022.xlsx')
df1=Dataframe(data1) #创建Dataframe对象数据
data=pd.read_excel('管理状态表test.xlsx')
df=Dataframe(data) #创建Dataframe对象数据
df1=df1.loc[:, ['存货编码', '版本状态']] #切片,只取存货编码,版本状态两列
df=pd.merge(df,df1,on='存货编码',how='left') #目的:左连接匹配版本状态至BOM表
#筛选-确认料体状态(优先级:正常销售>消耗升级>消耗淘汰>已下架)
data2=((df[df['子件存货分类']=='料体'][['子件编码', '子件存货分类','版本状态']]).drop_duplicates()).sort_values(axis=0,by='版本状态',ascending=True) #查看条件为料体的子件编码和存货分类,并去重
data3=data2.rename(columns={'子件编码':'存货编码'}).reset_index() #修改列名,重置索引
data3['版本状态']=data3['版本状态'].fillna('无状态') #填充空值
# 遍历选出当存在多个同样的编码时,标记第一个出现的为“选择”,其余标记为“不选择”
data3['遍历']=None
for i in range(0,len(data3['存货编码'])):
if data3.iat[i,1] != data3.iat[i-1,1]: #当当前栏不等于上一行编码时
data3.iat[i,4] ='选择'
#print('选择')
else:
data3.iat[i,4] ='不选择'
#print('不选择')
#筛选最终需要的料体状态明细
data3_final=data3[data3['遍历']=='选择'][['存货编码', '版本状态']]
#将配方状态匹配到“配方明细”表
data5=pd.read_excel('管理状态表test.xlsx',sheet_name='配方明细')
df2=Dataframe(data5) #创建Dataframe对象数据
df2['存货编码']=df2['存货编码'].astype(str)
df3=pd.merge(df2,data3_final,on='存货编码',how='left')
#从配方明细表中筛选-确认原料状态(优先级:正常销售>消耗升级>消耗淘汰>已下架)
df4=((df3[df3['子件存货分类']=='原料'][['子件编码', '子件存货分类','版本状态']]).drop_duplicates()).sort_values(axis=0,by='子件编码',ascending=True) #查看条件为原料的子件编码和存货分类,并去重
df4['版本状态']=df4['版本状态'].fillna('已下架') #填充空值
#汇总原料通用项(只汇总正常销售,消耗升级部分)
df4['是否通用']=None
#df3['汇总通用项']=df3.groupby('子件编码')['版本状态'].count()
for k in range(0,len(df4['子件编码'])):
if df4.iat[k,2]=="1正常销售"or df4.iat[k,2]=="2消耗升级":
df4.iat[k,3]=1
else:
df4.iat[k,3]=0
df3_1=df4.groupby('子件编码')['是否通用'].sum()
# 遍历选出当存在多个同样的编码时,标记第一个出现的为“选择”,其余标记为“不选择”
df4['遍历']=None
for j in range(0,len(df4['子件编码'])):
if df4.iat[j,0] != df4.iat[j-1,0]:
df4.iat[j,4] ='选择'
#print('选择')
else:
df4.iat[j,4] ='不选择'
#print('不选择')
#筛选最终需要的料体状态明细
df3_2=df4[df4['遍历']=='选择'][['子件编码', '版本状态']]
df3_final=pd.merge(df3_2,df3_1,on='子件编码',how='left')
#导出df至excel
writer = pd.ExcelWriter('原料总管理表.xlsx')
df.to_excel(writer,'BOM状态')
df3.to_excel(writer,'配方明细')
data3_final.to_excel(writer,'料体状态') #data3写入表格
df3_final.to_excel(writer,'原料状态')
writer.save()
最终输出状态为:
总结
本文目的纯属为了记录方便以后优化,第一次写代码仍有很多的bug。
需优化数据:1,与研发确认料体状态;2,简化代码,提高运行效率



