Python pywin32 error passing an optional string via a VBA click - python

I am working with legacy access code and am using pywin32 to automate batch processing.
This python code:
import win32com.client as win32
access = win32.Dispatch('Access.Application')
db = access.OpenCurrentDatabase(r'C:\test\PN.mdb')
access.Forms('frm_PN_Startup').cmdScenarioExport_Click()
sucessfully executes this Access VBA sub
Public Sub cmdScenarioExport_Click()
Export_Scenario_To_ScenarioDB
End Sub
I would like to pass an optional text string to fill the Access InputBox that opens in Export_Scenario_To_ScenarioDB. However, when I try
Python
import win32com.client as win32
access = win32.Dispatch('Access.Application')
db = access.OpenCurrentDatabase(r'C:\test\PN.mdb')
access.Forms('frm_PN_Startup').cmdScenarioExport_Click("hello")
Vba
Public Sub cmdScenarioExport_Click(Optional strTest As String = "")
Export_Scenario_To_ScenarioDB (strTest)
End Sub
I get the following error:
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "C:\Users\RS\miniconda3\envs\PN_PY\lib\site-packages\win32com\client\dynamic.py", line 197, in __call__
return self._get_good_object_(self._oleobj_.Invoke(*allArgs),self._olerepr_.defaultDispatchName,None)
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2146788252), None)
win32api tells me that the error is
win32api.FormatMessage(-2147352567)
'Exception occurred.\r\n'
After numerous hours spinning my wheels, I'm asking for any ideas to make this work. Thank you! This is my first foray into VBA.

Related

com_error when saving emails in windows outlook with python

I'm using python to save emails in a specified folder and complete the following:
check if the email is unread
save the email to target folder
mark the message as read
tell me how many messages were archived and the location
the code:
from win32com.client import Dispatch
import os
outlook = Dispatch('outlook.application').GetNamespace("MAPI")
root = outlook.Folders[0].Folders[27]
targetPath = os.path.expanduser(r'\\path\to\target\folder')
messages = root.Items
count = 0
for msg in messages:
if msg.UnRead:
msg.SaveAs(os.path.join(targetPath))
msg.UnRead = False
count +=1
print(str(count)+' emails archived to: '+targetPath)
I end up with this error i've never seen before, and I haven't had any luck with the google machine... so I come to stackoverflow and wake you from your slumber.
Traceback (most recent call last):
File "C:\Users\e582324\Documents\Python Scripts\untitled6.py", line 18, in <module>
msg.SaveAs(os.path.join(targetPath))
File "<COMObject <unknown>>", line 3, in SaveAs
com_error: (-2147352567, 'Exception occurred.', (4096, 'Microsoft Outlook', 'The operation failed.', None, 0, -2147024829), None)
Any idea whats causing this? I have a similar script that saves just attachments and it works fine. My target folder is on a network shared drive for both scripts and it hasn't caused an issue until now. Only real difference is the use of .SaveAs() instead of .SaveAsFile()
You need to specify the file name as well as its extension. passing the path is not enough sometimes, especially when you don't specify the format (see the second parameter). Note, an Outlook folder may contain different kind of items - mail items, appointments, documents, notes and etc. For example, here is a sample:
Item.SaveAs Environ("HOMEPATH") & "\My Documents\" & strname & ".txt", olTXT
Also I've noticed that you are iterating over all items in the folder:
for msg in messages:
if msg.UnRead:
Instead, you need to use the Find/FindNext or Restrict methods of the Items class. So, you get only items that correspond to your conditions and iterate only over them. Read more about these methods in the following articles:
How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
How To: Use Restrict method to retrieve Outlook mail items from a folder

pywintypes.error: (1400, 'GetMenu', 'Invalid window handle.')

