在上一篇 python驅動SAP完成資料匯出(一)中,我們提到了資料匯出前,SAP佈局的重要性,如何識別當前佈局模式,以及如何切換到想要的佈局。本篇小爬將著重講講資料匯出的注意事項。
我們可以通過如下方式進行匯出:
其中方法一與方法三並無本質差別,最終都是可以指令碼錄製或者快捷鍵(Ctrl+Shift+F7)得到,點選匯出按鈕後,介面【選擇電子表格】如下:
但是假如使用者曾經勾選過上圖中的【始終使用選定的格式】,那麼則不會彈出上圖所示視窗,直接進入如下介面:
注意一:
如果使用者執行操作前沒有點選【指令碼錄製】,則會彈出如下windows【另存為】介面:
由於該介面是windows系統窗體,無法通過指令碼錄製得到自動化指令碼程式碼,所以我們務必要提前進行指令碼錄製動作,才能確保檔案儲存的介面可通過錄制指令碼得到程式碼。
注意二:
如果我們一開始選擇的方法二 進行資料匯出,則無論使用者是否勾選【始終使用選定的格式】選項,SAP均會彈出【選擇電子表格】介面。
因此,為了避免操作介面不一致帶來的程式碼相容問題,小爬建議大家使用方法二來執行資料匯出。
最後的匯出介面,使用者可以設定儲存的路徑和檔名,最後基於各自的情況點選【生成】或者【替代】按鈕(【替代】按鈕,意味著如果設定目錄中如果提前有同名檔案,則會被新檔案覆蓋)。
點選完匯出後,SAP會預設呼叫Excel程式,生成一個Excel檔案,持續往該檔案中傳輸值,待傳輸完畢後,SAP左下角會有訊息顯示:已傳輸***個位元組。且該Excel檔案會被excel自動開啟。
那麼問題來了,如果我們要通過指令碼批量下載多個報表資料,則SAP會自動建立並開啟N個excel檔案,此舉很有可能導致系統記憶體緊張甚至excel檔案崩潰。因此我們有必要及時自動關閉Excel檔案。這該如何處理呢?
顯然,我們必須藉助於windows系統api來實現,python下就必須依託於pywin32庫。同時我們還要藉助SPY++提前捕獲視窗資訊。
可以看到當系統是否隱藏了副檔名,最後視窗標題是有差別的,而FindWindow函式本身不支援基於視窗標題模糊查詢,我們程式碼裡不得不特殊化處理。
基於前文提到的方法二匯出的,具體的示例程式碼如下(FB03為例):
1 import sys, win32com.client,os,win32gui,win32con,time 2 def Main(): 3 try: 4 SapGuiAuto = win32com.client.GetObject("SAPGUI") 5 application = SapGuiAuto.GetScriptingEngine 6 connection = application.Children(0) 7 if connection.DisabledByServer == True: 8 print("Scripting is disabled by server") 9 application = None 10 SapGuiAuto = None 11 return 12 13 session = connection.Children(0) 14 if session.Busy == True: 15 print("Session is busy") 16 session = None 17 connection = None 18 application = None 19 SapGuiAuto = None 20 return 21 22 if session.Info.IsLowSpeedConnection == True: 23 print("Connection is low speed") 24 session = None 25 connection = None 26 application = None 27 SapGuiAuto = None 28 return 29 30 session.findById("wnd[0]").maximize() 31 session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").contextMenu() 32 session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell").selectContextMenuItem("&XXL") 33 session.findById("wnd[1]/tbar[0]/btn[0]").press() 34 session.findById("wnd[1]/usr/ctxtDY_PATH").text = os.getcwd() #儲存路徑 35 session.findById("wnd[1]/usr/ctxtDY_FILENAME").text = "reportList.xlsx" #儲存檔名 36 session.findById("wnd[1]/tbar[0]/btn[11]").press() #點選【替代】,覆蓋可能的原檔案 37 sapInfo=session.findById("wnd[0]/sbar").text #由於SAP指令碼自身的特性,當程式讀到左下角訊息時,意味著資料已經傳輸完成! 38 39 '''找到開啟的excel檔案,並自動關閉它''' 40 excelHwnd=0 41 while ExcelHwnd==0: 42 time.sleep(0.2) 43 excelHwnd=max(win32gui.FindWindow("XLMAIN","reportList.XLSX - Excel"),win32gui.FindWindow("XLMAIN","reportList - Excel")) 44 45 '''以防SAP沒有完全釋放Excel程式,建議等待excel視窗可見後,再關閉它''' 46 isVisible=False 47 while isVisible==False: 48 time.sleep(0.2) 49 isVisible=win32gui.IsWindowVisible(excelHwnd) 50 51 '''關閉excel程式''' 52 win32gui.SendMessage(excelHwnd,win32con.WM_CLOSE,None,None) 53 54 55 except Exception as e: 56 print(e) 57 print(sys.exc_info()[0]) 58 59 finally: 60 session = None 61 connection = None 62 application = None 63 SapGuiAuto = None 64 65 Main()
各位筒子,趕快動手試下吧o(* ̄▽ ̄*)ブ
快來掃碼關注我的公眾號 獲取更多爬蟲、資料分析的知識!