在上一篇 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(* ̄▽ ̄*)ブ
快來掃碼關注我的公衆號 獲取更多爬蟲、數據分析的知識!