1. 什么是VBA?python
具体含义你们能够看百度百科,我就直接上图了,每一个单元格都是调用了VBA的宏计算语言函数,我就简称这个Excel含有macro计算逻辑吧。数组
2.问题是什么?app
你们都知道要比较一个API的准确性,咱们须要本身根据方法论去把全部原始数据都推演计算一遍,获得结果。而后在跟开发作的API response作下对比,若是两个结果相同,则表示这个API计算正确。函数
如今咱们PO不让我重写一遍开发的计算逻辑了,规定全部计算相关的逻辑都在Excel里面作好计算模板sheet,而后我将全部原始数据都放到计算模板同一个文件夹下。在含有Marco计算逻辑的那个excel(计算模板sheet)里面完成数据的引用和计算。ui
而后将API返回的Response也写入到同目录下的一个Excel中(样式跟计算模板计算出来的结果相同),模板里面将比较API response和Excel中的计算结果,而后输出一个如上图同样的一个sheet页(二维矩阵,单元格里的内容是TRUE或者FALSE)。spa
我要作的就是:将原始数据放到规定名字和格式的Excel中,将最终API的response也放到Excel中,而后打开这个含有macro函数的excel,查看sheet页中是否含有FALSE,若是有,告诉对应的行和列名称并输出。如果没有FALSE,这说明比对经过,API pass。excel
难点是:ip
我用Python写函数,如今Python用pandas打开这个含有Macro函数的Excel后,读出的数据永远都是Nan,由于它不能识别那些macro函数。。。因此我没法判断该API是否pass。开发
3. 手动操做Excel的时候要怎样看到是TRUE或FALSE呢?rem
在打开这个有macro函数的Excel以前,咱们须要打开全部它引用的其余Excel。而后回到这个Excel的时候,这些宏会自动引用其余excel相应的数据,并得出计算结果。
4. 用Python要怎样实现这一手动逻辑呢?
在Python中调用VBA去控制这些Excel便可。
5. 具体要怎样实现呢?
a. 下载Python扩展包: pywin32 (这个有32和64位之分)
能够直接去下载zip文件,而后安装;
但我建议直接用命令: pip install pywin32
b. 在本身python文件中引用: from win32com import client
from win32com import client
c. 在python中写VBA:
#打开Excel应用,而且依次打开该计算模板Excel依赖的全部excel文件,而后打开最终计算模板excel xlApp = client.Dispatch('Excel.Application') # xlApp.visible默认是0,就是不显示全部Excel文件窗口哦 xlApp.visible = 1 # Open original excels in the given absolute path one by one suite_name = suite_path.split(".")[-1] file_names = filter(lambda x: x.find("File") > -1, input_params.keys()) for file_name in file_names: # excel = pd.ExcelFile("OutputExcel/%s/%s" % (suite_name, input_params[file_name])) xlApp.Workbooks.Open(r"%s\APG_API_RobotFramework\OutputExcel\%s\%s" % (workspace_path, suite_name, input_params[file_name])) # Open the result excel and check data xlBook = xlApp.Workbooks.Open("%s\APG_API_RobotFramework\OutputExcel\%s\%s" % (workspace_path, suite_name, RESULT_EXCEL)) xlsheet = xlBook.Worksheets("Result")
# 操做Excel可能会出错,因此须要用到try, finally结构块 try: # Store calculation result into result_list rows = xlsheet.UsedRange.Rows.Count columns = xlsheet.UsedRange.Columns.Count # 读取作好的比较数据模板sheet页中的数据并放入二维数组中 result_list = [] for row in range(1, rows): temp_list = [] for column in range(1, columns): temp_list.append(str(xlsheet.Cells(row, column))) result_list.insert(row-1, temp_list) # print result_list # Get row and column title, then remove titles' values and put left values into new_list row_title = [x[0] for x in result_list][1:] column_title = [y for y in result_list[0]][1:] # print("row title : ", row_title) # print("column title :", column_title) new_list = [] for x in result_list[1:]: new_list.append(x[1:]) # print new_list # 由于最终要提示用户FALSE单元格对应的行和列名称,因此我用pandas来构造DataFrame,这样效率很高 # Put data into DataFrame then select values which are "FALSE" df = pd.DataFrame(data=new_list, index=row_title, columns=column_title) fail_list = [] for index, row in df.iterrows(): if row[0] == "False": fail_list.extend([index, row[0]]) # 若找到FALSE单元格,则提示具体错误信息,不然打印比较成功的提示 assert fail_list.__len__() == 0, "Failed cells are : "+str(fail_list) print "Compare successfully !" finally: # Don't let the save dialog pop up when close (Since the result excel shouldn't be saved) xlApp.DisplayAlerts = 0 # xlBook.Save() xlBook.Close() xlApp.Workbooks.Close() # xlApp.visible = 0 xlApp.Quit()
finally中的语句很是关键,至关于open一个文件以后进行读写,最终必定要关闭对应的io流同样!
那个计算模板是不容许改动的,因此在关闭那个xlBook的时候老是提示是否须要保存,在Jenkins上配置这个Project以后,全部相关操做确定是没法手动干预的。因此我就采起了最直接的方式:
xlApp.DisplayAlerts = 0
就是不弹出全部提示框。
先关闭计算模板Excel,而后关闭该Excel依赖的全部其余Excel。
最后退出Excel应用程序。
(如果最后退出程序之后发现还有一个空白的Excel窗口,这时候能够用 xlApp.visible=0 来隐藏)
全部这些都执行完了之后,这些被操做过的文件就不会被锁住了。(如果被锁住,之后用python读取的时候都会提示IOException哦~~)
由于项目太忙了,因此写的都是流水帐,若是你们有什么更好的建议或者疑问,能够给我留言哦,谢谢阅读~~