I am trying to automate Microstation using python and win32com but I get the following error trying to resend an object created through the COM interface. Can anyone help me troubleshoot?
import win32com.client
MS = win32com.client.Dispatch("MicroStationDGN.Application")
MS.Visible = 1
DF = MS.OpenDesignFile("C:\\mydgn.dgn", False)
print(DF.Models.Count)
startPoint = MS.Point3dFromXYZ(2.0,2.0,0.0)
endPoint = MS.Point3dFromXYZ(4.0,4.0,0.0)
line = MS.CreateLineElement2(None, startPoint, endPoint)
print(line)
MS.ActiveModelReference.AddElement(line)
line.redraw()
on the AddElement line i get the following error:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-54f93cd6e4bc> in <module>()
16 line = MS.CreateLineElement2(None, startPoint, endPoint)
17 print(line)
---> 18 MS.ActiveModelReference.AddElement(line)
19 line.redraw()
20
C:\Users\user\AppData\Local\Temp\gen_py\3.6\CF9F97BF-39F2-4B8E-835C-8BE9E99DAF5Bx0x8x0.py in AddElement(self, Element)
16408
16409 def AddElement(self, Element=defaultNamedNotOptArg):
> 16410 return self._oleobj_.InvokeTypes(1610743813, LCID, 1, (24, 0), ((9, 1),),Element
16411 )
16412
TypeError: The Python instance can not be converted to a COM object
but the print gives me a valid com object...
(<win32com.gen_py.Bentley MicroStation DGN 8.9 Object
Library._LineElement instance at 0x119452224>, com_struct(X=2.0,
Y=2.0, Z=0.0), com_struct(X=4.0, Y=4.0, Z=0.0))
The equivalent in ExcelVBA would be the following assuming Microstation DGN Library is loaded as a reference module.
Sub MSFromXlReference()
Dim MS As MicroStationDGN.Application
Dim DesignFile As DesignFile
Dim Line As LineElement
Dim startPoint As Point3d
Dim endPoint As Point3d
Set MS = New MicroStationDGN.Application
MS.Visible = 1
Set DesignFile =
MS.OpenDesignFile("C:\\mydgn.dgn", False)
startPoint = MS.Point3dFromXYZ(2#, 2#, 0#)
endPoint = MS.Point3dFromXYZ(4#, 4#, 0#)
Set Line = MS.CreateLineElement2(Nothing, startPoint, endPoint)
MS.ActiveModelReference.AddElement Line
Line.redraw
End Sub
Related
import pybullet as p
import pybullet_data
import time
obstacles_coor=[[-5,10,2.5],[2,10,2.5],[10,10,2.5],[0,5,2.5],[-10,-5,2.5]]
physicsClient = p.connect(p.GUI)
p.setAdditionalSearchPath(pybullet_data.getDataPath())
p.loadURDF('plane.urdf', [0,0,0])
p.setGravity(0,0,-10)
for obs in obstacles_coor:
p.loadURDF("cube.urdf",obs,globalScaling=0.5)
p.setAdditionalSearchPath(pybullet_data.getDataPath())
obstacles_coor.pop()
# obs = p.loadURDF("cube.urdf", globalScaling=0.5)
cube=p.loadURDF("cube.urdf", [0,0,1])
def contactPoints():
#obs is a list>
contacts = p.getContactPoints(bodyA=cube, bodyB=obs)
for contact in contacts:
link_index = contact[2]
if link_index >= 2:
# p.removeBody(obstacles_coor[0])
del(obstacles_coor[0])
for i in range(10000):
p.stepSimulation()
contactPoints()
time.sleep(1./240.)
the error jumps at the line:
contacts = p.getContactPoints(bodyA=cube, bodyB=obs)
With this error log:
Exception has occurred: TypeError
an integer is required (got type list)
File "C:\Users\AisyahJeff\niche_evo_single_species\old_model\test.py", line 58, in contactPoints
contacts = p.getContactPoints(bodyA=cube, bodyB=obs)
File "C:\Users\AisyahJeff\niche_evo_single_species\old_model\test.py", line 69, in <module>
contactPoints()
I am thinking it is python type of error instead of pybullet.
For anyone else that have this problem, my friend gave me a solution:
import pybullet as p
import pybullet_data
import time
obstacles_coor=[[-5,10,2.5],[2,10,2.5],[10,10,2.5],[0,5,2.5],[-10,-5,2.5]]
physicsClient = p.connect(p.GUI)
p.setAdditionalSearchPath(pybullet_data.getDataPath())
p.loadURDF('plane.urdf', [0,0,0])
cube=p.loadURDF("cube.urdf", [0,0,1])
obstacles_list=[]
for obs in obstacles_coor:
obstacles_list.append(p.loadURDF("cube.urdf",obs,globalScaling=0.5))
p.setGravity(0,0,-10)
def contactPoints():
#obs is a list>
for obs_idx in obstacles_list:
contacts = p.getContactPoints(bodyA=cube, bodyB=obs_idx)
for contact in contacts:
link_index = contact[2]
if link_index >= 2:
#del(obstacles_coor.pop(0))
p.removeBody(obstacles_coor.pop(0))
for i in range(10000):
p.stepSimulation()
contactPoints()
time.sleep(1./240.)
obstacles_coor or obs in this context is a list, not an int. Therefore it is not suitable for the p.getContactPoints argument. So, recognize it as index 'idx' in the argument so it can be an int.
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 want to add constraints between the planes of the base-coordinate systems of components in an Inventor assmbly using the Inventor API with Python. The placement of the components works. My issue is, that i cannot access WorkPlanes in the Definition of my individual Occurrences.
My Code looks like this:
import win32com.client as win32
project_folder = "C:\\Users\\User_1\\210608_project\\"
#initialization
inv = win32.gencache.EnsureDispatch('Inventor.Application')
inv.Visible = True
#Open a new assembly
inv.Documents.Add(win32.constants.kAssemblyDocumentObject, "", True)
invActDoc = inv.ActiveDocument
invAssDoc = win32.CastTo(invActDoc, 'AssemblyDocument')
#Create the transient matrices
oTG = inv.TransientGeometry
oMatrix = oTG.CreateMatrix()
#Add component to assembly
invAssDocDef = invAssDoc.ComponentDefinition
invAssOcc = invAssDocDef.Occurrences
occ1 = invAssOcc.Add(project_folder + 'generic_part_1.ipt', oMatrix)
occ2 = invAssOcc.Add(project_folder + 'generic_part_2.ipt', oMatrix)
#create constraints
#get the Planes of the Base-Coordinate-System of Part 1
wp_YZ_1 = occ1.Definition.WorkPlanes.Item(1)
wp_XZ_1 = occ1.Definition.WorkPlanes.Item(2)
wp_XY_1 = occ1.Definition.WorkPlanes.Item(3)
#get the Planes of the Base-Coordinate-System of Part 2
wp_YZ_2 = occ2.Definition.WorkPlanes.Item(1)
wp_XZ_2 = occ2.Definition.WorkPlanes.Item(2)
wp_XY_2 = occ2.Definition.WorkPlanes.Item(3)
#Add the constraints
AssCons = invAssDoc.ComponentDefinition.Constraints
AssCons.AddFlushConstraint(wp_YZ_1, wp_YZ_2, 0)
AssCons.AddFlushConstraint(wp_XZ_1, wp_XZ_2, 0)
AssCons.AddFlushConstraint(wp_XY_1, wp_XY_2, 0)
It breaks when i try to get the WorkPlanes:
Traceback (most recent call last):
File "C:/Users/User1/210608_projekt/how_to_constrain_components_in_assemblies.py", line 27, in <module>
wp1 = occ1.Definition.WorkPlanes.Item(1)
File "C:\Program Files\Python37\lib\site-packages\win32com\client\__init__.py", line 473, in __getattr__
raise AttributeError("'%s' object has no attribute '%s'" % (repr(self), attr))
AttributeError: '<win32com.gen_py.Autodesk Inventor Object Library.ComponentDefinition instance at 0x2748634277928>' object has no attribute 'WorkPlanes'
This happens to everything that I tried, that is inside of Occurrence.Item(i).Definition.
If i open the same assembly in a VBA script, everything is where it should be. Am I missing something about working with occurrences using the API?
You need to create WorkPlaneProxy object of the WorkPlane. It means representation of workplane defined in part in context of specific occurrence in the assembly
Here is part of VB.NET code
'Define variables for workplane proxy
Dim wp_YZ_1_proxy As WorkPlaneProxy
Dim wp_YZ_2_proxy As WorkPlaneProxy
'You need to pass result variable as argument
' ByRef in VB.NET, out in C#
'I don't know how to do in Python
occ1.CreateGeometryProxy(wp_YZ_1, wp_YZ_1_proxy)
occ2.CreateGeometryProxy(wp_YZ_2, wp_YZ_2_proxy)
Dim AssCons As AssemblyConstraints = asm.Constraints
'Use this proxies for constraint creation
AssCons.AddFlushConstraint(wp_YZ_1_proxy, wp_YZ_2_proxy, 0)
So this is how the solution/replacement of the last 3 blocks looks like:
#cast the definitions to PartComponentDefinition
occ1_def = win32.CastTo(occ1.Definition, 'PartComponentDefinition')
occ2_def = win32.CastTo(occ2.Definition, 'PartComponentDefinition')
#create constraints
#get the Planes of the Base-Coordinate-System of Part 1
wp_YZ_1 = occ1_def.WorkPlanes.Item(1)
wp_XZ_1 = occ1_def.WorkPlanes.Item(2)
wp_XY_1 = occ1_def.WorkPlanes.Item(3)
#create Geometry-Proxys for Workplanes of Comp1
wp_YZ_1_proxy = occ1.CreateGeometryProxy(wp_YZ_1)
wp_XZ_1_proxy = occ1.CreateGeometryProxy(wp_XZ_1)
wp_XY_1_proxy = occ1.CreateGeometryProxy(wp_XY_1)
#get the Planes of the Base-Coordinate-System of Part 2
wp_YZ_2 = occ2_def.WorkPlanes.Item(1)
wp_XZ_2 = occ2_def.WorkPlanes.Item(2)
wp_XY_2 = occ2_def.WorkPlanes.Item(3)
#create Geometry-Proxys for Workplanes of Comp2
wp_YZ_2_proxy = occ2.CreateGeometryProxy(wp_YZ_2)
wp_XZ_2_proxy = occ2.CreateGeometryProxy(wp_XZ_2)
wp_XY_2_proxy = occ2.CreateGeometryProxy(wp_XY_2)
#Add the constraints
AssCons = invAssDoc.ComponentDefinition.Constraints
AssCons.AddFlushConstraint(wp_YZ_1_proxy, wp_YZ_2_proxy, 0)
AssCons.AddFlushConstraint(wp_XZ_1_proxy, wp_XZ_2_proxy, 0)
AssCons.AddFlushConstraint(wp_XY_1_proxy, wp_XY_2_proxy, 0)
I am trying to make the code cleaner and better manageable and i wanted to start with reading a cisco file. However when i try to put it in a function, it is not able to give me the outputs. The same works perfectly out of a function
Working model
parse = CiscoConfParse("C:\\python\\mydata\\TestConfigFile.txt")
TCPSrv = parse.find_objects("service\stcp\sdestination\seq")
UDPSrv = parse.find_objects("service\sudp\sdestination\seq")
ObjectNetwork = parse.find_objects("^object\snetwork\s")
ObjectGroupSrv = parse.find_objects("^object-group\sservice")
ObjectGroupNetwork = parse.find_objects("^object-group\snetwork\s")
This creates a list for all the above like the one below
TCPSrv = [<IOSCfgLine # 83 ' service tcp destination eq https' (parent is # 82)>,<IOSCfgLine # 97 ' service tcp destination eq www '(parent is # 102)>]
But when i put this into a function, it does not work. This is the first time i am trying out to use functions, and I know that i am doing something wrong.
This is my code for Functions
def cisco(filename):
parse = CiscoConfParse(filename)
TCPSrv = parse.find_objects("service\stcp\sdestination\seq")
UDPSrv = parse.find_objects("service\sudp\sdestination\seq")
ObjectNetwork = parse.find_objects("^object\snetwork\s")
ObjectGroupSrv = parse.find_objects("^object-group\sservice")
ObjectGroupNetwork = parse.find_objects("^object-group\snetwork\s")
return TCPSrv, UDPSrv, ObjectNetwork, ObjectGroupSrv, ObjectGroupNetwork
file = C:\\python\\mydata\\TestConfigFile.txt
cisco(file)
This does not give any output.
>>> TCPSrc
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'TCPSrc' is not defined
I have tried putting it like this below also
cisco("C:\\python\\mydata\\TestConfigFile.txt")
Can someone kindly assist what I am doing wrong.
This does not give any output
>>> TCPSrc
Traceback (most recent call last):
File "", line 1, in
NameError: name 'TCPSrc' is not defined
You have not assigned the return values to anything. When you call cisco(), you need to assign the return values to something... please use:
from ciscoconfparse import CiscoConfParse
def cisco(filename):
parse = CiscoConfParse(filename)
TCPSrv = parse.find_objects("service\stcp\sdestination\seq")
UDPSrv = parse.find_objects("service\sudp\sdestination\seq")
ObjectNetwork = parse.find_objects("^object\snetwork\s")
ObjectGroupSrv = parse.find_objects("^object-group\sservice")
ObjectGroupNetwork = parse.find_objects("^object-group\snetwork\s")
return TCPSrv, UDPSrv, ObjectNetwork, ObjectGroupSrv, ObjectGroupNetwork
values = cisco("C:\\python\\mydata\\TestConfigFile.txt")
TCPsrv = values[0]
UDPsrv = values[1]
# ... etc unpack the remaining values as illustrated above
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.