I am trying to use Python for SAP Scripting, specifically to select a row in a GuiGridView object. It works just fine in VB Script, but in Python I get an exception: -2147352562, 'Invalid number of parameters.', which doesn't make sense to me since I'm using the same number of parameters as for VB Script.
I am trying to get away from VB Script since it doesn't have proper error handling.
Here is the documentation (https://help.sap.com/doc/9215986e54174174854b0af6bb14305a/760.01/en-US/sap_gui_scripting_api_761.pdf ), but even with that I haven't been able to resolve this:
Page 128
SelectedRows (Read-write)
Public Property SelectedRows As String
The string is a comma separated list of row index numbers or index ranges, such as “1,2,4-8,10”.Setting this property to an invalid string or a string containing invalid row indices will raise an exception.
The following VB Script code selects the GuiGridRow as expected, but when I attempt to convert that to Python it won't work.
If Not IsObject(application) Then
Set SapGuiAuto = GetObject("SAPGUI")
Set application = SapGuiAuto.GetScriptingEngine
End If
If Not IsObject(connection) Then
Set connection = application.Children(0)
End If
If Not IsObject(session) Then
Set session = connection.Children(0)
End If
If IsObject(WScript) Then
WScript.ConnectObject session, "on"
WScript.ConnectObject application, "on"
End If
Set GridView = session.findById("wnd[0]/usr/cntlGRID1/shellcont/shell")
GridView.SelectedRows = 1
Here is my Python 3.9 attempt using Jupyter Notebook and the results:
+*In[1]:*+
import win32com.client
+*In[2]:*+
SapGuiAuto = win32com.client.GetObject('SAPGUI')
application = SapGuiAuto.GetScriptingEngine
connection = application.Children(0)
session = connection.Children(0)
type(session)
+*Out[2]:*+
----win32com.client.CDispatch----
+*In[3]:*+
grid_view = session.findById('wnd[0]/usr/cntlGRID1/shellcont/shell')
print(grid_view)
+*Out[3]:*+
<COMObject <unknown>>
+*In[4]:*+
# to show that grid_view is a valid GuiGridView object
grid_view.RowCount
+*Out[4]:*+
----2----
+*In[5]:*+
# reading the SelectedRows works
grid_view.SelectedRows
+*Out[5]:*+
----'1'----
+*In[6]:*+
# setting SelectedRows as number fails
# note: I had manually unselected the row in SAP before running the rest of the code
grid_view.SelectedRows = 1
+*Out[6]:*+
---------------------------------------------------------------------------
com_error Traceback (most recent call last)
~\AppData\Local\Temp\20/ipykernel_21344/1273355717.py in <module>
----> 1 grid_view.SelectedRows = 1
E:\Anaconda\Lib\site-packages\win32com\client\dynamic.py in __setattr__(self, attr, value)
541 entry = self._olerepr_.propMap[attr]
542 invoke_type = _GetDescInvokeType(entry, pythoncom.INVOKE_PROPERTYPUT)
--> 543 self._oleobj_.Invoke(entry.dispid, 0, invoke_type, 0, value)
544 return
545 # Check the specific "put" map.
com_error: (-2147352562, 'Invalid number of parameters.', None, None)
----
+*In[7]:*+
# setting SelectedRows as string fails
grid_view.SelectedRows = '1'
+*Out[7]:*+
---------------------------------------------------------------------------
com_error Traceback (most recent call last)
~\AppData\Local\Temp\20/ipykernel_21344/1222153478.py in <module>
----> 1 grid_view.SelectedRows = '1'
E:\Anaconda\Lib\site-packages\win32com\client\dynamic.py in __setattr__(self, attr, value)
541 entry = self._olerepr_.propMap[attr]
542 invoke_type = _GetDescInvokeType(entry, pythoncom.INVOKE_PROPERTYPUT)
--> 543 self._oleobj_.Invoke(entry.dispid, 0, invoke_type, 0, value)
544 return
545 # Check the specific "put" map.
com_error: (-2147352562, 'Invalid number of parameters.', None, None)
----
+*In[8]:*+
# setting SelectedRows as string with multiple rows fails
grid_view.SelectedRows = '0,1'
----
+*Out[8]:*+
---------------------------------------------------------------------------
com_error Traceback (most recent call last)
~\AppData\Local\Temp\20/ipykernel_21344/3316141255.py in <module>
----> 1 grid_view.SelectedRows = '0,1'
E:\Anaconda\Lib\site-packages\win32com\client\dynamic.py in __setattr__(self, attr, value)
541 entry = self._olerepr_.propMap[attr]
542 invoke_type = _GetDescInvokeType(entry, pythoncom.INVOKE_PROPERTYPUT)
--> 543 self._oleobj_.Invoke(entry.dispid, 0, invoke_type, 0, value)
544 return
545 # Check the specific "put" map.
com_error: (-2147352562, 'Invalid number of parameters.', None, None)
----
+*In[9]:*+
# setting SelectedRows as string with multiple rows in a method-type notation fails
grid_view.SelectedRows('0,1')
----
+*Out[9]:*+
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
~\AppData\Local\Temp\20/ipykernel_21344/2186236324.py in <module>
----> 1 grid_view.SelectedRows('0,1')
TypeError: 'str' object is not callable
----
Ok, after digging around a lot more, patching to the latest version of win32com worked:
https://github.com/mhammond/pywin32/tree/main/com/win32com
Once I did that all of the following worked to select rows:
grid_view.SelectedRows = 1
grid_view.SelectedRows = '1'
grid_view.SelectedRows = '0,1'
grid_view.SelectedRows = '0-1'
The following did not work (type error), which makes sense since it would imply tuple packing/unpacking:
grid_view.SelectedRows = 0,1
This results in unexpected rows being selected since it is performing subtraction rather than indicating a range of rows:
grid_view.SelectedRows = 0-1
I hope someone can help me. I've been stuck with this error for a while. I have two .py files that I am importing in a jupyter notebook. When running the last cell (see code below) I get a Traceback error I can'f fix.
I think there is some error in my ch_data_prep.py file related to variable df_ch not correctly passed between files. Is this possible? Any suggestion on how to solve this problem?
Thanks!
ch_data_prep.py
def seg_data(self):
seg_startdate = input('Enter start date (yyyy-mm-dd): ')
seg_finishdate = input('Enter end date (yyyy-mm-dd): ')
df_ch_seg = df_ch[(df_ch['event_datetime'] > seg_startdate)
& (df_ch['event_datetime'] < seg_finishdate)
]
return df_ch_seg
df_ch_seg = seg_data(df_ch)
ch_db.py
def get_data():
# Some omitted code here to connect to database and get data...
df_ch = pd.DataFrame(result)
return df_ch
df_ch = get_data()
Jupyter Notebook data_analysis.ipynb
In[1]: import ch_db
df_ch = ch_db.get_data()
In[2]: import ch_data_prep
When I run cell 2, I get this error
--------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-3-fbe2d4fceba6> in <module>
----> 1 import ch_data_prep
~/clickstream/ch_data_prep.py in <module>
34 return df_ch_seg
35
---> 36 df_ch_seg = seg_data()
TypeError: seg_data() missing 1 required positional argument: 'df_ch'
The code I'm using has been working occasionally, but I need something to work all the time. The site I'm scraping sometimes has the info and other times omits it, which is why I get the error after running the program. Since the site doesn't always post a time for certain events, 'event_time' obviously is not defined.
The problem I'm facing is that sometimes the with suppress(Exception): works and sometimes it doesn't. What can I add to skip over the the event_time when the site doesn't specify a time, and have the program continue to scrape the rest of the site?
event_name = s.select_one('.eventname').get_text(strip=True)
event_day = s.select_one('.date').text.strip()
event_month = s.select_one('.month').text.strip()
with suppress(Exception):
event_time = s.select_one('.time').text.strip()
event_info = s.select_one('.event-header').text.strip()
Error:
NameError
Traceback (most recent call last)
<ipython-input-49-45cf21eb3177> in <module>
22 print('Dia: ' + event_day)
23 print('Mes: ' + event_month)
---> 24 print('Hora: ' + event_time)
25 print('Descripción: ' + event_info)
26 print('-' * 80)
NameError: name 'event_time' is not defined
Instead of supressing the exception
with suppress(Exception):
event_time = s.select_one('.time').text.strip()
catch it and add a default
try:
event_time = s.select_con('.time').text.strip()
except Exception:
event_time = ''
Catching a generic exception can hide other errors. Its best to figure out which exceptions can happen and catch those.
You can use a try-except statement to ensure that the exception is caught every time.
try:
event_time = s.select_con('.time').text.strip()
except NameError:
event_time = ...
I'm trying to port some working VBS code into Python, to analyze a collection of Word files. I was hoping that the comtypes would allow me to reuse most of my code, but I get an error when a Word instance opens a file:
ValueError: NULL COM pointer access
In [2]: from comtypes.client import CreateObject
In [3]: objWord = CreateObject("Word.Application")
In [4]: objWord.Visible = False
In [5]: objDoc = objWord.Documents.Open('my_file.docx')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-5-c1e34bdd2b13> in <module>
----> 1 objDoc = objWord.Documents.Open('my_file.docx')
c:\program files\python37\lib\site-packages\comtypes\_meta.py in _wrap_coclass(self)
11 itf = self._com_interfaces_[0]
12 punk = cast(self, POINTER(itf))
---> 13 result = punk.QueryInterface(itf)
14 result.__dict__["__clsid"] = str(self._reg_clsid_)
15 return result
c:\program files\python37\lib\site-packages\comtypes\__init__.py in QueryInterface(self, interface, iid)
1156 if iid is None:
1157 iid = interface._iid_
-> 1158 self.__com_QueryInterface(byref(iid), byref(p))
1159 clsid = self.__dict__.get('__clsid')
1160 if clsid is not None:
ValueError: NULL COM pointer access
I would expect to get a document object that I can then read:
nbpages = objDoc.Range.Information(4)
Seems like I needed to provide the full, absolute path to the file. Maybe the Python working folder isn't passed on to the COM object.
I can't figure out why traceback.format_exc() is returning "None" in the following example:
#!/usr/bin/env python
import sys
import traceback
def my_excepthook(type, value, tb):
print type.__name__
print value
# the problem: why does this return "None"?
print traceback.format_exc(tb) # see http://docs.python.org/library/traceback.html#traceback.format_exc
sys.excepthook = my_excepthook # see http://docs.python.org/library/sys.html#sys.excepthook
# some code to generate a naturalistic exception
a = "text"
b = 5
error = a + b
Using Python 2.7.1, I get the following output:
TypeError
cannot concatenate 'str' and 'int' objects
None
Instead of "None" on the 3rd line, I'd expect to get what happens when I comment out the sys.excepthook line:
Traceback (most recent call last):
File "log-test.py", line 17, in <module>
error = a+b
Try to change like this in my_excepthook:
print "".join(traceback.format_exception(type, value, tb))