Python讀取含有VBA宏的Excel數據

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哦~~)

 

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

相關文章
相關標籤/搜索