0

我已经修改了 pywin 包演示,该演示创建了一个用于 excel 功能区栏的按钮。按下按钮后,所选文本将在命令行中运行,所选文本将被输出替换。

使用不同的 clsid 文件名组合注册程序时出现问题。我无法更改代码的 clsid 和/或文件名。如果我创建此文件的副本,修改并注册它,运行的 COM 对象是原始的 excelAddin.py,而不是我新修改的文​​件。我现在缺少 COM 注册过程中的一个步骤。我应该在哪里添加哪一行?

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
import win32traceutil

# 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
        import subprocess
        app = Dispatch("Word.Application")
        cmd = app.Selection

        #subprocess.Popen(str(cmd))
        cmdP = subprocess.Popen(str(cmd), shell = True, stdout = subprocess.PIPE)
        txt = cmdP.stdout.readlines()
        output = ''
        for line in txt:
            output += line

        app.Selection.TypeText(output)
        #win32ui.MessageBox(txt, "Python Test",win32con.MB_OKCANCEL)
        return cancel

class ExcelAddin:
    _com_interfaces_ = ['_IDTExtensibility2']
    _public_methods_ = []
    _reg_clsctx_ = pythoncom.CLSCTX_INPROC_SERVER
    #_reg_clsid_ = ""
    _reg_clsid_ = "{C5482ECA-F559-45A0-B078-B2036E6F011A}"
    #_reg_clsid_ = "{E44EF798-7FDF-4015-AED6-00234CBBBA77}"
    #_reg_clsid_ = "{91A89B71-56C0-4a76-BF1F-CF52E3671740}"
    _reg_progid_ = 'Juha.test'#"Python.Test.ExcelAddin2"
    _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 = "&Run..."
            btnMyButton.TooltipText = "Runs the selected text in command line"
            btnMyButton.Width = "34"
            cbcMyBar.Visible = True
        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 "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\\Word\\Addins")
    #key = _winreg.CreateKey(_winreg.HKEY_LOCAL_MACHINE, "Software\\Classes\\CLSID")
    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, "Runs selection in command line and pastes output")
    _winreg.SetValueEx(subkey, "FriendlyName", 0, _winreg.REG_SZ, "cmdlineRunner")

def UnregisterAddin(klass):
    import _winreg
    try:
        _winreg.DeleteKey(_winreg.HKEY_CURRENT_USER, "Software\\Microsoft\\Office\\Word\\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)
4

0 回答 0