When getting Document object from Word.Application

2019-07-13 22:10发布

问题:

https://mail.python.org/pipermail/python-win32/2004-October/002582.html summarizes my problem perfectly (with slight edits to update it for my case):

I would like to have a Word Document instance with all methods and properties visible during interactive session. This is my currnet apporach:

>>> from win32com.client import gencache, Dispatch
>>> gencache.EnsureModule('{00020905-0000-0000-C000-000000000046}', 0, 8, 1, bForDemand=True) 
<module 'win32com.gen_py.00020905-0000-0000-C000-000000000046x0x8x1' from
'C:\DOCUME~1\osuchw\LOCALS~1\Temp\gen_py\2.3\00020905-0000-0000-C000-000000000046x0x8x1\__init__.py'>
>>> word = Dispatch('Word.Application')
>>> word 
<win32com.gen_py.Microsoft Word 12.0 Object Library._Application instance at 0x18074720>
>>> doc = word.Documents.Add()
>>> doc 
<win32com.gen_py.None.Document>

As you can see I am getting a dynamic object not knowing its methods/properties. What I would like to get is something like:

>>> doc = Dispatch('Word.Document')
>>> doc 
<win32com.gen_py.Microsoft Word 12.0 Object Library._Document instance at 0x37038040>

I guess I need to also generate a wrapper from another type library (e.g. there is "Office 12.0 Object Library") but there's no hint on which it is. Likewise, there's no TypeLib subkey at HKEY_CLASSES_ROOT\CLSID\{00020906-0000-0000-C000-000000000046} which is what doc.CLSID produces.

The only answer in that thread directs to RTFM a general book on Word programming w/o any hints whatsoever (I seriously doubt it even mentions typelibs).

I ended up generating wrappers for all the type libraries at the machine with the following code:

import win32com.client.selecttlb    
ii=win32com.client.selecttlb.EnumTlbs()
ii=[i.desc for i in ii]
# one typelib - "Visual Basic runtime objects and procedures [6.0]" - produced an error
for i in ii: subprocess.call(['python','-m','win32com.client.makepy',i])

but even in this case, it's still win32com.gen_py.None.Document.


The strangest thing is that the object's class is recognized and present in the cache:

>>> ad=win32com.client.gencache.EnsureDispatch("Word.Document")
>>> d = w.ActiveDocument
>>> d.__class__
<class win32com.gen_py.00020905-0000-0000-C000-000000000046x0x8x4.Document at 0x02A101B8>
>>> ad.__class__
<class win32com.gen_py.00020905-0000-0000-C000-000000000046x0x8x4._Document at 0x02A07B20>
>>> len(dir(ad.__class__))
141
>>> len(dir(d.__class__))
11

At the same time, VBA editor and VBSEdit list w.ActiveDocument's members just fine. How do they do that and why can't pythoncom do the same?

回答1:

d._dispobj_ has all the members, so it can be used instead of d.

The immediate problem is solved.

Yet I've still no idea what is going on.