一、目的

       动手写这个小功能主要出于简化工作量,提高工作效率。由于支付行业,每一笔资金的入款和出款都非常重要,所以测试过程中涉及到真实交易都需要记录,并发送给清算部门,方便资金的核对。如果某天测试数据量很大,那么几乎一个上午都用在手动整理交易记录表格上,则其他的测试计划可能被耽误,由此想到用python写一个小工具,只要输入商户编号、查询的开始时间和结束时间,则自动产生成一份对应商户某段时间内的入账记录excel。

二、环境

  • win7 64位系统
  • python 3.5 64位
  • oracle client 11gR2 64位
  • cx_Oracle-5.3-11g.win-amd64-py3.5-2.exe (md5)

三、思路

  • 连接oracle数据,通过查询数据库获取所需要的数据信息,保存到列表listA里
  • 先转化处理查询的数据listA,再写入到excel。
  • 编辑命令bat文件中的三个参数,通过双击bat文件,自动执行脚本生产入账记录表格

四、过程中遇到的坑以及解决办法

  • 环境配置的坑
  1. import cx_Oracle成功后,执行连接oracle数据库脚本,遇到报错:cx_Oracle.InterfaceError:Unable to acquire Oracle envirment handle

    解决办法:原先我的32位oracle版本不合适,开始想试过从其他同事的64位oracle安装目录下拷贝oci.dll、ocijdbc11.dll和oraociell.dll导入到python安装目录site-packages下,这种办法是不可行。正确的办法只有到oracle官网重新下载安装合适的oracle client版本。
  2. oracle的环境变量未配置
    解决办法:使用cx_Oracle模块需要配置python和oracle的环境变量。oracle需要配置2个值:环境变量增加ORACLE_HOME变量名,变量值指向oracle安装目录中oci.dll文件所在的路径;环境变量path后面加入oracle安装目录中oci.dll文件所在的路径。
  • 思路的坑
    1.查询数据处理和写excel逻辑的先后顺序
    正确思路:逻辑上应该先处理转化好查询的数据,再开始写入excel。由于入账记录表的数据模板都是公司制定好的,而数据库里获取的listA数据并不是完全符合,所以在写表之前,先处理listA数据,转化好数据。比如某些字段是数字,但是字段值代表的含义,非开发和测试人员根本不明白,所以不同的数字需要映射成不同内容;再比如我们的数据库表设计上消费和撤销都是同一笔流水数据,撤销数据是在消费数据上进行处理的,不会产生新的流水号,而入账记录表则需要分别记录消费和撤销两条数据。若是先写excel的话,再进行数据处理和插入数据,逻辑会更复杂,而且会更容易出现问题。
  • cx_Oracle中英文乱码的坑
    1.在使用cx_Oracle读取数据库,查询的中文信息出现?号
    解决办法:脚本头部加入如下2行代码
  • python辅助录入发票 python在自动录入会计凭证_excel


  • argv理解不够透彻
    1.使用argv传参,运行方法不正确(argv是获取命令行参数列表)
    遇到报错:print(sys.argv[1]) IndexError:list index out of range
  • python辅助录入发票 python在自动录入会计凭证_excel_02

  • 解决办法:应该在pycharmProjects工具下方的Terminal里执行:python xx.py aa 命令。sys.argv第一个参数是文件名,第二个参数开始是命令行输入的参数,以空格隔开。
  • python辅助录入发票 python在自动录入会计凭证_cx-Oracle_03


五、附上完整代码

