Unable to use win32com constants to automate powerpoint - python-3.x

I am new to python, trying to automate powerpoint using win32com. I am unable to import or use constants in my scripts. I have ran makepy to create libraries. below is the error messages & script. Can someone tell me how to import constants ?
Script :
import win32com.client
Application =win32com.client.gencache.EnsureDispatch("PowerPoint.Application")
Presentation = Application.Presentations.Add()
Base = Presentation.Slides.Add(1, ppLayoutBlank)
Error messages :
Traceback (most recent call last):
File "ppt.py", line 14, in
Base = Presentation.Slides.Add(1, ppLayoutBlank)
NameError: name 'ppLayoutBlank' is not defined

The INTEROP method you have chosen depends on the application interface to which you are connecting.
Not defined usually means that there is no such variable, but Python more often raises NameError in such cases. So what is exactly happening here is a little unclear.
So, depends on the version of PPoint on how to communicate with it.
I advise you to use pywinauto instead and go for "brute_force", i.e. emulate key presses and/or clicks etc. on right buttons, menues etc.
Because the names of thous is little less likely to change trough out the versions than a COM interface.
Microsoft has a nasty habit of changing just a little bit the interface, and then a program stops working.
If you want to insist on win32com, you will have to read PPoint's documentation for a specific version (or Office version), and for win32com for your Python version.
You should see whether you should start a COM Client or is there some other MS tweak you need to employ.

I'm under Linux now and cannot test here, but try to
import win32com.client.constants
... and then look for the constants defined in that module.
See also How to use win32com.client.constants with MS Word?.

Related

WxPython Error with wx.BufferedPaintDC method - Invalid DC

I'm currently updating a legacy application from Python 2.7.15 to Python 3.8.10. At the same time, I'm updating from wxPython version 2.8.12.1 to wxPython version 4.2.0.
I've used the 2to3 tool as well as done a lot of manual changes and the application is mostly running properly now. I have one major issue however, and it has to do with double-buffered drawing.
Specifically, in my onPaint() event handler, that has been bound to the EVT_PAINT event, I have the following code:
def onPaint(self,event):
drawPanelSize = self.drawPanel.GetSize()
self.bg_img = wx.Image('/background.png', wx.BITMAP_TYPE_ANY).Scale(drawPanelSize[0],
drawPanelSize[1])
bmp = wx.bitmap(self.bg_img)
dc = wx.BufferedPaintDC(self.drawPanel, bmp, wx.BUFFER_VIRTUAL_AREA)
There is more code above and below the code shown above, but this is the important area.
The problem that I am seeing is the following:
Traceback (most recent call last):
File "./TestBench.py", line 1553, in onPaint
dc = wx.BufferedPaintDC(self.drawPanel, bmp, wx.BUFFER_VIRTUAL_AREA)
wx._core.wxAssertionError: C++ assertion ""IsOk()"" failed at /tmp/pip-install-ewiqr929/wxPython/ext/wxWidgets/src/gtk/dc.cpp(238) in DoStretchBlit(): invalid DC
Does anyone have any insight into what may be going wrong here? Like I said this code worked fine using and older version of Python and an older version of wxPython. I would also accept any advice on how to appropriately debug this.
Please let me know if more information is required. I've already verified that the arguments to the function are valid. (i.e. self.drawPanel, and bmp are created properly and are valid arguments to the BufferedPaintDC method)
Also keep in mind most of the application (including the UI widgets, which are relying on gtk) is working at this point.
Things to note about my environment:
ubuntu (20:04)
gtk-3 (3.24.2)
Python (3.8.10)
wxPython (4.2.0)

How to create a logfile when calling CPLEX from python

In the website of https://www.ibm.com/support/knowledgecenter/SSSA5P_12.6.2/ilog.odms.cplex.help/CPLEX/GettingStarted/topics/tutorials/InteractiveOptimizer/solnOptions.html
I knew that when CPLEX solved a problem,it will create a logfile named as "cplex.log", but when I use CPLEX to solve a problem in python, this file wasn't created. And I'm so confused about that if this problem have some matters with the difference of languages. I mean, when using CPLEX to solve a problem in MATLAB, Java or C++, logfile will be created, but not created in python.
I'm expecting for your help.Thanks so much.
The cplex.log file is specific to the CPLEX interactive. It is not created automatically when using the other APIs (e.g., Python, Java, etc.). However, you can create it yourself doing the following (e.g., with the Python API):
cpx = cplex.Cplex()
cplexlog = "cplex.log"
cpx.set_results_stream(cplexlog)
cpx.set_warning_stream(cplexlog)
cpx.set_error_stream(cplexlog)
cpx.set_log_stream(cplexlog)
The argument to the set_*_stream methods can be a path (as above) or a file-like object, so you can do pretty much anything you want (e.g., implement a file-like object to display output on stdout but also write it to a log file, etc.). See the documentation for set_results_stream for more details.
NOTE: There is some output that gets displayed from the interactive that is not available in the other APIs. However, you should be able to recreate it easily as all of the information is available through the programmatic APIs.
EDIT:
With CPLEX 12.10 using a filename with the set_results_stream, set_warning_stream, set_error_stream, and set_log_stream methods has been removed (see announcement here). Instead, a file-like object should be passed in, like so:
with cplex.Cplex() as cpx, \
open("cplex.log") as cplexlog:
cpx.set_results_stream(cplexlog)
cpx.set_warning_stream(cplexlog)
cpx.set_error_stream(cplexlog)
cpx.set_log_stream(cplexlog)
...

