[Asm] 纯文本查看 复制代码
import pandas as pd
import datetime,os,re
df = pd.DataFrame() # 设置中间变量,为空dataFrame数据体,用于存储新“总表.xlsx”数据或售卖数据
df0 = pd.DataFrame() # 设置中间变量,为空DataFrame数据体,用于存储原“总表.xlsx”数据
df1 = pd.DataFrame() # 设置中间变量,为空DataFrame数据体,用于存储原售卖的中间数据
df2 = pd.DataFrame() # 设置中间变量,为空DataFrame数据体,用于存储当次入库的中间数据
now = datetime.datetime.now().strftime(r'%m月%d日%H时%M') # "%H:%M"应该怎么加进去?
rW1 = ['入库时间','商品ID','商品名称','入库数量','商品价格','金额','说明备注']
rW2 = ['入库时间','商品ID','商品名称','库存数量','商品价格','金额','说明备注']
fpth = r'd:/CHRKGL' # 结尾不能用“\”,为了操作方便,也不能用“d:/CHRKGL/”
fnm = rf'总库.xlsx'
nfnm = f'/{now}入库.xlsx'
snfnm=f'/售卖{now}.xlsx'
if not os.path.exists(fpth): # 判断是否存在特定目录,不存在就创建
os.makedirs(fpth)
if fnm in os.listdir(fpth): # 把已经存在的库存文件数据交给df0,并设置好列标签。
df0 = pd.read_excel(fpth+'/'+fnm) # 加“header=1”只是便于观察,并不能建立列索引
else: # 这几句的目的是如果是第一次运行,没有“总库.xlsx”的话,就创建个DataFrame数据供调用
df3 = pd.DataFrame([rW2]) # 其实可能没有这个必要。既然还没有,那新生成的就自己做主
df0 = pd.DataFrame(df3, columns=rW2)
# df0['原库存'] = df0['新库存'] # 处理中间数据
# df0['新库存'] = 0 # 处理中间数据
# df0['入库数量'] = 0 # 同上
def inpt(*x): # 收集需输入的内容
nW = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') #
iDn = int(rvw1(str(input('请扫描商品条码:').strip()))) # 自定义函数处理扫码,不足规定长度重新扫
nM = rvw2(str(input('请输入商品名称:').strip())) # 自定义函数去除空格和回车,限定输入长度
cNt = int(rvw3(rvw2(input('请输入入库数量:').strip()))) # 自定义函数判断是否为整数
pRc = rvw4(input('请输入商品价格:').strip().replace('。','.')) # 判断是否有浮点数,消除简单失误
aMnt = float(int(cNt) * pRc) # 计算本次入库物品金额,需转为浮点数
rMk = str(input('说明:')).strip() # 对输入内容无限制
if len(rMk) == 0:
rMk=czy
rW3 = [nW, iDn, nM, cNt, pRc, aMnt, rMk] # 将以上内容组成个列表
print('#'*50)
print(f'商品名称:{nM}')
print(f'入库数量:{cNt}')
print(f'商品价格:{pRc}')
print('#'*50)
j=1
while j: # 判断输入是否有误,有误的话删除此条并重新输入
hd = input('检查刚才输入是否有误,条目是否重复,数量、价格是否准确。\n'
'按“y”、“Y”或“是”重新输入,按回车等其它键继续输入下一条:')
if (len(hd) == 0) or (str(hd[0]) not in ['y','Y','是']): # 回车空格等均表示输入正确,将继续下一条
return rW3
else:
nM = rvw2(str(input('请输入商品名称:').strip())) # 输入错误的只能是以下三项,未更新录入时间
cNt = int(rvw3(rvw2(input('请输入入库数量:').strip())))
pRc = rvw4(input('请输入商品价格:').strip().replace('。', '.')) # 简单排除“。”
aMnt = float(int(cNt) * pRc)
rW3 = [] # 疑问:能不能清空while循环外的那个“rW3”?
rW3 = [nW, iDn, nM, cNt, pRc, aMnt, rMk] # 将以上内容组成个列表。如上句未能清空,会不会
# 是否会造成while外的rW3列表意外扩充?
print('#'*50)
print(f'商品名称:{nM}')
print(f'入库数量:{cNt}')
print(f'商品价格:{pRc}')
print('#'*50)
def rvw1(x): # 判断扫码是否正确,正确扫码为13位数字,实验码3位数字
while len(x) != 3:
print('扫码失败。正确条码是行13位长的数字,\n'
'请重新扫码!如仍不成功,可手动输入。')
x = str(input('请扫描商品条码:').strip())
return x
def rvw2(x): # 判断空回车
while len(x) < 1:
print('此处不能为空!')
x = str(input('请重新输入:').strip())
return x
def rvw3(x): # 判断是否为整数
while not x.isnumeric():
print('入库数量应为整数,请敲回车并重新输入!')
x = rvw2(input('请输入入库数量:').strip())
return x
def rvw4(x): # 用正则判断是否为浮点数.如果不用正则,少加载个模块,程序应该小一些
while bool(re.search(r'\d', x)) != 1:
print('请输入整数或小数,注意小数点是英文半角的“.”,不是中文的“。”')
return rvw4(input('请重新输入商品价格:').strip().replace('。','.'))
flt = re.findall("(\d+)(\.*\d*)", x)
if len(flt[0][1]) == 0:
return int(flt[0][0])
else:
return float(x)
def ipt(x): # 循环输入,每次一行,每行一个列表。
i = 1 # 设置循环变量,初始值为1
while i > 0:
# dT.append(inpt(x)) # 加不加x呢?如是多处调用此自字义函数,则应用x参数。
dT.append(inpt()) # 将通过自定义函数审核的输入内容逐次添加到二维列表中
# dT[i - 1].insert(0,i) # 在每个列表元素(也是个列表)的头部插入序号,为变量i-1。用行标签也可以不用加序号了
eN = input('是否继续入库:').strip() # 过滤掉空格
if (len(eN) == 0): # 直接回车则继续
i += 1
elif str(eN[0]) not in ['n', 'N', '不']: # 根据输入内容的第一个字符判断是否结束
i += 1
else:
i = 0
return dT
def cfcl(x): # 本次输入重复项的查找显示删除
if True in df2['商品ID'].duplicated(): # 是不是要把“df2”换成“X”?
key_duplicated = df2[df2['商品ID'].duplicated(False)] # 对df2['商品ID']使用duplicated方法,
# 并获取False所对应的数据,最后把获取的数据交给key_duplicated变量,保存为DataFrame数据体。
print("'商品ID'列中输入有重复:")
print('#' * 50)
print(key_duplicated[['商品ID', '商品名称']]) # 只显示数据体key_duplicated中的两列
print('#' * 50)
print('本次入库中扫码录入的“商品ID”重复的商品将全部删除,\n可在本程序结束后再次运行,重新录入该商品。\n')
os.system('pause')
df2.drop_duplicates(subset='商品ID',keep=False,inplace=True) # keep的值只有"first", "last"
# 或False。注意subset的参数,是判断重复的列标签。
return df2
def dfchl(x): # “总库.xlsx”合表后的重复项的处理
df = x.fillna(0) # groupby需要轴对齐,"NaN"和“Null”不能参与运算,但0可以
df_dpl = df[df['商品ID'].duplicated(False)] # 对df['商品ID']使用duplicated方法,
# 并获取False所对应的数据,最后把获取的数据交给df_dpl变量,保存为DataFrame数据体。
# df.drop_duplicates(subset=['商品ID'], keep=False, inplace=True) # 从df中删除“商品ID”重复的各行
# print(df) # 如果用“inplace=True”参数,df中就已经只剩“商品ID”不重复的行了。
df_sgl = df.drop_duplicates(subset=['商品ID'], keep=False, inplace=False) # 不改df就需要另外的变量来保存结果
df_dpl_sgl = df_dpl.drop_duplicates(subset='商品ID', keep='first', inplace=False) # 不要随便为了省事就用True
df_dpl_sum = df_dpl.groupby('商品ID')['入库数量'].sum().reset_index() # "reset_index"和“reset_index()”结果不一样
df_dpl_sgl['入库数量'] = df_dpl_sum['入库数量'] # 根据“商品ID”分组后,对其它数值列求和,如果指定字符串列,则扩充字符串
df = pd.concat([df_dpl_sgl, df_sgl], axis=0, ignore_index=True)
return df
czy = rvw2(input('请输入操作人姓名或编号:').strip())
cz = input('售卖还是入库?售卖请直接回车;入库请输入"RK"后回车:').strip()
if cz == 'RK':
dT = [] # 设置用于保存输入内容的空列表
df2 = pd.DataFrame(ipt(dT), columns=rW1)
cfcl(df2)
df2 = df2[rW1] # 各列重新排序
df2.to_excel(fpth+'/'+nfnm) # 这个读入路径和文件名的方式实在丑
print('#' * 50)
print(df2)
print('#' * 50)
print(f'本次输入商品如上显示,保存在"{fpth}"目录,文件名"{nfnm}"。')
os.system('pause')
# df2['原库存'] = 0 # 在df2中,均为新输入,df2['原库存']均视为0。如有和df0中的重复项,将专门调整
# df2['新库存'] = 0
# df2['库存金额'] = 0
df = pd.concat([df2, df0], axis=0, ignore_index=True)
df = dfchl(df)
df['金额'] = df['商品价格'].astype(float) * df['入库数量'].astype(float) # df2[df2['商品单价'] * df2['新库存']]
df['库存数量'] = df['入库数量']
# # # df0.to_excel('d:/Temp/食堂窗口售卖表.xlsx',index=False,columns=False)
# # # df0.to_excel('d:/Temp/食堂窗口售卖表.xlsx',columns=False) # columns=True也不行,没这参数
df = df[rW2] # 不明白为啥df最后会多出几列,先用这个取巧的办法吧。
df.to_excel(fpth+'/'+fnm)
print('#' * 50)
print(df)
print('#' * 50)
os.system('pause')
print(f'本次入库结果如上显示,保存在"{fpth}"目录,文件名"{fnm}"\n,请打开该文件核对。')
else:
print('#' * 50)
print('开始售卖!')
print('#' * 50)
os.system('pause')
if fnm not in os.listdir(fpth): # 上面已经有过这句了,怎么利用一下而不是重复写一遍呢?
print('#' * 50)
print('"总库.xlsx"尚未建立,请先将商品入库再售卖。\n按任意键退出程序。')
print('#' * 50)
os.system('pause')
else:
df0 = pd.read_excel(fpth + '/' + fnm) # 读取“总库.xlsx”
print('#' * 50)
print(df0) # 显示商品总库存
print('#' * 50)
i = 1
stb = []
id01=[]
while i:
siDn = rvw2(input('请扫描商品条码:').strip())
if siDn[0] == '0': # 输入0结束程序
i = 0
print('#' * 50)
print('要结束商品售卖吗?按任意键退出程序!')
print('#' * 50)
os.system('pause')
else:
if len(siDn) != 3:
print('#' * 50)
print('刚才扫码可能不正确。正确商品ID为13位连续阿拉伯数字,请重新扫码!')
print('#' * 50)
continue
i = i + 1
snW = datetime.datetime.now().strftime('%m-%d %H:%M:%S') #
id01=(df0['商品ID'] == int(siDn)).values.tolist()
if True not in id01: # 要先做判断,是否在“总库.xlsx”中及其库存数
print('#' * 50)
print('该商品可能还没入库,请结束程序,进行入库操作后再售卖!')
print('#' * 50)
break
snM = df0[df0['商品ID'] == int(siDn)]['商品名称'].values.astype(str)[0]
spRc = df0[df0['商品ID'] == int(siDn)]['商品价格'].values.astype(float)[0]
print('#' * 50)
print(f'应收款{spRc}元。')
print('#' * 50)
srMk = czy
srW3 = [snW, siDn, snM, spRc, 1, srMk]
stb.append(srW3)
id01=[]
df1 = pd.DataFrame(stb, columns=['售卖时间', '商品ID', '商品名称', '商品价格', '售卖计数', '说明备注'])
if df1.shape[0] == 0:
print('#' * 50)
print('未入库的商品无法售卖!按任意键退出。')
print('#' * 50)
os.system('pause')
quit()
else:
if len(id01) == 0:
df = df1.groupby(['商品ID', '商品名称', '商品价格'])['售卖计数'].sum() # 这里如是多列要用双层的“[]”
df = df.reset_index()
df['商品金额'] = df['商品价格'] * df['售卖计数']
dfcnts = df[['商品ID','售卖计数']].copy()
dfcnts['商品ID'] = dfcnts['商品ID'].astype(str)
df0 = df0.copy()
df0['商品ID'] = df0['商品ID'].astype(str)
df00 = pd.merge(df0,dfcnts,on='商品ID',how='outer')
df00.fillna(0,inplace=True)
df00['库存数量']=df00['库存数量']-df00['售卖计数']
df00['金额']=df00['商品价格']*df00['库存数量']
df0 = df00[rW2]
df.loc[df.shape[0] + 1, '商品金额'] = df['商品金额'].sum()
df.loc[df.shape[0], '商品ID'] = '本次售卖总计'
df.to_excel(fpth + '/' + snfnm)
df0.to_excel(fpth + '/' + fnm)
print(f'本次售卖结果如上显示,保存在"{fpth}"目录,文件名"{snfnm}"\n,'
f'"{fnm}"的“库存数量”已根据本次售卖核减,请打开该文件核对。')
print(df0)
print('#' * 50)
print(df)
print('#' * 50)
else:
df = df1[:-1].groupby(['商品ID', '商品名称', '商品价格'])[['售卖计数']].sum() # 这里如是多列要用双层的“[]”
df = df.reset_index()
df['商品金额'] = df['商品价格'] * df['售卖计数']
dfcnts = df[['商品ID', '售卖计数']].copy()
dfcnts['商品ID'] = dfcnts['商品ID'].astype(str)
df0 = df0.copy()
df0['商品ID'] = df0['商品ID'].astype(str)
df00 = pd.merge(df0, dfcnts, on='商品ID', how='outer')
df00.fillna(0, inplace=True)
df00['库存数量'] = df00['库存数量'] - df00['售卖计数']
df00['金额'] = df00['商品价格'] * df00['库存数量']
df0 = df00[rW2]
df.loc[df.shape[0] + 1, '商品金额'] = df['商品金额'].sum()
df.loc[df.shape[0], '商品ID'] = '本次售卖总计'
df.to_excel(fpth + '/' + snfnm)
df0.to_excel(fpth + '/' + fnm)
print(f'本次售卖最后一项未在{fnm}中,请先将该商品入库,\n'
f'其它结果如下显示,保存在"{fpth}"目录,文件名"{snfnm}"\n'
f'"{fnm}"的“库存”已根据本次售卖核减,请打开该文件核对。')
print(df0)
print('#' * 50)
print(df)
print('#' * 50)