1

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.

enter image description here

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.

2 Answers2

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.

fuglede
  • 17,388
  • 2
  • 54
  • 99
1

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

King Burst
  • 71
  • 4
  • 1
    this was helpful. Does this also somehow work in the other direction: start with an InChI and generate a ChemDraw file (.cdx or .cdxml)? – theozh Sep 28 '19 at 01:17
  • @theozh Assuming you already have the InChI string in your clipboard, you can copy the InChI string and paste that string into ChemDraw, which will result in the corresponding structure being displayed in the ChemDraw file. So you can write a COM script that opens ChemDraw -> pastes that string into the ChemDraw workspace -> and then saves the resulting file. – King Burst Sep 29 '19 at 19:14
  • 1
    thank you! I hope I will find the necessary information how to open an empty ChemDraw file, paste the clipboard content and save the file. I assume the primary source to consult would be https://pythonhosted.org/comtypes/ , correct? – theozh Sep 29 '19 at 19:35
  • That's definitely a good reference for learning more about the comtypes package, albeit COM scripting in a specific application would probably involve more debugging on the developer's end. In fact, I'll edit my answer to refer to that site. – King Burst Sep 29 '19 at 19:56
  • hmmm, I can't find any specific information about ChemDraw even not on http://insideinformatics.cambridgesoft.com/categories/chemistry/chemdraw/default.aspx. Where did you get your information about ChemDraw classes? Maybe you can have a look at https://stackoverflow.com/q/58183902/7295599 and can give some hints? – theozh Oct 01 '19 at 20:37
  • Regarding the information about ChemDraw classes, I honestly just used import pdb; pdb.set_trace() within my Python code and used dir(Compound) to get some information pertaining to the Compound as well as the methods I could utilize. Back when I worked on a project involving that code, we also used the following to give us an idea as to what we could do with ChemDraw programmatically http://www.cambridgesoft.com/services/documentation/sdk/chemdraw/ActiveX11/ChemDrawControl10_P.html. Its example code is in Basic I believe, but from looking at the code, I converted it into Python. – King Burst Oct 07 '19 at 01:41