Christian K. wrote:
<Clip ...>
Hi Christian,
As promised, attached please find a sample program for accessing the
Office Ribbon from Python. A couple notes:
1) The program I've written is for Excel; if you want Outlook you'll
need to change the registration code, but this shouldn't be a big deal!
2) I'd appreciate it if you'll let me know whether the Tag attribute
in the callback can be read. This is the problem I mentioned in my
initial response. Just let me know the contents of the second message
box after clicking the button in Office.
3) If you get into this and have to start writing XML, you might want
to pick up a copy of "Ribbon X: Customizing the Office 2007 Ribbon."
It's written from a VBA perspective but has a lot of info on the Ribbon
controls, their attributes and callbacks. If there are errors in the
XML, Excel silently ignores it, not adding anything to the ribbon.
Hope this helps.
Robert Kaplan
robert2...@veriozn.net
# ribbon.py sample program for accessing the Office Ribbon
# Copyright 2010 Robert Kaplan. All Rights Reserve.
# Copying is premitted in accordance with terms of
# orignal copyright
#
# Sample file demonstrating ribbon control addin for Excel
# This file was originally based on excelAddin.py demo file,
# included in the win32 com distribution
# the original copyright for that file follows:
#
# START OF ORIGINAL COPYRIGHT
#
# A demo plugin for Microsoft Excel
#
# This addin simply adds a new button to the main Excel toolbar,
# and displays a message box when clicked. Thus, it demonstrates
# how to plug in to Excel itself, and hook Excel events.
#
#
# To register the addin, simply execute:
# excelAddin.py
# This will install the COM server, and write the necessary
# AddIn key to Excel
#
# To unregister completely:
# excelAddin.py --unregister
#
# To debug, execute:
# excelAddin.py --debug
#
# Then open Pythonwin, and select "Tools->Trace Collector Debugging Tool"
# Restart excel, and you should see some output generated.
#
# NOTE: If the AddIn fails with an error, Excel will re-register
# the addin to not automatically load next time Excel starts. To
# correct this, simply re-register the addin (see above)
#
# Author <eko...@yahoo.com> Eric Koome
# Copyright (c) 2003 Wavecom Inc. All rights reserved
#
# Redistribution and use in source and binary forms, with or without
#modification, are permitted provided that the following conditions
#are met:
#
#1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL ERIC KOOME OR
# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# END OF ORIGINAL COPYRIGHT
#import win32com
from win32com import universal
from win32com.server.exception import COMException
from win32com.client import gencache, DispatchWithEvents
import winerror
import pythoncom
from win32com.client import constants, Dispatch
from win32com.server.util import wrap, unwrap
import win32ui
import win32con
import sys
import os
# Support for COM objects we use.
gencache.EnsureModule('{00020813-0000-0000-C000-000000000046}', 0, 1, 6, bForDemand=True) # Excel 12
gencache.EnsureModule('{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}', 0, 2, 4, bForDemand=True) # Office 12
# The TLB defiining the interfaces we implement
universal.RegisterInterfaces('{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}', 0, 1, 0, ["_IDTExtensibility2"])
have_ribbon = True
try:
universal.RegisterInterfaces('{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}', 0, 2, 4, ["IRibbonExtensibility", "IRibbonControl"])
except:
have_ribbon = False
class ExcelAddin:
_com_interfaces_ = ['_IDTExtensibility2']
if have_ribbon:
_com_interfaces_. append ('IRibbonExtensibility') # in case we have new excel with ribbon interface !
_public_methods_ = ['RibbonCall']
_reg_clsctx_ = pythoncom.CLSCTX_INPROC_SERVER
_reg_clsid_ = "{01256242-64D6-4F67-BF4B-2ECA4F9AB7D1}"
_reg_progid_ = "Python.RibbonDemo"
_reg_policy_spec_ = "win32com.server.policy.EventHandlerPolicy"
def __init__(self):
self.appHostApp = None
# these five routines are the IDTExtensibility2 interface
def OnConnection(self, application, connectMode, addin, custom):
try:
print 'App:', application
self.appHostApp = application
if not have_ribbon:
# code to add old menu bar style menus would go here
pass
except Exception as e:
win32ui. MessageBox (str (e), 'Python error', win32con. MB_OKCANCEL)
def OnDisconnection(self, mode, custom):
print "OnDisconnection"
self.appHostApp=None
def OnAddInsUpdate(self, custom):
print "OnAddInsUpdate", custom
def OnStartupComplete(self, custom):
print "OnStartupComplete", custom
def OnBeginShutdown(self, custom):
print "OnBeginShutdown", custom
# this is the IRibbonExtensibility interface and is called by Excel to get the xml for adding ribbon panels
def GetCustomUI (self, arg):
xml = """
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<tabs>
<tab id="Python" label="Python">
<group id="SampleGroup" label="Sample Group">
<button id="FromPython" label="Hello" onAction="RibbonCall" tag="RibbonCall" enabled="true"/>
</group>
</tab>
</tabs>
</ribbon>
</customUI>
"""
#print xml
return xml
# this is the callback routine for when the button is clicked
# it is referenced in the onAction attribute of the xml above
def RibbonCall (self, a1):
print 'RibbonCall'
try:
# this is the callback for the ribbon button added
win32ui. MessageBox ("Hello from the ribbon", 'Python', win32con. MB_OKCANCEL)
try:
ta = a1. Tag
m = "Getting tag ok, tag = " + ta
except Exception as e:
m = "Getting tag failed, error = " + str (e)
win32ui. MessageBox (m, 'Python', win32con. MB_OKCANCEL)
except pythoncom.com_error, (hr, msg, exc, arg):
print "The Excel call failed with code %d: %s" % (hr, msg)
if exc is None:
print "There is no extended error information"
else:
wcode, source, text, helpFile, helpId, scode = exc
print "The source of the error is", source
print "More info can be found in %s (id=%d)" % (helpFile, helpId)
def RegisterAddin(klass):
import _winreg
key = _winreg.CreateKey(_winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Office\\Excel\\Addins")
subkey = _winreg.CreateKey(key, klass._reg_progid_)
_winreg.SetValueEx(subkey, "CommandLineSafe", 0, _winreg.REG_DWORD, 0)
_winreg.SetValueEx(subkey, "LoadBehavior", 0, _winreg.REG_DWORD, 3)
_winreg.SetValueEx(subkey, "Description", 0, _winreg.REG_SZ, "Ribbon Demo Excel Addin")
_winreg.SetValueEx(subkey, "FriendlyName", 0, _winreg.REG_SZ, "Ribbon Demo Excel Addin")
def UnregisterAddin(klass):
import _winreg
try:
_winreg.DeleteKey(_winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Office\\Excel\\Addins\\" + klass._reg_progid_)
except WindowsError:
pass
if __name__ == '__main__':
import win32com.server.register
win32com.server.register.UseCommandLine(ExcelAddin)
if "--unregister" in sys.argv:
UnregisterAddin(ExcelAddin)
else:
RegisterAddin(ExcelAddin)
_______________________________________________
python-win32 mailing list
python-win32@python.org
http://mail.python.org/mailman/listinfo/python-win32