人在江湖~

做一个快乐学习的小透明~~~

导航

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:\学习\Python\Pandas模块的导入及学习-数据分析\bank.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         # 增加一个日期判断条件,即前面日期输入错误的数据不进行覆盖,只将今日错误的数据名字进行列表化
 82         # 不建议进行先遍历名字,再去判断日期,因为名字在之前可能也登录错误过,会造成索引有很多,匹配时只认第一个符合项
 83         if bank_error.cell(k, 3).value == time.strftime('%Y-%m-%d', time.localtime()):
 84             error_name_list.append(bank_error.cell(k, 1).value)  # error_name第一列数据...
 85 
 86 
 87 def re_password():  # 修改密码
 88     old_password = input('请输入原6位数密码:')
 89     if old_password == password_list[new_index]:
 90         while True:
 91             new_password = input('请输入新6位数密码:')
 92             again_password = input('请再次输入新6位数密码:')
 93             if new_password == '' or again_password == '':
 94                 print('密码不能为空,请重新输入')
 95             elif new_password == again_password and new_password != '':
 96                 if new_password.isdigit():  # 判断是否是纯数字
 97                     if len(new_password) == 6:  # 判断长度是否为6
 98                         print('密码修改成功')
 99                         bank.cell(new_index + 2, 2, new_password)
