吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2449|回复: 12
收起左侧

[求助] 总算跑通了,可我觉得逻辑和语法真屎

[复制链接]
13832811375 发表于 2020-11-30 16:27
本帖最后由 13832811375 于 2020-11-30 16:32 编辑

一、“请输入操作人姓名或编号:”:可以为字符和数字,但不能是空格也不能直接回车;此部分内容会默认添加到“说明”栏,如果“说明”里直接回车没有输入内容的话。
二、“售卖还是入库?售卖请直接回车;入库请输入"RK"后回车。”:
        1、商品要先入库(“RK”是英文大写,输入时不用输入引号),然后才能进行售卖;商品没有入库就进行售卖的话,程序会提示后退出。
        2、输入“RK”回车后开始入库,在此处任何其它输入,包括回车、空格等,都会进行“售卖”界面(为方便厨师操作);
        2、“售卖”和“入库”以及“RK”这些关键字应做成特别颜色,尚待改进;
三、“请扫描商品条码:”:直接用扫码枪扫码一个(件/类)商品。识别正确的条码应该是13位数字(目前实验阶段为手输3位阿拉伯数字),不符合这个规范的一律拒绝输入。成功后,自动进入下一步;
四、“请输入商品名称:”:可输入字符或者数字,不能是空格或者回车;输入空格或者回车时,程序会要求重新输入“商品名称”。
五、“请输入入库数量:”:必须输入整数阿拉伯数字,不能是空格或者回车;输入空格或者回车时,程序会要求重新输入“入库数量”(每次入库一种商品,商品可以是任意个。注意要点齐商品数量,如果有遗落,重复入库的话,会因为是重复录入而删除所有重复项)。
六、“请输入商品价格:”:只能是整数或者小数的阿拉伯数字,不能是空格或者回车;输入小数时,小数点儿应为英文半角的“.”,但程序里稍做优化,误输入“。”也可以正常计算;输入普通字符、空格或者回车时,程序会要求重新输入“商品价格”。
七、“说明:”:此处输入无限制,也可以为空或者直接回车。如果为空或直接回车,此处将填入第一项中输入的“操作人姓名或编号”。
八、“说明”完成后,会显示刚才输入的这一条共六项内容(多了一项操作时间),并提示检查输入是否正确。并自动回到开始,要求重新录入。此处的特殊字符,如“y”、“Y”和“回车”等,应该做特殊颜色处理,未完成。
        1、如果输入正确,可以输入除了“y”、“Y”和“是”开头儿的任意内容,最方便的是直接按回车键,然后进入下一条的输入;
        2、按“y”、“Y”(就是yes/YES的第一个字母)或“是”的话,程序会认上条内容输入有误,会删除刚才输入的这一条的部分内容。
        3、如果按“y”、“Y”或“是”,会直接让输入“商品名称”、“价格”和“数量”,不需要再扫码,因为刚才已经判断扫码了。“说明”也不需要。
九、“是否继续入库:”:是询问是否对下一个(件/类)商品开始扫码。比如上次可能一次入库一根火腿,也可是能15瓶可乐,但往下要开始扫别的商品了(最好不要重复)。
        1、此处,如果继续入库其它商品,可以直接回车;
        2、如果结束入库,按“n”、“N”或“否”即可。注意,由于判断逻辑是只判断最左侧第一个字符,所以,即使你输入的是“否否...”、“Num...”或者“nnnnn....”,程序也会认为是结束入库操作,开始下一步。
        3、单次入库多件商品的去重处理:由于一次入库有可能要操作几十件商品,有可能会误拿,或者操作员自己也不记得是否入过某件商品,因此入库操作设计了去重功能。不需要操作员做操作,程序会自己根据“商品ID”,也就是扫码结果,而不是商品名称来判断。发现有重复的“商品ID”后,会把重复项全删除。操作员只需记住提示的内容,然后再打开程序重新录入该商品即可。
十一、按“n”等并回车后,程序保存输入结果到“D:\CHRKGL”文件夹中,是两个文件,一个是“总库.xlsx”,另一个是带有时间戳的“...入库.xlsx”文件。“总库.xlsx”既是以后售卖的根据,也是每次入库的汇总,是关键文件。每次入库都会改变其中的数据,每次售卖也会改变其中的数据,必须保存好。生成的带时间戳的文件仅供参考,总数正确的话,可以保存备查,也可以删除。
十二、第二次入库时,程序会自动读取“总库.xlsx”数据,并根据是否已经入库更新总库数据(主要是数量和金额,价格如有变动会更新为后新价格)。
十三、如果在开始时直接回车(输入除了“RK”以外的任意字符回车也行),可以自动进入“售卖”环节。
十四、按照提示按下任意键后,程序先显示一遍目前的“总库.xlsx”中的数据,然后开始等待扫码枪扫码。扫码后,会根据多种因素做判断:
        1、如果找不到“总库.xlsx”文件,会提示后退出程序;
        2、如果此时误按回车、空格等,程序会提示重新扫码;
        3、如果扫码错误(即扫码结果不是个13位长的数字),程序会提示重新扫码;
        4、如果扫码正确,但商品不在“总库.xlsx”中,程序会提示后结束,请重新打开程序进行入库操作;
        5、排除以上异常后,显示“应收XXX元”
        6、售卖结束后,直接在“请扫描商品条码:”后直接输入“0”或任意以“0”开始字符,程序会提示“按任意键结束售卖,退出程序”。
十五、程序在退出过程中,会显示本次售卖清单,包括每种商品卖出多少及金额,和售卖本次售卖总钱数,以及根据本次售卖对“总库.xlsx”的核减,主要是“总库.xlsx”中的“库存数量”和“库存金额”。
十六、本次售卖会保存为一个带当前时间戳的EXCEL文件,新总库文件也随即保存。整个程序正常结束。
十七、语音和图形界面,还不会加。想最后搞成鼠标操作的。
[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)

欢迎多多指出不足,不管是逻辑思路、语法技巧,必虚心接受!


免费评分

参与人数 2吾爱币 +2 收起 理由
阿傑 + 1 我很赞同!
5371753818 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 13832811375 发表于 2020-11-30 16:30
做成单文件后,居然有65M之多,现在一个简版的Office2003,不过二三十M,Office2010也不过六七十M,,,唉编程之路啊
as614001 发表于 2020-11-30 16:53
as614001 发表于 2020-11-30 16:54
python在于大量数据自动化 你这又增加又输入的(没看你的1-xx条)、,类似库存系统,找个excel版的库存系统吧。
zrwd01 发表于 2020-11-30 18:06
总算跑通了,,但是代码比较臃肿,应该可以精简...再看一下循环部分.
沐日黄泉 发表于 2020-11-30 18:09
不明觉厉 虽然看不懂但是很厉害
QingYi. 发表于 2020-11-30 18:32
看着比较臃肿的
江南烟雨终 发表于 2020-11-30 19:13
加油,还有优化空间
 楼主| 13832811375 发表于 2020-11-30 19:27
zrwd01 发表于 2020-11-30 18:06
总算跑通了,,但是代码比较臃肿,应该可以精简...再看一下循环部分.

发现有个计算错了,不过不是主要问题,现在主要问题是做成文件后太大,65M!
jyjjf 发表于 2020-11-30 19:28
你不配流程图啊
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-26 10:16

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表