SAP 系统中进行某些清账操作时,要求只选中金额汇总(黄色的行)为负数和 0 的项目进行清账,效果如图所示:
SAP 中有一个方法可以选中指定的行:
1 import sys 2 import win32com.client 3 4 SapGuiAuto = win32com.client.GetObject("SAPGUI") 5 application = SapGuiAuto.GetScriptingEngine 6 connection = application.Children(0) 7 session = connection.Children(0) # 连接SAP服务 8 9 e = session.findByID('wnd[0]/usr/cntlGRID1/shellcont/shell') # 获取SAP表格 10 e.selectedRows = '1'
如果要选中多行只需要这样写:
e.selectedRows = '1,2,3,5'
如果是连续的行可以更简单:
e.selectedRows = '1-5'
我们运行看一下效果:
需要注意一点,如果表很大时,表后面的部分没有加载,所以直接运行 e.selectedRows 没有效果,因此必须翻页,当翻到最后一页时运行就可以把需要的行都选中了。
翻页部分代码如下:
1 import ubpa.ikeyboard as ikeyboard 2 3 row = e.rowCount # 行数 4 print(row // 44) # 需要翻页的次数,44为当前页面显示的行数 5 6 for j in range(row // 44): 7 ikeyboard.key_send_cs(text='{PGDN}',waitfor=10) 8 time.sleep(0.4)
现在有个更优秀的翻页方法:http://support.isearch.com.cn/article/1544495156668
因此还是建议少用 pagedown 进行翻页。
下面开始设计算法:
我们需要三个列表,一个存金额汇总所在的行数,一个存每个金额汇总的标记(这边把金额为负和 0 的标记为负号,把金额为正的标记为正号),一个存所有负号的索引。分别命名为 index、type_index、need_index
①首先根据凭证编号遍历整张表,并把凭证编号为空行的索引加入到第一个列表中,这个就是金额汇总所在的行数:
1 for i in range(e.rowCount - 1): 2 value = e.getCellValue(i, e.columnOrder(0)) 3 if value == '': 4 index.append(i)
②然后给每个金额汇总打上标记并存入第二个列表中:
1 for i in index: 2 if e.getCellValue(i, e.columnOrder(12)).endswith('-') or e.getCellValue(i, e.columnOrder(12)) == '0.00': 3 type_index.append('-') 4 else: 5 type_index.append('+')
③接下来只要判断第二个列表中的标记,如果为负就取这个索引与上一个索引中间的值,把所有符合条件的值都加入到第三个列表中:
1 if type_index[0] == '+': 2 for i in range(len(type_index)): 3 if type_index[i] == '-': 4 if index[i - 1] + 1 == index[i] - 1: # 如果两个金额汇总之间只隔了一行 5 need_index.append(str(index[i - 1] + 1)) 6 else: 7 need_index.append(str(index[i - 1] + 1) + '-' + str(index[i] - 1)) 8 elif type_index[0] == '-': # 第一个金额汇总为负号的话情况稍微复杂点 9 if index[0] == 1: # 第一个金额汇总前面只有一行 10 need_index.append('0') 11 else: 12 need_index.append('0-' + str(index[0] - 1)) 13 for i in range(len(type_index) - 1): 14 if type_index[i + 1] == '-': 15 if index[i] + 1 == index[i + 1] - 1: 16 need_index.append(str(index[i]+1)) 17 else: 18 need_index.append(str(index[i] + 1) + '-' + str(index[i + 1] - 1))
④need_index 现在包含了所有需要选择的行,接下来把它变成我们需要的字符串格式:
e.selectedRows = ','.join(need_index)
算法的时间复杂度还是高了点,如果你们有更好的思路也可以分享出来
完整代码
1 import sys 2 import win32com.client 3 import time 4 import ubpa.ikeyboard as ikeyboard 5 6 SapGuiAuto = win32com.client.GetObject("SAPGUI") 7 application = SapGuiAuto.GetScriptingEngine 8 connection = application.Children(0) 9 session = connection.Children(0) # 连接SAP服务 10 11 e = session.findByID('wnd[0]/usr/cntlGRID1/shellcont/shell') # 获取SAP表格 12 13 f = e.columnCount # 列数 14 row = e.rowCount # 行数 15 print('表格行数为{},表格列数为{}'.format(row, f)) 16 print('-' * 20) 17 print(int(row / 44)) #需要翻页的次数 18 19 for j in range(int(row / 44)): 20 ikeyboard.key_send_cs(text = '{PGDN}',waitfor = 10) 21 time.sleep(0.4) 22 23 index = [] #金额汇总所在的行数 24 type_index = [] #每个金额汇总的正负值,若为0也标记为负值 25 need_index = [] #所有负值的索引 26 27 for i in range(e.rowCount - 1): 28 value = e.getCellValue(i, e.columnOrder(0)) 29 if value == '': 30 index.append(i) 31 32 print('每个金额汇总所在的索引为{},总共的客户数量为{}'.format(index, len(index))) 33 print('-'*20) 34 35 for i in index: 36 if e.getCellValue(i, e.columnOrder(12)).endswith('-') or e.getCellValue(i, e.columnOrder(12)) == '0.00': 37 type_index.append('-') 38 else: 39 type_index.append('+') 40 41 if type_index[0] == '+': 42 for i in range(len(type_index)): 43 if type_index[i] == '-': 44 if index[i - 1] + 1 == index[i] - 1: 45 need_index.append(str(index[i - 1] + 1)) 46 else: 47 need_index.append(str(index[i - 1] + 1) + '-' + str(index[i]-1)) 48 elif type_index[0] == '-': 49 if index[0] == 1: 50 need_index.append('0') 51 else: 52 need_index.append('0-' + str(index[0] - 1)) 53 for i in range(len(type_index) - 1): 54 if type_index[i + 1] == '-': 55 if index[i] + 1 == index[i + 1] - 1: 56 need_index.append(str(index[i] + 1)) 57 else: 58 need_index.append(str(index[i] + 1) + '-' + str(index[i + 1] - 1)) 59 60 e.selectedRows = ','.join(need_index)
原文链接:https://support.i-search.com.cn/article/1542766504938