codekingpro/portable-devtools
114k
1# A demo plugin for Microsoft Excel2#3# This addin simply adds a new button to the main Excel toolbar,4# and displays a message box when clicked. Thus, it demonstrates5# how to plug in to Excel itself, and hook Excel events.6#7#8# To register the addin, simply execute:9# excelAddin.py10# This will install the COM server, and write the necessary11# AddIn key to Excel12#13# To unregister completely:14# excelAddin.py --unregister15#16# To debug, execute:17# excelAddin.py --debug18#19# Then open Pythonwin, and select "Tools->Trace Collector Debugging Tool"20# Restart excel, and you should see some output generated.21#22# NOTE: If the AddIn fails with an error, Excel will re-register23# the addin to not automatically load next time Excel starts. To24# correct this, simply re-register the addin (see above)25#26# Author <ekoome@yahoo.com> Eric Koome27# Copyright (c) 2003 Wavecom Inc. All rights reserved28#29# Redistribution and use in source and binary forms, with or without30# modification, are permitted provided that the following conditions31# are met:32#33# 1. Redistributions of source code must retain the above copyright34# notice, this list of conditions and the following disclaimer.35#36# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED37# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES38# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE39# DISCLAIMED. IN NO EVENT SHALL ERIC KOOME OR40# ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,41# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT42# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF43# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND44# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,45# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT46# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF47# SUCH DAMAGE.48 49import sys50 51import pythoncom52from win32com import universal53from win32com.client import Dispatch, DispatchWithEvents, constants, gencache54from win32com.server.exception import COMException55 56# Support for COM objects we use.57gencache.EnsureModule(58 "{00020813-0000-0000-C000-000000000046}", 0, 1, 3, bForDemand=True59) # Excel 960gencache.EnsureModule(61 "{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}", 0, 2, 1, bForDemand=True62) # Office 963 64# The TLB defining the interfaces we implement65universal.RegisterInterfaces(66 "{AC0714F2-3D04-11D1-AE7D-00A0C90F26F4}", 0, 1, 0, ["_IDTExtensibility2"]67)68 69 70class ButtonEvent:71 def OnClick(self, button, cancel):72 import win32con # Possible, but not necessary, to use a Pythonwin GUI73 import win32ui74 75 win32ui.MessageBox("Hello from Python", "Python Test", win32con.MB_OKCANCEL)76 return cancel77 78 79class ExcelAddin:80 _com_interfaces_ = ["_IDTExtensibility2"]81 _public_methods_ = []82 _reg_clsctx_ = pythoncom.CLSCTX_INPROC_SERVER83 _reg_clsid_ = "{C5482ECA-F559-45A0-B078-B2036E6F011A}"84 _reg_progid_ = "Python.Test.ExcelAddin"85 _reg_policy_spec_ = "win32com.server.policy.EventHandlerPolicy"86 87 def __init__(self):88 self.appHostApp = None89 90 def OnConnection(self, application, connectMode, addin, custom):91 print("OnConnection", application, connectMode, addin, custom)92 try:93 self.appHostApp = application94 cbcMyBar = self.appHostApp.CommandBars.Add(95 Name="PythonBar",96 Position=constants.msoBarTop,97 MenuBar=constants.msoBarTypeNormal,98 Temporary=True,99 )100 btnMyButton = cbcMyBar.Controls.Add(101 Type=constants.msoControlButton, Parameter="Greetings"102 )103 btnMyButton = self.toolbarButton = DispatchWithEvents(104 btnMyButton, ButtonEvent105 )106 btnMyButton.Style = constants.msoButtonCaption107 btnMyButton.BeginGroup = True108 btnMyButton.Caption = "&Python"109 btnMyButton.TooltipText = "Python rules the World"110 btnMyButton.Width = "34"111 cbcMyBar.Visible = True112 except pythoncom.com_error as xxx_todo_changeme:113 (hr, msg, exc, arg) = xxx_todo_changeme.args114 print("The Excel call failed with code %d: %s" % (hr, msg))115 if exc is None:116 print("There is no extended error information")117 else:118 wcode, source, text, helpFile, helpId, scode = exc119 print("The source of the error is", source)120 print("The error message is", text)121 print("More info can be found in %s (id=%d)" % (helpFile, helpId))122 123 def OnDisconnection(self, mode, custom):124 print("OnDisconnection")125 self.appHostApp.CommandBars("PythonBar").Delete126 self.appHostApp = None127 128 def OnAddInsUpdate(self, custom):129 print("OnAddInsUpdate", custom)130 131 def OnStartupComplete(self, custom):132 print("OnStartupComplete", custom)133 134 def OnBeginShutdown(self, custom):135 print("OnBeginShutdown", custom)136 137 138def RegisterAddin(klass):139 import winreg140 141 key = winreg.CreateKey(142 winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Office\\Excel\\Addins"143 )144 subkey = winreg.CreateKey(key, klass._reg_progid_)145 winreg.SetValueEx(subkey, "CommandLineSafe", 0, winreg.REG_DWORD, 0)146 winreg.SetValueEx(subkey, "LoadBehavior", 0, winreg.REG_DWORD, 3)147 winreg.SetValueEx(subkey, "Description", 0, winreg.REG_SZ, "Excel Addin")148 winreg.SetValueEx(subkey, "FriendlyName", 0, winreg.REG_SZ, "A Simple Excel Addin")149 150 151def UnregisterAddin(klass):152 import winreg153 154 try:155 winreg.DeleteKey(156 winreg.HKEY_CURRENT_USER,157 "Software\\Microsoft\\Office\\Excel\\Addins\\" + klass._reg_progid_,158 )159 except WindowsError:160 pass161 162 163if __name__ == "__main__":164 import win32com.server.register165 166 win32com.server.register.UseCommandLine(ExcelAddin)167 if "--unregister" in sys.argv:168 UnregisterAddin(ExcelAddin)169 else:170 RegisterAddin(ExcelAddin)171 