How can I write unit tests against code that uses QDesktopServices openUrl?

I'm working on a python (3.5) program that use a PyQt5 GUI. In the GUI, I need to add some help links to the documentation on a website. I manage to make it work with:
QDesktopServices.openUrl(QUrl("my_url"))
It works fine but I want to be sure that it will always be the case.
A quick and dirty unittest is to call the function and simply notice that there is no error. I would like to make a test that will check that the correct website page did show up. What should I use?
Checking for an error is not going to work at all, because Qt itself never raises errors (of course, Python or PyQt might do, but for completely unrelated reasons). The best you can do is check the return value of openUrl, which will simply return True or False depending on whether it was "successful". But note the following from the Qt docs for openUrl:
Warning: A return value of true indicates that the application has
successfully requested the operating system to open the URL in an
external application. The external application may still fail to
launch or fail to open the requested URL. This result will not be
reported back to the application.
If you want more control, I suggest you use Python's webbrowser module instead. This would, for example, allow you to register your own mock-browser class for the purposes of testing. The webbrowser module is written in pure Python and the code is quite straightforward.

Pygsr speech recognition error

I'm trying to use Pygsr, what I'm doing wrong?
from pygsr import Pygsr
speech = Pygsr()
speech.record(3)
phrase, complete_response = speech.speech_to_text('es_ES')
print (phrase)
but I got error:
Traceback (most recent call last):
File "D:/VIV/PyCharm_project/0_WORKFILE_2.py", line 1, in <module>
from pygsr import Pygsr
File "C:\Users\User\AppData\Roaming\Python\Python35\site-packages\pygsr\__init__.py", line 30
print "REC: "
^
SyntaxError: Missing parentheses in call to 'print'
Process finished with exit code 1
The issue is that the Pygsr library seems to be written with some version of Python 2 in mind.
In Python 2, print is a statement and as such allows "softspace" in between the statement itself and the string to be printed. As of Python 3.0, print is a function and as such, requires opening and closing parentheses around the function arguments. Because Pygsr is written with some version of Python 2, it still uses the statement form of print, which is invalid in Python 3. This can be seen in the line that the SyntaxError is pointing to, which is a statement and not a function (print "REC: " vs print("REC: ")).
You've got a few options for fixing this issue:
The first option is to switch back down to using the latest version of Python 2 (which is 2.7.11 at time of writing). This will mean that anything that's not backwards compatible in 3 (but still works in 2) will function, but I don't recommend switching versions just to get a library working, especially because it will affect the code you write. As well as that, the general consensus (to the best of my knowledge) seems to be that new scripts built on 2 should use the function form of print, which is available from 2.6 onwards but can be imported from __future__ for versions before 2.6.
The second option is to use the automatic tool 2to3 to convert the scripts in the library to be compatible with 3. This won't always work 100% due to the complexity and potential edge cases that a Python script may have, but it's usually a good way to get a lot of the simpler changes out of the way quickly.
The third option is to make the changes yourself. This should be as simple as manually going through the library and fixing any references to print, but you could also find the issues by running your script, seeing which file and line number is referenced in the error and then making the required edits.

How to force Excel VBA to use updated COM server

I'm developing a COM server to be used from Excel VBA. When I update the server (edit code, unregister, re-register) Excel seems to carry on using the original version of the COM server, not the updated version. The only way I have found to get it to use the updated version is to close and re-open Excel, which gets a bit irritating. Is there a way to force Excel to use the newly registered version (maybe some kind of "clear cache" option)?
More details:
The server is being developed in Python using win32com.
In VBA I'm doing something like:
set obj=CreateObject("Foo.Bar")
obj.baz()
Where Foo.Bar is the COM server I have registered in the registry.
If I unregister the server then run the VBA code, I get a "can't create object" error from VBA, so it must realise that something is going on. But once I reregister it picks up the old version.
Any hints appreciated!
Thanks,
Andy
I've found a solution to my problem - the general idea is to set things up so that the main COM server class dynamically loads the rest of the COM server code when it is called. So in Python I've created a COM server class that looks something like:
import main_code
class COMInterface:
_public_methods_ = [ 'method1' ]
_reg_progid_ = "My.Test"
_reg_clsid_ = "{D6AA2A12-A5CE-4B6C-8603-7952B711728B}"
def methods(self, input1,input2,input3):
# force python to reload the code that does the actual work
reload(main_code)
return main_code.Runner().go(input1,input2,input3)
The main_code module contains the code that does the actual work and is reloaded each time the COM method is called. This works as long as the inputs don't change. There will presumably be a runtime penalty for this, so might want to remove the reload for the final version, but it works for development purposes.
Just a suggestion, have you tried to Unload the object? Maybe create a button in your excel spredsheat that force to unload the object.
I hope it helps

Resources