I am using python API to remote control software called PLAXIS (Geotechnical software). And there are certain modules in PLAXIS that can be used by using the editor(its editor is SciTE) of this software. now, I am trying to run a code which I attached the part that I get an error on here. this code is supposed to get the results of a couple of simulations and give those to the user in an excel file. I debugged a couple of errors, but, I can not understand this error. I will appreciate your help if you could help me to fix this error.
`
Function:Close current file and open a new file
def Closeandopen(Number,path,subpath):
assert type(Number)==str
assert type(path)==str
assert type(subpath)==str
Menuid=win32gui.GetMenu(outwindow)
SubMenuid=win32gui.GetSubMenu(Menuid,1)
Openid=win32gui.GetMenuItemID(SubMenuid,0)
CloseAllid=win32gui.GetMenuItemID(SubMenuid,2)
if CloseAllid==4:
win32gui.PostMessage(outwindow, win32con.WM_COMMAND, CloseAllid, 0)
time.sleep(0.5)
Quickselect=win32gui.FindWindow('TfrmStartup',None)
win32api.PostMessage(Quickselect, win32con.WM_KEYDOWN,27, 0)
win32api.PostMessage(Quickselect, win32con.WM_KEYUP,27, 0)
time.sleep(0.5)
Openbox=win32gui.FindWindow('#32770','打开')
if Openbox==0:
Menuid=win32gui.GetMenu(outwindow)
SubMenuid=win32gui.GetSubMenu(Menuid,0)
Openid=win32gui.GetMenuItemID(SubMenuid,0)
win32gui.PostMessage(outwindow, win32con.WM_COMMAND, Openid, 0)
time.sleep(0.5)
Openbox=win32gui.FindWindow('#32770',None)
ComboBoxEx32=win32gui.FindWindowEx(Openbox,0,"ComboBoxEx32", None)
ComboBox=win32gui.FindWindowEx(ComboBoxEx32,0,"ComboBox", None)
Filenamebox = win32gui.FindWindowEx(ComboBox,0,"Edit", None)
Filename=path+subpath+subpath+'-'+Number+'.p2dx'
print(Filename)
win32api.SendMessage(Filenamebox, win32con.WM_SETTEXT, 0, os.path.abspath(Filename))
win32api.PostMessage(Filenamebox, win32con.WM_KEYDOWN,13, 0)
win32api.PostMessage(Filenamebox, win32con.WM_KEYUP,13, 0)`
the error is:
`>C:\ProgramData\Bentley\Geotechnical\PLAXIS Python Distribution V1 Update 1\python\pythonw.exe -u "sand_excavation_output.py"
Traceback (most recent call last):
File "sand_excavation_output.py", line 135, in <module>
output('D:\PLAXIS\Strut-Sand-AU14-Simulations','\COV=0.1-theta=1m\COV=0.1-theta=1m-001.p2dxdat',1,5)
File "sand_excavation_output.py", line 67, in output
Closeandopen(Number,path,subpath)
File "sand_excavation_output.py", line 26, in Closeandopen
Menuid=win32gui.GetMenu(outwindow)
pywintypes.error: (1400, 'GetMenu', 'Invalid window handle.')
>Exit code: 1`

Extract all confirmed transactions from a bitcoin block using python

I want to extract all confirmed transactions from the bitcoin blockchain. I know there are repos out there (e.g. https://github.com/znort987/blockparser) but I want to write something myself for my better understanding.
I am have tried the following code after having downloaded far more than 42 blocks and while running bitcoind (minimal example):
from bitcoin.rpc import RawProxy
proxy = RawProxy()
blockheight=42
block = proxy.getblock(proxy.getblockhash(blockheight))
tx_list = block['tx']
for tx_id in tx_list:
raw_tx = proxy.getrawtransaction(tx_id)
This yields the following error:
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
File "/home/donkeykong/.local/lib/python3.7/site-packages/bitcoin/rpc.py", line 315, in <lambda>
f = lambda *args: self._call(name, *args)
File "/home/donkeykong/.local/lib/python3.7/site-packages/bitcoin/rpc.py", line 239, in _call
'message': err.get('message', 'error message not specified')})
bitcoin.rpc.InvalidAddressOrKeyError: {'code': -5, 'message': 'No such mempool transaction. Use -txindex or provide a block hash to enable blockchain transaction queries. Use gettransaction for wallet transactions.'}
Could anyone elucidate what I am misunderstanding?
For reproduction:
python version: Python 3.7.3
I installed the bitcoin.rpc via: pip3 install python-bitcoinlib
bitcoin-cli version: Bitcoin Core RPC client version v0.20.1
Running the client as bitcoind -txindex solves the problem as it maintains the full transaction index. I should have spent more attention to the error message...
Excerpt from bitcoind --help:
-txindex
Maintain a full transaction index, used by the getrawtransaction rpc
call (default: 0)

Pass the variable `Nothing` using Python's `win32com`

