问题
I'm trying to automate ChemDraw for a user in the background, preferably avoiding using SendKeys() as I believe that requires a ChemDraw instance to be visible for that to work. What I need to do is somehow click Edit -> Copy As -> InChI programmatically, then retrieve the result from the Windows clipboard.
We're currently using Python and COM scripting to attempt this. Here's our current code:
# Opens ChemDraw and loads the file, while keeping the window hidden.
ChemDraw = w32.DispatchEx('ChemDraw.Application') # ChemDraw Application Object
ChemDraw.Visible = False # Makes Invisible
Compound= ChemDraw.Documents.Open(cdx_filepath) # ChemDraw File Object (Can be seen with ChemDraw.Activate())
# Selects the whole molecule.
Compound.Objects.Select()
# Here is where we need to figure out how to do CopyAs and Save off clipboard content.
# Saves the file and Quits afterwards.
Compound.SaveAs(jpg_filepath)
ChemDraw.Quit()
I guess I have two questions: how do we access "Edit" in the toolbar and the resulting values in it? How do take the resulting object made from a line like "ChemDraw = w32.DispatchEx('ChemDraw.Application')" and determine what you can do with it? Part of the issue is that we can't seem to introspect the resulting DispatchEx object, thus we're having a hard answering our own question.
回答1:
The first question on how to access the contents of the "Edit" menu will be specific to ChemDraw itself, and not having that around, I am unable to give an immediate solution to that.
However, perhaps having an answer to the second question will allow you to answer the first one yourself, so, here goes: Assuming that the ChemDraw COM object allows it, you can use win32com.client.gencache.EnsureDispatch in place of DispatchEx in order to auto-generate Python classes for the object; this allows you to inspect the objects in greater detail. Rather than using EnsureDispatch, you can also access the underlying code-generating functionality directly, which may be more applicable to your workflow. See this question and this guide for further details.
回答2:
Because of the intricacies of COM scripting, I don't think you can really "access the edit menu", but there's a solution to access and store an InChI string:
For starters, I highly recommend you use comtypes over win32com because that gives a lot more information when you use dir(), and the syntax is almost identical as far as I can tell. Win32com gives little to nothing, so you're essentially looking for a needle in a dark room for mere functions (unless you have an SDK available). From there, you open the ChemDraw file, access the Objects class, then use the Data() method and input "chemical/x-inchi" (in your case). I've been working with ChemDraw for a project as well, and I had to do the same thing, so here's what you want:
import comtypes.client as w32
# Path for experimental ChemDraw File.
cdx_file = # Insert ChemDraw file path here
# Creates invisible ChemDraw object.
ChemDraw = w32.CreateObject("ChemDraw.Application")
ChemDraw.Visible = True
# Creates file object.
Compound = ChemDraw.Documents.Open(cdx_file)
# Converts file to InChI string.
file_inchi = Compound.Objects.Data("chemical/x-inchi")
print(file_inchi)
# Closes ChemDraw
ChemDraw.Quit()
P.S.: CreateObject is the comtypes equivalent of DispatchEx() for win32com.
Comtypes Documentation: https://pythonhosted.org/comtypes/
ChemDraw SDK: http://www.cambridgesoft.com/services/documentation/sdk/chemdraw/ActiveX11/ChemDrawControl10_P.html
来源:https://stackoverflow.com/questions/51502558/windows-application-automation-with-python-com