python驱动SAP完成数据导出(二)

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

快来扫码关注我的公众号 获取更多爬虫、数据分析的知识!

 

posted @ 2022-01-10 09:57  NewJune  阅读(2153)  评论(22编辑  收藏  举报