I am trying to pass the variable Nothing in VBA using Python's win32com. I tried to use None but it returned 'Type dismatch.'
Could anyone please help?
Thank you!
An example:
' Book1.xlsm!Module1
Function test(arg As Object) As String
If arg Is Nothing Then
test = "Success"
Exit Function
Else
test = "Failure"
Exit Function
End If
End Function
And in Python:
import win32com.client
import os
import pythoncom
xl = win32com.client.Dispatch('Excel.Application')
xl.Visible = True
xl.Workbooks.Open(Filename=os.path.abspath('Book1.xlsm'))
test_str = xl.Application.Run('Book1.xlsm!Module1.test', pythoncom.Empty)
The REPL says:
runfile('C:/Users/shwang/Downloads/untitled0.py', wdir='C:/Users/shwang/Downloads')
Traceback (most recent call last):
File "<ipython-input-22-301693920f2c>", line 1, in <module>
runfile('C:/Users/shwang/Downloads/untitled0.py', wdir='C:/Users/shwang/Downloads')
File "C:\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 866, in runfile
execfile(filename, namespace)
File "C:\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)
File "C:/Users/shwang/Downloads/untitled0.py", line 16, in <module>
test_str = xl.Application.Run('Book1.xlsm!Module1.test', pythoncom.Empty)
File "<COMObject <unknown>>", line 14, in Run
File "C:\Anaconda3\lib\site-packages\win32com\client\dynamic.py", line 287, in _ApplyTypes_
result = self._oleobj_.InvokeTypes(*(dispid, LCID, wFlags, retType, argTypes) + args)
com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2147352561), None)
In VBA, Nothing is used as the uninitialized default value Object type which usually references COM objects (i.e., Excel object library or external application's object library). VBA's primitive integer, long, and string types cannot be assigned the Nothing value. And usually programmers use this at the end of code block to release objects from memory.
Hence, there is no strict translation between VBA's Nothing (a special value for COM types) and Python's value types including None which crudely means empty or no value for any type.
With that said, your code will not err out if you pass a COM object which you already initialize with xl. Below outputs FAILURE. If somehow you can declare an uninitialized COM object which then will carry Nothing then you can pass that into your function. But to call Dispatch requires a named object. Catch-22!
import win32com.client
import os
try:
xl = win32com.client.Dispatch('Excel.Application')
xl.Visible = True
wb = xl.Workbooks.Open(Filename=os.path.abspath('Book1.xlsm'))
test_str = xl.Application.Run('test', xl)
print(test_str)
# FAILURE
wb.Close(False)
xl.Quit
except Exception as e:
print(e)
finally:
wb = None
xl = None
Here is a working example (in python) that passes VBA Nothing object to SolidWorks API.
import win32com.client
import pythoncom
swApp = win32com.client.Dispatch('SldWorks.Application')
Part = swApp.ActiveDoc
boolstatus = Part.Extension.SelectByID2("", "SKETCHCONTOUR", 75e-3, -4e-3, 0, False, 0, pythoncom.Nothing, 0)
print(boolstatus)
Here is the output in Sublime Text 3:
True
[Finished in 0.7s]
The script tries to select a sketch contour with the coordinates (75mm, -4mm). The "Callout" argument of the SolidWorks API "SelectByID2" is assigned as pythoncom.Nothing. For the script to work, the premise is that you are editing a sketch as shown in the attached figure below.
The attached figure shows what happens in SolidWorks (before | after).
Pass Nothing to SW API SelectByID2
Some background. I want to draw some electric motor geometry in SolidWorks via python because I already have the working python codes with other drawing tools (such as JMAG Designer, FEMM, or PyX).
Thanks for the post! Your discussion helps me find this.

How get list of Databases using Dispatch('ADODB.Connection')?

I am using PIOLEDBENT provider, i need to extract list of databases in my PIAF Server when i call oConn.GetSchema i throws exception mention bellow. please guide me what is wrong with my code.
from win32com.client import Dispatch
oConn = Dispatch('ADODB.Connection')
oRS = Dispatch('ADODB.RecordSet')
oConn.ConnectionString = "Provider=PIOLEDBENT; Data Source=localhost; Integrated Security=True; Integrated Security=True;User ID=abubakr;Password=#Spark123!"
oConn.Open()
oConn.GetSchema();
Exception :
pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, u'ADODB.Connection', u'Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.', u'C:\\Windows\\HELP\\ADO270.CHM', 1240641, -2146825287), None)

Categories