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()
原文地址:https://www.cnblogs.com/www123yyy123/p/13560713.html