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哦~~)
由於項目太忙了,因此寫的都是流水帳,若是你們有什麼更好的建議或者疑問,能夠給我留言哦,謝謝閱讀~~