Hi, team:
Though I'm using Python as a platform, I'm basically using a VB Scripting to perform a series of steps in SAP. The script usually runs without issues, if we only have one session window open. The crashes happen at random iterations but usually happen when querying data from SAP, performing changes or saving changes. This causes the entire SAP GUI to close all session and conexions. Please advise.
import win32com.client
import sys
import subprocess
import time
import datetime
import pandas as pd
import numpy as np
def process_past(past_df):
try:
print('Connecting to SAP GUI...')
sapg = win32com.client.GetObject('SAPGUI')
if not type(sapg) == win32com.client.CDispatch:
return
appx = sapg.GetScriptingEngine
if not type(appx) == win32com.client.CDispatch:
sapg = None
return
conx = appx.Children(0)
if not type(conx) == win32com.client.CDispatch:
sapg = None
appx = None
return
ssnx = conx.Children(0)
if not type(ssnx) == win32com.client.CDispatch:
sapg = None
appx = None
conx = None
return
print('Connection is successful\nStarting to process Past Dues...')
unqso = past_df['so'].unique()
unqso.sort()
stime = 0.0
for sox in unqso:
block = past_df.query('so == @sox & action.isnull()')
block = block.sort_values(by = ['crrDlv','vldDlv', 'soLn'], ascending = [True, True, True])
unqc = block['crrDlv'].unique()
try:
for cdlv in unqc:
cblock = block.query('crrDlv == @cdlv')
unqd = cblock['vldDlv'].unique()
unqd.sort()
for vdlv in unqd:
print(f'Opening transaction VA02 in SAP\nSearching for SO {sox}...')
ssnx.findById("wnd[0]/tbar[0]/okcd").text = '/nva02'
ssnx.findById('wnd[0]').sendVKey(0)
ssnx.findById('wnd[0]/usr/ctxtVBAK-VBELN').text = sox
ssnx.findById('wnd[0]/usr/btnBT_SUCH').press()
sleep_run = 0
while ssnx.findById('wnd[0]/sbar').text != '' and sleep_run <= 4:
print(f'Waiting for {stime} seconds and try to open SO {sox} again')
time.sleep(stime)
ssnx.findById('wnd[0]/usr/ctxtVBAK-VBELN').text = sox
ssnx.findById('wnd[0]/usr/btnBT_SUCH').press()
sleep_run += 1
stime = 10
while ssnx.ActiveWindow.Name == 'wnd[1]':
ssnx.findById('wnd[1]/tbar[0]/btn[0]').press()
wgrp = cblock.query('vldDlv == @vdlv')
wgrp = wgrp.sort_values(by = 'soLn')
vdlx = datetime.datetime.strptime(vdlv, '%m/%d/%Y')
print(ssnx.ActiveWindow.text)
# display all the SO lines
ssnx.findById('wnd[0]/tbar[0]/okcd').text = 'uall'
ssnx.findById('wnd[0]').sendVKey(0)
for x, rows in wgrp.iterrows():
noack = wgrp.loc[x, 'no_ack']
mout = wgrp.loc[x, 'move_out']
mfgx = wgrp.loc[x, 'mfgl'].lower()
lnx = wgrp.loc[x, 'soLn']
invc = wgrp.loc[x, 'invChk']
cdlv = wgrp.loc[x, 'crrDlv'].date()
rdlv = wgrp.loc[x, 'rqtDlv'].date()
dlpf = wgrp.loc[x, 'dlrProfile']
fstd = None
hold = None
rjct = None
rwg = int(lnx/10) - 1
0 if rwg < 0 else rwg
ssnx.findById(soLn_grid).verticalScrollbar.position = rwg
lns = int(ssnx.findById(f'{soLn_grid}/txtVBAP-POSNR[0,0]').text)
if rwg > 0 and lns == 10:
rwg = round(rwg/2,0)
ssnx.findById(soLn_grid).verticalScrollbar.position = rwg
lns = int(ssnx.findById(f'{soLn_grid}/txtVBAP-POSNR[0,0]').text)
print(f'Script overshot on first try. Starting off SO Line {lns} found on row {rwg}')
while lns != lnx:
if lns == lnx:
pass # the lines match there is no need to move the row
elif lns < lnx:
rwg += 1
ssnx.findById(soLn_grid).verticalScrollbar.position = rwg
lns = int(ssnx.findById(f'{soLn_grid}/txtVBAP-POSNR[0,0]').text)
elif lns > lnx:
rwg -= 1
ssnx.findById(soLn_grid).verticalScrollbar.position = rwg
lns = int(ssnx.findById(f'{soLn_grid}/txtVBAP-POSNR[0,0]').text)
ssnx.findById(soLn_grid).verticalScrollbar.position = rwg
ssnx.findById(soLn_grid).getAbsoluteRow(rwg).selected = True
past_df.loc[x,'saprow'] = rwg
print(f'SO: {sox} line: {lnx} was found on row: {rwg} with grid line value: {lns}')
ssnx.findById('wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\\01').select()
fstd = ssnx.findById(f'{soLn_grid}/ctxtRV45A-ETDAT[8,0]').text
past_df.loc[x, 'fdate'] = datetime.datetime.strptime(fstd, '%m/%d/%Y')
hold = ssnx.findById(f'{soLn_grid}/chkRV45A-STAT03[16,0]').selected
past_df.loc[x, 'hold'] = hold # boolean value (True or False)
past_df.loc[x, 'rjctr'] = ssnx.findById(f'{soLn_grid}/cmbVBAP-ABGRU[9,0]').text
if past_df.loc[x, 'hold'] == True or past_df.loc[x, 'rjctr'] != '' or vdlx.date() == cdlv:
past_df.loc[x, 'action'] = 'close as cib'
cblock.loc[x, 'action'] = 'close as cib'
elif mfgx == 'x':
past_df.loc[x, 'action'] = 'update delivery and send to mfg'
cblock.loc[x, 'action'] = 'update delivery and send to mfg'
elif mfgx != 'x' and vdlx.date() > cdlv and rdlv < cdlv:
past_df.loc[x, 'action'] = 'close as cib'
cblock.loc[x, 'action'] = 'close as cib'
elif invc == True and vdlx.date() == cdlv:
past_df.loc[x, 'action'] = 'update delivery and send to mfg'
cblock.loc[x, 'action'] = 'update delivery and send to mfg'
elif past_df.loc[x, 'fdate'].date() == vdlx.date():
past_df.loc[x, 'action'] = 'past due process 01'
cblock.loc[x, 'action'] = 'past due process 01'
elif past_df.loc[x, 'fdate'].date() != vdlx.date():
past_df.loc[x, 'action'] = 'past due process 02'
cblock.loc[x, 'action'] = 'past due process 02'
ssnx.findById('wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\\01').select()
dgrp = cblock.query('action == "close as cib"')
if len(dgrp) > 0:
print(f'so {sox} valid: {vdlx} == current: {cdlv}.\nRemoving NoAck and saving changes. Complete as CIB.')
ssnx.findById('wnd[0]/mbar/menu[1]/menu[1]/menu[11]/menu[5]').select()
ssnx.findById('wnd[1]/tbar[0]/btn[7]').press()
ssnx.findById('wnd[0]/tbar[0]/btn[11]').press()
start_time = time.perf_counter()
while ssnx.ActiveWindow.Name == 'wnd[1]':
if ssnx.ActiveWindow.Text == 'Information':
ssnx.findById("wnd[1]/tbar[0]/btn[0]").press()
elif ssnx.ActiveWindow.Text == 'Warning - Defect Code':
ssnx.findById('wnd[1]/tbar[0]/btn[0]').press()
elif ssnx.ActiveWindow.Text == 'Save Incomplete Document':
ssnx.findById("wnd[1]/usr/btnSPOP-VAROPTION1").press()
elif ssnx.ActiveWindow.Text == 'Change Initiator':
ssnx.findById("wnd[1]/usr/btnPB_SC").press()
elif ssnx.ActiveWindow.Text == 'STOP! Dates Changed - Click SAVE or CANCEL':
ssnx.findById("wnd[1]/usr/btnPB_SAVE").press()
elif ssnx.ActiveWindow.Text == 'STOP! Unconfirmed Lines - Click SAVE or CANCEL':
ssnx.findById("wnd[1]/usr/btnPB_SAVE").press()
elif ssnx.ActiveWindow.Text == 'Requirements/Stocks Individual Customer Order':
ssnx.findById("wnd[1]/tbar[0]/btn[0]").press()
else:
q = input('did you save the script for this save pop-up (else)? ')
end_time = time.perf_counter()
stime = round(end_time - start_time, 0)
print(ssnx.findById('wnd[0]/sbar').text)
for x, rows in dgrp.iterrows():
past_df.loc[x, 'action'] = 'so line ready to be completed'
cblock.loc[x, 'action'] = 'so line ready to be completed'
wgrp.loc[x, 'action'] = 'so line ready to be completed'
dgrp = cblock.query('mfgl == "X" & action == "update delivery and send to mfg"')
if len(dgrp) > 0:
print(f'so {sox} has lines marked for MFG. Closing without saving changes and sending to MFG.')
ssnx.findById('wnd[0]/tbar[0]/btn[3]').press()
ssnx.findById("wnd[1]/usr/btnSPOP-OPTION2").press()
dgrp = cblock.query('mfgl != "X" & action == "past due process 01"')
if len(dgrp) > 0:
ssnx.findById('wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\\01').select()
print(f'first date: {fstd} and valid delivery date {vdlv} are the same')
ssnx.findById('wnd[0]/mbar/menu[1]/menu[1]/menu[0]').select()
ssnx.findById('wnd[1]/usr/chkGF_SEL_MVGR3').selected = True
ssnx.findById('wnd[1]/usr/chkGF_SEL_GRKOR').selected = True
ssnx.findById('wnd[1]/usr/ctxtGF_MVGR3').text = 'D'
ssnx.findById('wnd[1]/tbar[0]/btn[7]').press()
while ssnx.ActiveWindow.Name == 'wnd[2]':
ssnx.findById('wnd[2]/tbar[0]/btn[0]').press()
if ssnx.ActiveWindow.Name == 'wnd[0]' and ssnx.ActiveWindow.Text=='SC Standard Order: Availability Control':
ssnx.findById("wnd[0]/tbar[1]/btn[18]").press()
while ssnx.ActiveWindow.Name == 'wnd[2]':
ssnx.findById('wnd[2]/tbar[0]/btn[0]').press()
if ssnx.ActiveWindow.Name == 'wnd[0]' and ssnx.ActiveWindow.Text=='SC Standard Order: Availability Control':
ssnx.findById("wnd[0]/tbar[1]/btn[18]").press()
while ssnx.ActiveWindow.Name == 'wnd[2]':
ssnx.findById('wnd[2]/tbar[0]/btn[0]').press()
ssnx.findById('wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\\02').select()
while ssnx.ActiveWindow.Name == 'wnd[1]':
ssnx.findById("wnd[1]/tbar[0]/btn[0]").press()
ssnx.findById('wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\\05').select()
while ssnx.ActiveWindow.Name == 'wnd[1]':
ssnx.findById("wnd[1]/tbar[0]/btn[0]").press()
ssnx.findById('wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\\06').select()
while ssnx.ActiveWindow.Name == 'wnd[1]':
ssnx.findById("wnd[1]/tbar[0]/btn[0]").press()
ssnx.findById('wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\\05').select()
while ssnx.ActiveWindow.Name == 'wnd[1]':
ssnx.findById("wnd[1]/tbar[0]/btn[0]").press()
ssnx.findById('wnd[0]/usr/tabsTAXI_TABSTRIP_OVERVIEW/tabpT\\06').select()
while ssnx.ActiveWindow.Name == 'wnd[1]':
ssnx.findById("wnd[1]/tbar[0]/btn[0]").press()
save_changes = 0
for x,rows in dgrp.iterrows():
sdlx = ssnx.findById(f'{ship_grid}/ctxtRV45A-GRETD[3,0]').text
sdlv = datetime.datetime.strptime(sdlx,'%m/%d/%Y')
if sdlv == vdlx:
past_df.loc[x, 'fst_try'] = 'yes'
wgrp.loc[x, 'fst_try'] = 'yes'
dgrp.loc[x, 'fst_try'] = 'yes'
else:
past_df.loc[x, 'fst_try'] = 'no'
wgrp.loc[x, 'fst_try'] = 'no'
dgrp.loc[x, 'fst_try'] = 'no'
save_changes = len(dgrp.query('fst_try == "yes"'))
if save_changes == len(dgrp):
print(f'so {sox} delivery date(s) have been updated from {cdlv} to {vdlx}')
ssnx.findById(ship_grid).verticalScrollbar.position = 0
for x, rows in dgrp.iterrows():
rwg = past_df.loc[x, 'saprow']
ssnx.findById(ship_grid).verticalScrollbar.position = rwg
ssnx.findById(ship_grid).getAbsoluteRow(rwg).selected = True
ssnx.findById('wnd[0]/mbar/menu[1]/menu[1]/menu[11]/menu[5]').select()
ssnx.findById('wnd[1]/tbar[0]/btn[7]').press()
start_time = time.perf_counter()
ssnx.findById('wnd[0]/tbar[0]/btn[11]').press()
while ssnx.ActiveWindow.Name == 'wnd[1]':
if ssnx.ActiveWindow.Text == 'Information':
ssnx.findById("wnd[1]/tbar[0]/btn[0]").press()
elif ssnx.ActiveWindow.Text == 'Warning - Defect Code':
ssnx.findById('wnd[1]/tbar[0]/btn[0]').press()
elif ssnx.ActiveWindow.Text == 'Save Incomplete Document':
ssnx.findById("wnd[1]/usr/btnSPOP-VAROPTION1").press()
elif ssnx.ActiveWindow.Text == 'Change Initiator':
ssnx.findById("wnd[1]/usr/btnPB_SC").press()
elif ssnx.ActiveWindow.Text == 'STOP! Dates Changed - Click SAVE or CANCEL':
ssnx.findById("wnd[1]/usr/btnPB_SAVE").press()
elif ssnx.ActiveWindow.Text == 'STOP! Unconfirmed Lines - Click SAVE or CANCEL':
ssnx.findById("wnd[1]/usr/btnPB_SAVE").press()
elif ssnx.ActiveWindow.Text == 'Requirements/Stocks Individual Customer Order':
ssnx.findById("wnd[1]/tbar[0]/btn[0]").press()
else:
q = input('did you save the script for this save pop-up (else)? ')
end_time = time.perf_counter()
stime = round(end_time - start_time, 0)
print(ssnx.findById('wnd[0]/sbar').text)
for x, rows in dgrp.iterrows():
past_df.loc[x, 'action'] = 'so line ready to be completed'
cblock.loc[x, 'action'] = 'so line ready to be completed'
wgrp.loc[x, 'action'] = 'so line ready to be completed'
elif save_changes > 0 and save_changes < len(dgrp):
print(f'so {sox} will require a second pass in order to update\nClosing {sox} without saving changes')
ssnx.findById('wnd[0]/tbar[0]/btn[3]').press()
ssnx.findById("wnd[1]/usr/btnSPOP-OPTION2").press()
for x, rows in dgrp.iterrows():
past_df.loc[x, 'action'] = 'run 2nd time'
cblock.loc[x, 'action'] = 'run 2nd time'
wgrp.loc[x, 'action'] = 'run 2nd time'
else:
print(f'so {sox} will be updated and sent to mfg for review')
ssnx.findById('wnd[0]/tbar[0]/btn[3]').press()
ssnx.findById("wnd[1]/usr/btnSPOP-OPTION2").press()
for x, rows in dgrp.iterrows():
past_df.loc[x, 'action'] = 'update delivery and send to mfg'
cblock.loc[x, 'action'] = 'update delivery and send to mfg'
wgrp.loc[x, 'action'] = 'update delivery and send to mfg'
# had to cut part of the code from this point due to num of characters permitted
print('Moving on to the next so. first pass')
except:
print(f'Error occurred on SO {sox}. Moving on to the next SO')
except:
print(f'Script broke on SO {sox} Line {lnx} please review')
print('Displaying system error:\n', sys.exc_info())
finally:
# terminate connection
ssnx = None
conx = None
appx = None
sapg = None
print('Processing past due SO lines is done\nTerminating connection to SAP')