import cx_Oracle,xlwt,time,sys 
 import os# 解决查询结果中文乱码的问题,设置oracle客户端的字符编码为utf-8 
 os.environ[‘NLS_LANG’] = ‘SIMPLIFIED CHINESE_CHINA.UTF8’print(sys.argv[0])#传入脚本路径 
 print(sys.argv[1])#传入商户编号 
 print(sys.argv[2])#传入查询开始时间,格式如: 2017-03-16T00:00:00Z 
 print(sys.argv[3])#传入查询结束时间,格式如: 2017-03-16T00:00:00ZEnvironment=’测试’ #环境 
 title = [ #excel字段内容 
 ‘创建时间’, 
 ‘环境’, 
 ‘转入账号’, 
 ‘交易渠道’, 
 ‘机构订单号’, 
 ‘交易金额’, 
 ‘手续费’, 
 ‘支付银行’, 
 ‘支付状态’, 
 ‘签购单打印状态’, 
 ‘交易类型’, 
 ‘备注’ 
 ] 
 chan ={ 
 0: ‘x1渠道’, 
 1: ‘x2渠道’, 
 2: ‘x3渠道’, 
 3: ‘x4渠道’} 
 cur_status = { 
 1: ‘支付成功’, 
 5: ‘撤销中’, 
 6: ‘撤销成功’, 
 9: ‘撤销失败’ 
 } 
 t = 0 
 types = [] #存放交易类型 
 prit = [] #存放签购单打印状态 
 resfull =[]#新列表,增加了撤销数据的原交易数据def get_oracle_data(agent_num,sstime,eetime):#获取查询结果函数 
 # 转换成时间数组 
 rtime = time.strptime(sstime, “%Y-%m-%dT%H:%M:%SZ”) 
 # 转换成时间戳 
 stime = time.mktime(rtime) 
 # 转换成时间数组 
 retime = time.strptime(eetime,”%Y-%m-%dT%H:%M:%SZ”) 
 # 转换成时间戳 
 etime = time.mktime(retime) 
 #查询的SQL语句 
 oracle_sql = ”’ 
 ….查询SQL语句省略…. 
 ”’%(agent_num,stime,etime) 
 host = “192.168.xxx.xx” 
 port = “1521” 
 sid = “xxxx” 
 user = “xxxx” 
 pwd = “xxxx” 
 dsn = cx_Oracle.makedsn(host, port, sid) 
 conn = cx_Oracle.connect(user, pwd, dsn) 
 cursor = cx_Oracle.Cursor(conn) 
 cursor.execute(oracle_sql) 
 res=cursor.fetchall() 
 cursor.close() 
 conn.close() 
 return resresults = get_oracle_data(sys.argv[1],sys.argv[2],sys.argv[3])#调用函数,产生查询结果数据
#写excel 
 wbk = xlwt.Workbook() 
 sheet = wbk.add_sheet(‘sheet1’) 
 for i in range(len(title)):#写表头 
 sheet.write(0,i,title[i])#处理转化查询的数据:映射部分字段数据,同时撤销数据前插入原消费交易数据,重新生成多个新的数组 
 for i in range(len(results)): 
 if results[i][5] == 1: 
 resfull.append(results[i]) 
 prit.append(‘打印成功’) 
 types.append(‘消费’) 
 elif results[i][5] == 6: 
 resfull.append((results[i][0],results[i][1],results[i][2],results[i][3],results[i][4],1,results[i][6],results[i][7])) 
 resfull.append(results[i]) 
 prit.append(‘打印成功’) 
 prit.append(‘打印成功’) 
 types.append(‘消费’) 
 types.append(‘消费撤销’) 
 else: 
 resfull.append((results[i][0], results[i][1], results[i][2], results[i][3], results[i][4], 1, results[i][6],results[i][7])) 
 resfull.append(results[i]) 
 prit.append(‘打印成功’) 
 prit.append(‘未打印’) 
 types.append(‘消费’) 
 types.append(‘消费撤销’)for i in range(len(resfull)):#循环新的列表,写入Excel 
 if resfull[i][5] ==1: 
 sheet.write(i + 1, title.index(‘机构订单号’), resfull[i][3]) 
 sheet.write(i + 1, title.index(‘交易金额’), resfull[i][7]) 
 else: 
 sheet.write(i + 1, title.index(‘机构订单号’), resfull[i][8]) 
 sheet.write(i + 1, title.index(‘交易金额’), -resfull[i][7]) 
 time_local = time.localtime(resfull[i][0]) 
 create_time = time.strftime(“%Y-%m-%d %H:%M:%S”, time_local) 
 sheet.write(i + 1, title.index(‘创建时间’), create_time)
sheet.write(i + 1, title.index('环境'), Environment)

sheet.write(i + 1, title.index('转入账号'), resfull[i][1])

channel = chan[(resfull[i][2])]
sheet.write(i + 1, title.index('交易渠道'), channel)

bank_name = (resfull[i][4]).split('::')[0]
sheet.write(i + 1,title.index('支付银行'),bank_name)

sheet.write(i + 1, title.index('支付状态'),cur_status[(resfull[i][5])])

sheet.write(i + 1, title.index('备注'), resfull[i][6])

sheet.write(i + 1, title.index('交易类型'), types[i])

sheet.write(i + 1, title.index('签购单打印状态'), prit[i])

wbk.save(‘xx入款对账记录-autoxxx.xls’)

六、总结

  • 过程中总会遇到各种问题,尝试在网上找解决办法,实在不行再请教其他人。
  • 先敲,一定要敲代码,自己一步步来,整个功能也就写出来了。
  • 上面的代码虽然功能是简单实现了,但是很多代码都存在重复,后面会慢慢优化。而且这个代码是一股脑的写下来的,没有什么结构化,异常处理逻辑也都忽略了。
  • 针对编辑bat文件达到参数的输入不是很方便,后面一篇准备尝试调用tkinter模块,实现在图形界面上输入需要的参数,启动自动生成入账记录脚本。
  • 最后生成的表格,如下图所示: