好用的Python,便捷的Pandas,在数据计算和分析中其强大的功能堪比数据库的存在,操作却如同Excel般易于上手。他比Excel、Word、PPT使用VBA更能提升办公自动化程度,也更让人有发展和想象的空间!人类科技的进步,在开源这个共享智慧的时代里,一日千里。
这么好的东西,因为各种原因,如教材的高不可攀,或案例脱离应用场景,常常将人拒之门外,或者枯躁得让人无法坚持学习下去。
作为数据分析的拥趸,有义务也有责任将这么好的技术和工具推荐给大家。接下来的日子里,将会和大家一起来学习Python这个语言,我们使用Spyder这个Python开发环境,[参考资料https://blog.csdn.net/yusongcan/article/details/77073794]
首先我们需要安装Anaconda,建议安装3.7以上的版本,这个啊,想想看,有iphone6和iphone 11免费让你选,你会选哪个?[参考资料 https://blog.csdn.net/ITLearnHall/article/details/81708148]
声明:对于长的参考资料,可以随便看,不想看的时候可以不看,想看的时候再看,这样才会走得更远!还有看教程一定要动手,可以一天选一个主题或一个任务来训练自己。欲成强者:动眼、动脑、还动手!网上看到好的资料,收藏到分类的收藏夹里。网上的文章、电子书和纸质的书都是学习的好帮手和好工具。
眼见为实,现在我们就通过一个递归函数和MRP物料需求计划的计算来看一下我们“好用的Python,便捷的Pandas”,体验一下“人生苦短,我用Python”是何等深情的“告白”吧!
用到的表单释义,抓住重点,我们尽量符合数据库第三范式。
进入正题,在Spyder新建一个空白文件,复制下列代码和注释
# -&- coding: utf-8 -&-
"""
Created on Mon Jul 8 22:05:32 2019
@author: same3
"""
#引入三个python 包
#pandas:数据分析包
import pandas as pd #"as"顾名思义,即以后可以在程序中以缩写pd 代表 pandas
#numpy:科学计算包
import numpy as np
#xlwings:python操作Excel的模块,最好的Excel操作包之一,有取代VBA的趋势
#中文入门学习资料之一: https://www.cnblogs.com/catgatp/p/7875683.html
#英文官方学习网站https://docs.xlwings.org/en/stable/ 建设初学者有空翻翻,随便看看就好,不要太深入,因为太无趣
import xlwings as xw
#声明Excel应用程序,或直接使用 wb=xw.Book(file) 也可以
#app=xw.App(visible=True,add_book=False)
"""
visible
Ture:可见excel
False:不可见excel
add_book
True:打开excel并且新建工作簿
False:不新建工作簿
"""
# display_alerts= False ,禁止Excel弹出提示的对话框
#app.display_alerts=False
#Excel 文件路径
file = r'D:\VBA\LEARNING_ERP.xlsm' #字符串前面加r,是表示其后的字符串不转义,使用真实字符
#打开Excel工作簿,文件路径:'D:\VBA\LEARNING_ERP.xlsm' ,可根据实际设定
wb=xw.Book(file)
wb.app.display_alerts=False
#引用工作簿(workbook)里的工作表(worksheet)
sht_test=wb.sheets['base'] #存放基础数据
sht_view=wb.sheets['view'] #存放计算后的数据
'''
引用单元格当前拓展区域,注意四周行和列的单元格(黄色部分)为空
工作表(worksheet)引用,下标从0从始,如sht_test[19,0];单元格(range)引用,下标从1开始,如sht_test.range(20,1)这是python的特例。
RNG1[第20行,第1列]的拓展区域(绿色部分),即20-45行,A-C列的区域,即Bom物料清单
RNG2(蓝色部分),即Plan产品生产计划
'''
RNG1= sht_test[19,0].api.currentregion
RNG2= sht_test[19,5].api.currentregion
#命名Excel单元格区域名称
RNG1.name='Bom'
RNG2.name='Plan'
'''
Plan及Bom资料导入pandas的DataFrame中
header=1表示单元格区第一行为列标题行
index=True表示单元格区第一列为索引列,False表示自动索引(从0开始)
'''
dfsz5= sht_test['Plan'].options(pd.DataFrame, header=1,index=True).value
dfsz6 = sht_test['Bom'].options(pd.DataFrame, header=1,index=True).value
'''
连接Plan和Bom,merge横向(列)连接,类似SQL SERVER数据库连接join,
left_index=True,right_index=True表示左右两个DataFrame以索引列为基准进行连接
how='inner'表示内连接
Bom(bill of material)根据物料清单(递归)计算 MRP 物料需求计划
第二阶开始到最尾阶的物料分解,从第一阶分解后取得所需数据
'''
def eeBom(df4A,df4,df2,CX1):
df5=df4[['CID','PCQT','PROCID']]
df5.rename(columns={'CID':'PID','PCQT':'PQT','PROCID':'PROPID'}, inplace = True)
df5.reset_index(drop=True,inplace = True)
df5.set_index('PID',inplace = True)
df6=pd.merge(df5,df2,left_index=True,right_index=True,how='inner')
if df6.empty :
return df4A
else:
df6['PCQT']=df6['PQT']*df6['CQT']
df6['PROCID']=df6['PROPID']+'-'+str(CX1+1)
df6['LEVEL']=CX1+1
df4A=df4A.append(df6)
return eeBom(df4A,df6,df2,CX1+1)
#第一阶的物料分解,从Plan取得所需数据
#首先调动eBom函数,eBom函数再调用eeBom,但是eeBom要定义在eBom之前,不然会出错,会显示找不到eeBom函数
def eBom(df1,df2):
df3=pd.merge(df1,df2,left_index=True,right_index=True,how='inner')
df3['PCQT']=df3['PQT']*df3['CQT']
df3['PROCID']=df3['PROPID']+'-'+str(1)
df3['LEVEL']=1
return eeBom(df3,df3,df2,1)
#计算MRP,并按单据号,物料父项编号排序
dfsz7=eBom(dfsz5,dfsz6).sort_values(by=['PROCID','PID'])
#'FC'列标志物料子项是否为:'F'-尾阶(最终件),'M'-非尾阶(中间件)
#全部先标注为'M'
dfsz7['FC']='M'
#获取Bom表中所有物料父项编号,取唯一值即可
list1=list(dfsz6.index.unique())
#print(list1)
#对MRP物料需求计划表中的最终件标识为'F'
dfsz7.loc[~dfsz7['CID'].isin( list1),['FC']]='F'
#就这样完成啦!超简洁,有没有小伙伴们!
print(dfsz7)
#导出到Excel,首先删除A:AA列,把格式也一起删除,用cells.delete或clear无法删除格式
sht_view.api.columns('A:AA').delete
sht_view.api.cells.delete
sht_view.clear
#在Excel view表'A1'单元格的扩展位置显示dfsz5(即:Plan生产计划表)
sht_view.range(1,1).expand().value = dfsz5
#在Excel view表'E1'单元格的扩展位置显示dfsz6(即:Bom物料清单表)
sht_view.range(1,5).expand().value = dfsz6
#在Excel view表'I1'单元格的扩展位置显示dfsz7(即:MRP物料需求计划表)
sht_view.range(1,9).expand().value = dfsz7
#在Excel view表'第4、8列设置列的颜色,便于在Excel中区分各个计算出来的数据集
sht_view.cells.columns(4).color=(255,128,255)
sht_view.cells.columns(8).color=(255,128,255)
#列自动调整宽度,如果要指定列宽可用 sht_view.range((1,1),(1,20)).api.ColumnWidth = 8
sht_view.api.columns('A:AA').autofit
结果如下:
看不明白的小伙伴们不要着急,今天只是展示了Python强大功能的一角,接下来的日子里,我们就一起共同来学习和进步吧!
工作之余要学习,学习之余要分享。平时只是看别人写,现在自己写一写,才知道其中需要巨大的努力,所谓的台上一分钟,台下十年功,诚不欺人也!