100                         history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    修改密码')
101                         bank.cell(new_index + 2, 4, str(history_list))
102                         bank_file.save(file_path)
103                         break
104                     else:
105                         print('密码长度错误,请重新输入6位有效数字密码!')
106                 else:
107                     print('密码应为纯数字密码,请输入6位有效数字密码!')
108             elif new_password != again_password:
109                 print('两次密码输入不一致,请重新输入')
110 
111     elif old_password != password_list[new_index]:
112         print('原密码输入错误,请重新输入')
113         re_password()
114     else:
115         print('请输入有效的数字')
116 
117 
118 def search_record():   # 查询历史记录
119     while True:
120         start_date = input('请输入查询开始时间Y-m-d:')  # 若想精确到时分秒,切片10变成取到19即可
121         if judge(start_date):
122             while True:
123                 end_date = input('请输入查询结束时间Y-m-d:')
124                 if judge(end_date):
125                     start_time = pd.to_datetime(start_date)  # 将输入的文本转化为时间格式
126                     end_time = pd.to_datetime(end_date)
127                     if start_time > end_time:
128                         print('开始时间大于结束时间,请重新输入时间')
129                         break
130                     else:
131                         print(f'查询开始时间为:{start_date}')
132                         print(f'查询结束时间为:{end_date}')
133                         record = []
134                         for j in history_list:
135                             if start_time <= pd.to_datetime(j[0:10:]) <= end_time:  # 对列表中的时间进行切片处理并转为时间格式
136                                 print(j)
137                                 record.append(j)
138                         else:  # for正常执行完,会执行else内容,不正常结束,不执行else内容--可避免筛选出一条记录跟着打印出一条提示内容
139                             if len(record) != 0:
140                                 print(f'该时间段的操作记录有{len(record)}条')
141                             # 该时间段的历史记录导出到新excel中
142                                 out_put = input('是否导出到新excel?1.是,2.否--')
143                                 if out_put == '1':  # 导出
144                                     new_excel = openpyxl.Workbook()
145                                     new_sheet = new_excel.active   # 当前活跃的sheet,默认第一个sheet,也可使用create_sheet
146                                     new_sheet.title = f'{start_date}--{end_date}时间段的历史记录'
147                                     new_sheet.append(['时间', '操作记录'])
148                                     font = openpyxl.styles.Font('宋体', size=11, bold=True, color='000000')
149                                     new_sheet['A1'].font = font
150                                     new_sheet['B1'].font = font
151                                     list_record = []
152                                     for i in record:
153                                         list_record.append(i[0:19])
154                                         list_record.append(i[23::])  # 将时间字段与操作名称拆开放入列表中
155                                     temp_list = zip(*(iter(list_record),) * 2)  # 将列表中的数据拆成2个元素组成一个列表
156                                     for j in temp_list:
157                                         new_sheet.append(list(j))   # 数据写入到new_sheet中
158                                     """
159                                     将列表中的数据拆成2个元素组成一个列表也可写成下面这种代码:
160                                     for k in range(0, len(list_record), 2):
161                                         list2 = list()
162                                         list2.append(list1[k])
163                                         list2.append(list1[k+1])
164                                         new_sheet.append(list2)
165                                     """
166                                     filename = 'C://Users//Administrator//Desktop//' \
167                                                + f'{input_name}的{start_date}-{end_date}间的操作记录' + '.xlsx'
168                                     # 这里的路径是进行组合的,因此不能写成r‘/’的形式,这种形式无法组合,写成//路径即可实现组合
169                                     new_excel.save(filename)
170                                     print('历史记录导出成功')
171                                 else:
172                                     input('>>按确定键继续为您服务<<')
173                             else:
174                                 print('该时间段无操作记录')
175                         history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    查询历史')
176                         bank.cell(new_index + 2, 4, str(history_list))
177                         bank_file.save(file_path)
178                         break
179             break
180 
181 
182 def work():   # 主界面程序
183     while True:
184         welcome_page()
185         action_str2 = input('请输入您的操作:')
186         if action_str2 == '1':  # 查询余额
187             print(f'你的账户余额是:{bank.cell(new_index+2, 3).value} 元')
188             history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    查询余额')
189             bank.cell(new_index+2, 4, str(history_list))
190             # bank.cell(new_index+2, 4).value = str(history_list)
191             bank_file.save(file_path)
192             input('>>按确定键继续为您服务<<')
193         elif action_str2 == '2':  # 取款
194             money_out = int(input('请输入取款金额:'))
195             if money_out <= bank.cell(new_index+2, 3).value:
196                 bank.cell(new_index+2, 3).value -= money_out
197                 print(f"您的取款金额为{money_out}元,剩余金额为{bank.cell(new_index+2, 3).value}元")
198                 history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    取款'
199                                     + str(money_out)+'')
200                 bank.cell(new_index + 2, 4, str(history_list))
201                 bank_file.save(file_path)
202             else:
203                 print('您的余额不足,请重新选择金额')
204             input('>>按确定键继续为您服务<<')
205         elif action_str2 == '3':  # 存款
206             money_in = int(input('请输入存款金额:'))
207             bank.cell(new_index+2, 3).value += money_in
208             print(f"您的存款金额为{money_in}元,剩余金额为{bank.cell(new_index+2, 3).value}元")
209             history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    存款' + str(money_in)+'')
210             bank.cell(new_index + 2, 4, str(history_list))
211             bank_file.save(file_path)
212             input('>>按确定键继续为您服务<<')
213         elif action_str2 == '4':  # 修改密码
214             re_password()
215             print('即将退出当前界面,重新登录')
216             input('>>按确定键继续为您服务<<')
217             main_menu()
218         elif action_str2 == '5':  # 查询操作记录
219             # 历史记录太多,也可再建一个sheet专门放历史记录,列名为客户名、时间、操作记录,(建议再加一个客户id号,同名的人查询不会出错)
220             # 也就是每一步操作后再sheet.append([input_name,操作的时间,操作的记录]),相应的查询操作历史处代码也要跟着改变
221             search_record()
222             while True:
223                 action_str3 = input('请输入您的操作1.继续查询历史;2.回到操作界面---')
224                 if action_str3 == '1':
225                     search_record()
226                 elif action_str3 == '2':
227                     break
228                 else:
229                     print('输入错误,请重新输入')
230             input('>>按确定键继续为您服务<<')
231         elif action_str2 == '6':  # 回主菜单
232             history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    退回主界面')
233             bank.cell(new_index + 2, 4, str(history_list))
234             bank_file.save(file_path)
235             main_menu()
236         elif action_str2 == '7':  # 退出系统
237             input('>>按确定键退出系统<<')
238             print('欢迎您的下次光临')
239             history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    退出系统')
240             bank.cell(new_index + 2, 4, str(history_list))
241             bank_file.save(file_path)
242             exit()
243         else:
244             print('您的输入有误,请重新输入')
245             input('>>按确定键继续为您服务<<')
246 
247 
248 def login():   # 登录账户
249     global input_name,history_list,new_index
250     while True:
251         bank_list()
252         input_name = input('请输入您的姓名:')
253         input_password = input('请输入您的密码:')
254         if input_name in name_list and input_password != '':
255             new_index = name_list.index(input_name)
256             # 增加一个判断,即若当日的错误次数已经达到3次,不能再进行登录,就算密码输入正确也不可以登录
257             if input_name in error_name_list:
258                 error_index = error_name_list.index(input_name)
259                 row = bank_error.max_row-len(error_name_list)+error_index+1 # 不是加2,因为前面的行数-时已经包含行标题那一行了
260                 # 总共的行数-今日错误的长度=原先错误的次数行数,再+对应今日错误的索引行数即变成了真正需要改变数值处所在的行数
261                 if bank_error.cell(row, 2).value == 3:
262                     print('该账户今日已经输入错误3次,禁止再登录')
263                     history_list = eval(bank.cell(new_index + 2, 4).value)  # # 转化为原列表形式
264                     history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    尝试登录系统,禁止登录')
265                     bank.cell(new_index + 2, 4, str(history_list))
266                     bank_file.save(file_path)
267                     break
268                 else:
269                     if input_password == password_list[new_index]:
270                         # ps:单纯的姓名与密码登录不够严谨,因为若有同名的,只要保证输入的密码是其中一个就能登录成功,因此可再加入身份证,id等字段验证
271                         history_list = eval(bank.cell(new_index + 2, 4).value)  # # 转化为原列表形式
272                         history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    登录系统')
273                         bank.cell(new_index + 2, 4, str(history_list))
274                         bank_file.save(file_path)
275                         work()
276                     else:
277                         # 输入名字在今日错误列表中
278                         print('账户和密码不匹配,请重新输入')
279                         bank_error.cell(row, 2).value += 1
280                         if bank_error.cell(row, 2).value == 2:
281                             print('今日已输入错误2次,还剩1次机会')
282                             history_list = eval(bank.cell(new_index + 2, 4).value)
283                             history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    尝试登录系统第2次')
284                             bank.cell(new_index + 2, 4, str(history_list))
285                             bank_file.save(file_path)
286                         elif bank_error.cell(error_index + 2, 2).value == 3:
287                             print('今日已输入错误3次,无输入机会,请明日再来')
288                             history_list = eval(bank.cell(new_index + 2, 4).value)
289                             history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    尝试登录系统第3次')
290                             bank.cell(new_index + 2, 4, str(history_list))
291                             bank_file.save(file_path)
292             elif input_name not in error_name_list:
293                 if input_password == password_list[new_index]:
294                     history_list = eval(bank.cell(new_index + 2, 4).value)
295                     history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    登录系统')
296                     bank.cell(new_index + 2, 4, str(history_list))
297                     bank_file.save(file_path)
298                     work()
299                 else:
300                     # 输入名字不在今日错误列表中,创建数据
301                     print('账户和密码不匹配,今日已输错1次,还剩2次机会')
302                     bank_error.append([input_name, 1, time.strftime('%Y-%m-%d', time.localtime())])
303                     history_list = eval(bank.cell(new_index + 2, 4).value)
304                     history_list.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    尝试登录系统第1次')
305                     bank.cell(new_index + 2, 4, str(history_list))
306                     bank_file.save(file_path)
307                     # 加入的名字,执行后,不在error_name_list里是因为bank_error表的行数没有跟着更新,因此在bank_list()处写行数,而不是开头
308         elif input_name == '' or input_password == '':
309             print('姓名或密码不能为空,请重新输入')
310         elif input_name not in name_list:
311             print('此用户不存在,请重新输入')
312 
313 
314 def add_user():   # 添加账户
315     while True:
316         while True:
317             bank_list()
318             new_name = input('请输入新账户名:')
319             if new_name in name_list:
320                 print('该账户名已存在,请重新输入')
321             elif new_name == '':
322                 print('账户名不得为空,请重新输入')
323             elif new_name not in name_list and new_name != '':
324                 new_user = {'name': new_name}
325                 break
326 
327         while True:
328             set_new_password = input('请输入6位数密码:')
329             re_set_new_password = input('请再次确认6位数密码:')
330             if set_new_password == '' or re_set_new_password == '':
331                 print('密码不能为空,请重新输入')
332             elif set_new_password == re_set_new_password and set_new_password != '':
333                 if set_new_password.isdigit():
334                     if len(set_new_password) == 6:
335                         print('恭喜您,新用户注册成功')
336                         new_user['password'] = set_new_password
337                         break
338                     else:
339                         print('密码长度错误,请重新输入6位有效数字密码!')
340                 else:
341                     print('密码应为纯数字密码,请输入6位有效数字密码!')
342             elif set_new_password != re_set_new_password:
343                 print('两次密码输入不一致,请重新输入')
344 
345         # 新用户预存金额
346         select = input('是否需要预存金额,需要请输入“1”后按确认键:')
347         if select == '1':
348             new_balance = int(input('请输入您的预存金额:'))
349             new_user['balance'] = new_balance
350             print(f'预存款成功,存款金额为:{new_balance}元')
351         else:
352             new_user['balance'] = 0
353 
354         new_history = list()  # 先声明其是空列表,若直接用[]赋值,会警告
355         # 或者直接这种赋值 new_history = [time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    注册账户']
356         new_history.append(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) + '    注册账户')
357         new_user['history'] = str(new_history)
358         new_user_list = []
359         for key, value in new_user.items():
360             new_user_list.append(value)
361         bank.append(new_user_list)
362         bank_file.save(file_path)   # 时效性问题,即刚注册完接着登录时是找不到该用户的,因为登录时读取的bank_file是之前打开的
363         # 因此在name_list()处读取各sheet的行列,此时的数据都是添加保存后的数据,而不是把行列写在开头处
364         input('>>按确定键继续为您服务<<')
365         break
366 
367 
368 def main_menu():   # 主函数
369     while True:
370         home_page()
371         action_str = input('请输入您的选择1-登录账户,2-注册账户,3-退出系统: ')
372         if action_str == '1':
373             # 登录账户
374             login()
375         elif action_str == '2':
376             # 注册账户
377             add_user()
378         elif action_str == '3':
379             input('>>按确定键退出系统<<')
380             print('欢迎您的下次光临')
381             bank_file.close()  # 关闭文件
382             exit()
383         else:
384             print('您的输入有误,请重新输入')
385             input('>>按确定键继续为您服务<<')
386 
387 
388 if __name__ == '__main__':
389     main_menu()

 

posted on 2020-08-25 17:10  人在江湖~  阅读(322)  评论(0编辑  收藏  举报