如何使用Win32COM在Python中检索Excel Iribbonui实例?
我正在尝试使用Python的win32com
软件包将Excel加载项色带上的特定控件无效,以便重新呼叫。
阅读Microsoft的对象引用和 iribbonui 我所看到的所有建议是保存一个在其onload
回调中引用功能区。这也是我过去在VBA编码时完成此操作的方式。不幸的是,我不确定如何使用Python的win32com
软件包到达这一点。
我正在使用 pyxll 作为使用Python代码代码的手段而不是Xlam。通过使用此功能,我能够访问功能区 onload 回调中的功能区com对象,但在onclick
on Callback 中不在功能区中的回调,因为唯一的传递到这些函数的参数是控件的com对象。
将一些恢复调试信息
- 参数传递到功能区
on Lota
回调的实例是win32com.gen_py.gen_py.microsoft Office 16.0对象库库库
- 参数的
_ 值是_OLEOBJ _OLEOBJ _OLEOBJ _OLEOBJ _OLEOBJ _
_PyidisPatch
实例, - 错误似乎是围绕
dispatchbaseclass
inwin32com.client
class DispatchBaseClass:
def __init__(self, oobj=None):
if oobj is None:
oobj = pythoncom.new(self.CLSID)
elif isinstance(oobj, DispatchBaseClass):
try:
oobj = oobj._oleobj_.QueryInterface(
self.CLSID, pythoncom.IID_IDispatch
) # Must be a valid COM instance
except pythoncom.com_error as details:
import winerror
# Some stupid objects fail here, even tho it is _already_ IDispatch!!??
# Eg, Lotus notes.
# So just let it use the existing object if E_NOINTERFACE
if details.hresult != winerror.E_NOINTERFACE:
raise
oobj = oobj._oleobj_
self.__dict__["_oleobj_"] = oobj # so we dont call __setattr__
- 我的想法是保存对实际类的参考,重新创建它,设置
clsid
类变量,然后实例化新课。
def ribbon_loaded(ribbon):
r_class = ribbon.__class__
# was thinking I could pickle this class for use elsewhere
class RibbonUI(r_class): # also tried type(r_class)
CLSID = ribbon.CLSID
# just checking below that this would work
# if CLSID is not set on the new class above __init__ fails
# but, even when provided __new__ fails with the next line
new_ribbon = RibbonUI()
new_ribbon.InvalidateControl("ribbon_control_1")
如果不设置CLSID
在新类上,错误是
2022-07-06 20:48:09,294 - INFO : ribbon.CLSID: IID('{000C03A7-0000-0000-C000-000000000046}')
2022-07-06 20:48:09,314 - ERROR : Error calling ribbon function 'components.ribbon.ribbon_loaded'
2022-07-06 20:48:15,364 - ERROR : Traceback (most recent call last):
2022-07-06 20:48:15,364 - ERROR : File "C:\Users\mhill\PycharmProjects\excel-addin\components\ribbon.py", line 46, in ribbon_loaded
2022-07-06 20:48:15,365 - ERROR : new_ribbon = RibbonUI()
2022-07-06 20:48:15,366 - ERROR : File "c:\users\mhill\PyCharmProjects\excel-addin\.venv\lib\site-packages\win32com\client\__init__.py", line 514, in __init__
2022-07-06 20:48:15,366 - ERROR : oobj = pythoncom.new(self.CLSID)
2022-07-06 20:48:15,366 - ERROR : pywintypes.com_error: (-2147221164, 'Class not registered', None, None)
在创建新类并指定CLSID
类变量时,错误变为
2022-07-06 20:48:22,429 - INFO : ribbon.CLSID: IID('{000C03A7-0000-0000-C000-000000000046}')
2022-07-06 20:48:22,429 - ERROR : Error calling ribbon function 'components.ribbon.ribbon_loaded'
2022-07-06 20:48:28,949 - ERROR : Traceback (most recent call last):
2022-07-06 20:48:28,950 - ERROR : File "C:\Users\mhill\PycharmProjects\excel-addin\components\ribbon.py", line 46, in ribbon_loaded
2022-07-06 20:48:28,951 - ERROR : new_ribbon = RibbonUI()
2022-07-06 20:48:28,951 - ERROR : TypeError: type.__new__() takes exactly 3 arguments (0 given)
相关问题提到了创建IDTextensibility2对象的一些问题,但不确定该如何处理。
除了模仿从功能区的onload
回调的情况
下,在Microsoft文档所建议的那样,除了模仿将全局引用对功能区的全局引用外,我如何在功能区onload Callback中的Iribbonui com对象和能够在控件的onclick
回调中访问它吗?
I'm trying to invalidate specific controls on an Excel add-in ribbon using Python's win32com
package in order to have their callbacks re-fire.
Reading over Microsoft's Object References and the IRibbonUI documentation all I've seen recommended is to save a reference to the ribbon in its onLoad
callback. This is also how I've accomplished this in the past when coding in VBA. Unfortunately, I'm not sure how to get to that point using python's win32com
package.
I'm using PyXLL as a means to code the add-in using Python and for future distribution as an xll instead of xlam. By using this I'm able to access the ribbon com object in the ribbon onLoad
callback, but not within the onClick
callbacks of the controls included in the ribbon, since the only parameter passed into those functions is the control's com object.
Some relavent debugging info
- parameter passed into the ribbon
onLoad
callback is an instance ofwin32com.gen_py.Microsoft Office 16.0 Object Library.IRibbonUI
- the parameter's
_oleobj_
value is aPyIDispatch
instance - The errors seems to center around the
DispatchBaseClass
inwin32com.client
class DispatchBaseClass:
def __init__(self, oobj=None):
if oobj is None:
oobj = pythoncom.new(self.CLSID)
elif isinstance(oobj, DispatchBaseClass):
try:
oobj = oobj._oleobj_.QueryInterface(
self.CLSID, pythoncom.IID_IDispatch
) # Must be a valid COM instance
except pythoncom.com_error as details:
import winerror
# Some stupid objects fail here, even tho it is _already_ IDispatch!!??
# Eg, Lotus notes.
# So just let it use the existing object if E_NOINTERFACE
if details.hresult != winerror.E_NOINTERFACE:
raise
oobj = oobj._oleobj_
self.__dict__["_oleobj_"] = oobj # so we dont call __setattr__
- My thinking is to save a reference to the actual class, recreate it, set the
CLSID
class variable, then instantiate the new class.
def ribbon_loaded(ribbon):
r_class = ribbon.__class__
# was thinking I could pickle this class for use elsewhere
class RibbonUI(r_class): # also tried type(r_class)
CLSID = ribbon.CLSID
# just checking below that this would work
# if CLSID is not set on the new class above __init__ fails
# but, even when provided __new__ fails with the next line
new_ribbon = RibbonUI()
new_ribbon.InvalidateControl("ribbon_control_1")
Without setting CLSID
on the new class the error is
2022-07-06 20:48:09,294 - INFO : ribbon.CLSID: IID('{000C03A7-0000-0000-C000-000000000046}')
2022-07-06 20:48:09,314 - ERROR : Error calling ribbon function 'components.ribbon.ribbon_loaded'
2022-07-06 20:48:15,364 - ERROR : Traceback (most recent call last):
2022-07-06 20:48:15,364 - ERROR : File "C:\Users\mhill\PycharmProjects\excel-addin\components\ribbon.py", line 46, in ribbon_loaded
2022-07-06 20:48:15,365 - ERROR : new_ribbon = RibbonUI()
2022-07-06 20:48:15,366 - ERROR : File "c:\users\mhill\PyCharmProjects\excel-addin\.venv\lib\site-packages\win32com\client\__init__.py", line 514, in __init__
2022-07-06 20:48:15,366 - ERROR : oobj = pythoncom.new(self.CLSID)
2022-07-06 20:48:15,366 - ERROR : pywintypes.com_error: (-2147221164, 'Class not registered', None, None)
When creating the new class and specifying the the CLSID
class variable the error becomes
2022-07-06 20:48:22,429 - INFO : ribbon.CLSID: IID('{000C03A7-0000-0000-C000-000000000046}')
2022-07-06 20:48:22,429 - ERROR : Error calling ribbon function 'components.ribbon.ribbon_loaded'
2022-07-06 20:48:28,949 - ERROR : Traceback (most recent call last):
2022-07-06 20:48:28,950 - ERROR : File "C:\Users\mhill\PycharmProjects\excel-addin\components\ribbon.py", line 46, in ribbon_loaded
2022-07-06 20:48:28,951 - ERROR : new_ribbon = RibbonUI()
2022-07-06 20:48:28,951 - ERROR : TypeError: type.__new__() takes exactly 3 arguments (0 given)
Related question mentions something about creating an IDTExtensibility2 object, but not quite sure what to do with that.
The question
Apart from mimicking saving a global reference to the ribbon object from within the ribbon's onLoad
callback as Microsoft's documentation suggests, how can I properly save a reference to the IRibbonUI com object when in the ribbon onLoad callback and be able to access it in the controls' onClick
callbacks?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
叹气,看起来全局变量选项是推荐路线
摘录
Sigh, looks like the global variable option is the recommended route
Excerpt