python驅動SAP完成資料匯出(二)

NewJune發表於2022-01-10

  在上一篇 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(* ̄▽ ̄*)ブ

快來掃碼關注我的公眾號 獲取更多爬蟲、資料分析的知識!

 

相關文章