123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- # 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 <ekoome@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.
- 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
- import sys
- # Support for COM objects we use.
- gencache.EnsureModule('{00020813-0000-0000-C000-000000000046}', 0, 1, 3, bForDemand=True) # Excel 9
- gencache.EnsureModule('{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}', 0, 2, 1, bForDemand=True) # Office 9
- # The TLB defiining the interfaces we implement
- universal.RegisterInterfaces('{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}', 0, 1, 0, ["_IDTExtensibility2"])
- class ButtonEvent:
- def OnClick(self, button, cancel):
- import win32ui # Possible, but not necessary, to use a Pythonwin GUI
- import win32con
- win32ui.MessageBox("Hello from Python", "Python Test",win32con.MB_OKCANCEL)
- return cancel
- class ExcelAddin:
- _com_interfaces_ = ['_IDTExtensibility2']
- _public_methods_ = []
- _reg_clsctx_ = pythoncom.CLSCTX_INPROC_SERVER
- _reg_clsid_ = "{C5482ECA-F559-45A0-B078-B2036E6F011A}"
- _reg_progid_ = "Python.Test.ExcelAddin"
- _reg_policy_spec_ = "win32com.server.policy.EventHandlerPolicy"
- def __init__(self):
- self.appHostApp = None
-
- def OnConnection(self, application, connectMode, addin, custom):
- print("OnConnection", application, connectMode, addin, custom)
- try:
- self.appHostApp = application
- cbcMyBar = self.appHostApp.CommandBars.Add(Name="PythonBar", Position=constants.msoBarTop, MenuBar=constants.msoBarTypeNormal, Temporary=True)
- btnMyButton = cbcMyBar.Controls.Add(Type=constants.msoControlButton, Parameter="Greetings")
- btnMyButton=self.toolbarButton = DispatchWithEvents(btnMyButton, ButtonEvent)
- btnMyButton.Style = constants.msoButtonCaption
- btnMyButton.BeginGroup = True
- btnMyButton.Caption = "&Python"
- btnMyButton.TooltipText = "Python rules the World"
- btnMyButton.Width = "34"
- cbcMyBar.Visible = True
- except pythoncom.com_error as xxx_todo_changeme:
- (hr, msg, exc, arg) = xxx_todo_changeme.args
- 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("The error message is", text)
- print("More info can be found in %s (id=%d)" % (helpFile, helpId))
- def OnDisconnection(self, mode, custom):
- print("OnDisconnection")
- self.appHostApp.CommandBars("PythonBar").Delete
- self.appHostApp=None
-
- def OnAddInsUpdate(self, custom):
- print("OnAddInsUpdate", custom)
- def OnStartupComplete(self, custom):
- print("OnStartupComplete", custom)
- def OnBeginShutdown(self, custom):
- print("OnBeginShutdown", custom)
- 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, "Excel Addin")
- winreg.SetValueEx(subkey, "FriendlyName", 0, winreg.REG_SZ, "A Simple 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)
|