• Python系列(7)——使用openpyxl写银行系统


      1 # -*-coding:utf-8 -*-
      2 # 使用openpyxl操作xlsx文件数据,可以在同一excel中新建其他sheet
      3 import pandas as pd
      4 import time
      5 import openpyxl
      6 import openpyxl.styles   # 设置格式
      7 file_path = r'E:学习PythonPandas模块的导入及学习-数据分析ank.xlsx'  # 若是同一项目下的文件,可直接使用'./bank.xlsx'文件路径即可
      8 bank_file = openpyxl.load_workbook(file_path)
      9 bank = bank_file['user']
     10 bank_error = bank_file['input_error']
     11 
     12 
     13 def home_page():   # 主界面
     14     print('欢迎使用ATN银行自助系统'.center(40, '='))
     15     print('1.登录账户'.center(40, ' '))
     16     print('2.注册账户'.center(40, ' '))
     17     print('3.退出系统'.center(40, ' '))
     18     print('欢迎使用ATM银行自助系统'.center(40, '='))
     19 
     20 
     21 def welcome_page():  # 登录成功界面
     22     print('欢迎使用银行ATM自助服务系统'.center(60, '='))
     23     print('* 您好 %s *'.center(60, ' ') % input_name)
     24     print()
     25     print('1.查询余额      2.自助取款'.center(60, ' '))
     26     print('3.自助存款      4.修改密码'.center(60, ' '))
     27     print('5.查询操作历史   6.回主菜单'.center(60, ' '))
     28     print('    7.退出系统                '.center(60, ' '))
     29     print()
     30     print('欢迎使用银行ATM自助服务系统'.center(60, '='))
     31 
     32 
     33 def judge(input_date):  # 判断输入的时间是否正确
     34     date = input_date.split('-')   # 用-符将数据分隔开
     35     list1 = []
     36     if len(date) == 3:
     37         for j in range(len(date)):
     38             if date[j].isdigit():
     39                 list1.append(int(date[j]))
     40             else:
     41                 print('输入数据非纯数字,请重新输入')
     42                 break
     43         else:   # 都是数字执行完后,执行的内容
     44             year, month, day = list1[0], list1[1], list1[2]
     45             if len(str(year)) == 4:  # int型数据无len
     46                 if 0 < month <= 12:
     47                     if (month in (1, 3, 5, 7, 8, 10, 12)) and (day > 31 or day <= 0):
     48                         print(f'输入日期有误,{month}为大月,天数最多为31天,请重新输入!')
     49                     elif (month in (4, 6, 9, 11)) and (day > 30 or day <= 0):
     50                         print(f'输入日期有误,{month}为小月,天数最多为30天,请重新输入!')
     51                     elif month == 2:
     52                         if ((year % 4 == 0) and (year % 100 != 0)) or (year % 400 == 0):
     53                             if (day > 29) or (day <= 0):
     54                                 print('输入的日期有误,该年2月为闰年2月,最多29天。请重新输入!')
     55                         else:
     56                             if (day > 28) or (day <= 0):
     57                                 print('输入的日期有误,该年2月为平年2月,最多28天。请重新输入!')
     58                     else:
     59                         return True
     60                 else:
     61                     print('输入的月份错误,每年只有12个月,请重新输入')
     62             else:
     63                 print('输入日期有误,年份必须是四位数,请重新输入')
     64     else:
     65         print('输入的日期长度有误,请重新输入')
     66 
     67 
     68 def bank_list():   # 将name/password列表化
     69     global name_list, password_list,error_name_list
     70     name_list, password_list, error_name_list = [], [], []
     71     error_row = bank_error.max_row
     72     row = bank.max_row
     73     # bank_file中各sheet的行和列写在此处,否则excel中的数据不是即时的数据,保存后继续执行可能无法立即查询到
     74     # 此步骤涉及到login()处bank_error添加登录错误的新成员、add_user()处bank添加账户的新成员问题
     75     for i in range(1, row + 1):  # 将password这一列转为字符串类型
     76         str(bank.cell(i, 2).value)
     77     for j in range(2, row+1):
     78         name_list.append(bank.cell(j, 1).value)     # name第一列数据,从第2行开始读取
     79         password_list.append(bank.cell(j, 2).value)  # password第二列数据,....
     80     for k in range(2, error_row+1):
     81         error_name_list.append(bank_error.cell(k, 1).value)  # error_name第一列数据...
     82 
     83 
     84 def re_password():  # 修改密码
     85     old_password = input('请输入原6位数密码:')
     86     if old_password == password_list[new_index]:
     87         while True:
     88             new_password = input('请输入新6位数密码:')
     89             again_password = input('请再次输入新6位数密码:')
     90             if new_password == '' or again_password == '':
     91                 print('密码不能为空,请重新输入')
     92             elif new_password == again_password and new_password != '':
     93                 if new_password.isdigit():  # 判断是否是纯数字
     94                     if len(new_password) == 6:  # 判断长度是否为6
     95                         print('密码修改成功')
     96                         bank.cell(new_index + 2, 2, new_password)
     97                         history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    修改密码')
     98                         bank.cell(new_index + 2, 4, str(history_list))
     99                         bank_file.save(file_path)
    100                         break
    101                     else:
    102                         print('密码长度错误,请重新输入6位有效数字密码!')
    103                 else:
    104                     print('密码应为纯数字密码,请输入6位有效数字密码!')
    105             elif new_password != again_password:
    106                 print('两次密码输入不一致,请重新输入')
    107 
    108     elif old_password != password_list[new_index]:
    109         print('原密码输入错误,请重新输入')
    110         re_password()
    111     else:
    112         print('请输入有效的数字')
    113 
    114 
    115 def search_record():   # 查询历史记录
    116     while True:
    117         start_date = input('请输入查询开始时间Y-m-d:')  # 若想精确到时分秒,切片10变成取到19即可
    118         if judge(start_date):
    119             while True:
    120                 end_date = input('请输入查询结束时间Y-m-d:')
    121                 if judge(end_date):
    122                     start_time = pd.to_datetime(start_date)  # 将输入的文本转化为时间格式
    123                     end_time = pd.to_datetime(end_date)
    124                     if start_time > end_time:
    125                         print('开始时间大于结束时间,请重新输入时间')
    126                         break
    127                     else:
    128                         print(f'查询开始时间为:{start_date}')
    129                         print(f'查询结束时间为:{end_date}')
    130                         record = []
    131                         for j in history_list:
    132                             if start_time <= pd.to_datetime(j[0:10:]) <= end_time:  # 对列表中的时间进行切片处理并转为时间格式
    133                                 print(j)
    134                                 record.append(j)
    135                         else:  # for正常执行完,会执行else内容,不正常结束,不执行else内容--可避免筛选出一条记录跟着打印出一条提示内容
    136                             if len(record) != 0:
    137                                 print(f'该时间段的操作记录有{len(record)}条')
    138                             # 该时间段的历史记录导出到新excel中
    139                                 out_put = input('是否导出到新excel?1.是,2.否--')
    140                                 if out_put == '1':  # 导出
    141                                     new_excel = openpyxl.Workbook()
    142                                     new_sheet = new_excel.active   # 当前活跃的sheet,默认第一个sheet,也可使用create_sheet
    143                                     new_sheet.title = f'{start_date}-{end_date}时间段的历史记录'
    144                                     new_sheet.append(['时间', '操作记录'])
    145                                     font = openpyxl.styles.Font('宋体', size=11, bold=True, color='000000')  # 设置单元格格式
    146                                     new_sheet['A1'].font = font
    147                                     new_sheet['B1'].font = font
    148                                     list_record = []
    149                                     for i in record:
    150                                         list_record.append(i[0:19])
    151                                         list_record.append(i[23::])  # 将时间字段与操作名称拆开放入列表中
    152                                     temp_list = zip(*(iter(list_record),) * 2)  # 将列表中的数据拆成2个元素组成一个列表
    153                                     for j in temp_list:
    154                                         new_sheet.append(list(j))   # 数据写入到new_sheet中
    155                                     """
    156                                     将列表中的数据拆成2个元素组成一个列表也可写成下面这种代码:
    157                                     for k in range(0, len(list_record), 2):
    158                                         list2 = list()
    159                                         list2.append(list1[k])
    160                                         list2.append(list1[k+1])
    161                                         new_sheet.append(list2)
    162                                     """
    163                                     filename = 'C://Users//Administrator//Desktop//' 
    164                                                + f'{input_name}的{start_date}-{end_date}间的操作记录' + '.xlsx'
    165                                     # 这里的路径是进行组合的,因此不能写成r‘/’的形式,这种形式无法组合,写成//路径即可实现组合
    166                                     new_excel.save(filename)
    167                                     print('历史记录导出成功')
    168                                 else:
    169                                     input('>>按确定键继续为您服务<<')
    170                             else:
    171                                 print('该时间段无操作记录')
    172                         history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    查询历史')
    173                         bank.cell(new_index + 2, 4, str(history_list))
    174                         bank_file.save(file_path)
    175                         break
    176             break
    177 
    178 
    179 def work():   # 主界面程序
    180     while True:
    181         welcome_page()
    182         action_str2 = input('请输入您的操作:')
    183         if action_str2 == '1':  # 查询余额
    184             print(f'你的账户余额是:{bank.cell(new_index+2, 3).value} 元')
    185             history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    查询余额')
    186             bank.cell(new_index+2, 4, str(history_list))
    187             # bank.cell(new_index+2, 4).value = str(history_list)
    188             bank_file.save(file_path)
    189             input('>>按确定键继续为您服务<<')
    190         elif action_str2 == '2':  # 取款
    191             money_out = int(input('请输入取款金额:'))
    192             if money_out <= bank.cell(new_index+2, 3).value:
    193                 bank.cell(new_index+2, 3).value -= money_out
    194                 print(f"您的取款金额为{money_out}元,剩余金额为{bank.cell(new_index+2, 3).value}元")
    195                 history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    取款'
    196                                     + str(money_out)+'')
    197                 bank.cell(new_index + 2, 4, str(history_list))
    198                 bank_file.save(file_path)
    199             else:
    200                 print('您的余额不足,请重新选择金额')
    201             input('>>按确定键继续为您服务<<')
    202         elif action_str2 == '3':  # 存款
    203             money_in = int(input('请输入存款金额:'))
    204             bank.cell(new_index+2, 3).value += money_in
    205             print(f"您的存款金额为{money_in}元,剩余金额为{bank.cell(new_index+2, 3).value}元")
    206             history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    存款' + str(money_in)+'')
    207             bank.cell(new_index + 2, 4, str(history_list))
    208             bank_file.save(file_path)
    209             input('>>按确定键继续为您服务<<')
    210         elif action_str2 == '4':  # 修改密码
    211             re_password()
    212             print('即将退出当前界面,重新登录')
    213             input('>>按确定键继续为您服务<<')
    214             main_menu()
    215         elif action_str2 == '5':  # 查询操作记录
    216             # 历史记录太多,也可再建一个sheet专门放历史记录,列名为客户名、时间、操作记录,(建议再加一个客户id号,同名的人查询不会出错)
    217             # 也就是每一步操作后再sheet.append([input_name,操作的时间,操作的记录]),相应的查询操作历史处代码也要跟着改变
    218             search_record()
    219             while True:
    220                 action_str3 = input('请输入您的操作1.继续查询历史;2.回到操作界面---')
    221                 if action_str3 == '1':
    222                     search_record()
    223                 elif action_str3 == '2':
    224                     break
    225                 else:
    226                     print('输入错误,请重新输入')
    227             input('>>按确定键继续为您服务<<')
    228         elif action_str2 == '6':  # 回主菜单
    229             history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    退回主界面')
    230             bank.cell(new_index + 2, 4, str(history_list))
    231             bank_file.save(file_path)
    232             main_menu()
    233         elif action_str2 == '7':  # 退出系统
    234             input('>>按确定键退出系统<<')
    235             print('欢迎您的下次光临')
    236             history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    退出系统')
    237             bank.cell(new_index + 2, 4, str(history_list))
    238             bank_file.save(file_path)
    239             exit()
    240         else:
    241             print('您的输入有误,请重新输入')
    242             input('>>按确定键继续为您服务<<')
    243 
    244 
    245 def login():   # 登录账户
    246     global input_name,history_list,new_index
    247     while True:
    248         bank_list()
    249         input_name = input('请输入您的姓名:')
    250         input_password = input('请输入您的密码:')
    251         if input_name in name_list and input_password != '':
    252             new_index = name_list.index(input_name)
    253             if input_password == password_list[new_index]:
    254                 # ps:单纯的姓名与密码登录不够严谨,因为若有同名的,只要保证输入的密码是其中一个就能登录成功,因此可再加入身份证,id等字段验证
    255                 history_list = eval(bank.cell(new_index+2, 4).value)  # # 转化为原列表形式
    256                 history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())+'    登录系统')
    257                 bank_file.save(file_path)
    258                 work()
    259             else:  # 输入名字不在,创建数据;输入名字在列表中,时间为今天,先判断次数,再继续计算次数;时间不是今天,将时间设为今天,次数变为1,与创建数据一致
    260                 print('账户和密码不匹配,请重新输入')
    261                 error_time = time.strftime('%Y-%m-%d', time.localtime())
    262                 if input_name not in error_name_list:
    263                     value = [input_name, 1, error_time]
    264                     bank_error.append(value)
    265                     bank_file.save(file_path)
    266                     print('今日已输入错误1次,还剩2次机会')
    267                     # 加入的名字,执行后,不在error_name_list里是因为bank_error表的行数没有跟着更新,因此在bank_list()处写行数,而不是开头
    268                 else:
    269                     error_index = error_name_list.index(input_name)
    270                     if error_time == bank_error.cell(error_index+2, 3).value:
    271                         if bank_error.cell(error_index+2, 2).value == 3:   # 先判断今日已输入的错误次数,再进行次数计算
    272                             print('今日输入次数已达上限,请明日再来')
    273                             break
    274                         else:
    275                             bank_error.cell(error_index + 2, 2).value += 1
    276                             bank_file.save(file_path)
    277                             if bank_error.cell(error_index + 2, 2).value == 2:
    278                                 print('今日已输入错误2次,还剩1次机会')
    279                             elif bank_error.cell(error_index + 2, 2).value == 3:
    280                                 print('今日已输入错误3次,无输入机会,请明日再来')
    281                     else:
    282                         bank_error.cell(error_index + 2, 1, input_name)
    283                         bank_error.cell(error_index + 2, 2, 1)
    284                         bank_error.cell(error_index + 2, 3, error_time)
    285                         bank_file.save(file_path)
    286                         print('今日已输入错误1次,还剩2次机会')
    287         elif input_name == '' or input_password == '':
    288             print('姓名或密码不能为空,请重新输入')
    289         elif input_name not in name_list:
    290             print('此用户不存在,请重新输入')
    291 
    292 
    293 def add_user():   # 添加账户
    294     while True:
    295         while True:
    296             bank_list()
    297             new_name = input('请输入新账户名:')
    298             if new_name in name_list:
    299                 print('该账户名已存在,请重新输入')
    300             elif new_name == '':
    301                 print('账户名不得为空,请重新输入')
    302             elif new_name not in name_list and new_name != '':
    303                 new_user = {'name': new_name}
    304                 break
    305 
    306         while True:
    307             set_new_password = input('请输入6位数密码:')
    308             re_set_new_password = input('请再次确认6位数密码:')
    309             if set_new_password == '' or re_set_new_password == '':
    310                 print('密码不能为空,请重新输入')
    311             elif set_new_password == re_set_new_password and set_new_password != '':
    312                 if set_new_password.isdigit():
    313                     if len(set_new_password) == 6:
    314                         print('恭喜您,新用户注册成功')
    315                         new_user['password'] = set_new_password
    316                         break
    317                     else:
    318                         print('密码长度错误,请重新输入6位有效数字密码!')
    319                 else:
    320                     print('密码应为纯数字密码,请输入6位有效数字密码!')
    321             elif set_new_password != re_set_new_password:
    322                 print('两次密码输入不一致,请重新输入')
    323 
    324         # 新用户预存金额
    325         select = input('是否需要预存金额,需要请输入“1”后按确认键:')
    326         if select == '1':
    327             new_balance = int(input('请输入您的预存金额:'))
    328             new_user['balance'] = new_balance
    329             print(f'预存款成功,存款金额为:{new_balance}元')
    330         else:
    331             new_user['balance'] = 0
    332 
    333         new_history = list()  # 先声明其是空列表,若直接用[]赋值,会警告
    334         # 或者直接这种赋值 new_history = [time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    注册账户']
    335         new_history.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    注册账户')
    336         new_user['history'] = str(new_history)
    337         new_user_list = []
    338         for key, value in new_user.items():
    339             new_user_list.append(value)
    340         bank.append(new_user_list)
    341         bank_file.save(file_path)   # 时效性问题,即刚注册完接着登录时是找不到该用户的,因为登录时读取的bank_file是之前打开的
    342         # 因此在name_list()处读取各sheet的行列,此时的数据都是添加保存后的数据,而不是把行列写在开头处
    343         input('>>按确定键继续为您服务<<')
    344         break
    345 
    346 
    347 def main_menu():   # 主函数
    348     while True:
    349         home_page()
    350         action_str = input('请输入您的选择1-登录账户,2-注册账户,3-退出系统: ')
    351         if action_str == '1':
    352             # 登录账户
    353             login()
    354         elif action_str == '2':
    355             # 注册账户
    356             add_user()
    357         elif action_str == '3':
    358             input('>>按确定键退出系统<<')
    359             print('欢迎您的下次光临')
    360             bank_file.close()  # 关闭文件
    361             exit()
    362         else:
    363             print('您的输入有误,请重新输入')
    364             input('>>按确定键继续为您服务<<')
    365 
    366 
    367 if __name__ == '__main__':
    368     main_menu()
  • 相关阅读:
    简单的javascript抽奖程序
    Linux 二层协议架构组织
    常用正则表达式总结
    很好的矩阵覆盖问题
    很好的求幂的题目
    不错的题目-n个数连接得到的最大值
    netstat命令介绍-要用熟
    一次完整的http事务
    Apache vs. Nginx
    Python学习-生成器
  • 原文地址:https://www.cnblogs.com/www123yyy123/p/13560713.html
Copyright © 2020-2023  润新知