ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 47884|回复: 94

[分享] 【少同叨叨叨】COM加载项制作过程及代码全解析,有难不求人,求人不入心!

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2015-5-20 08:53 | 显示全部楼层 |阅读模式
本帖已被收录到知识树中,索引项:插件开发
本帖最后由 心电感应 于 2015-9-2 21:38 编辑
一、缘何而萌生COM开发
最近有一个开发项目,陆陆续续开发了三三两两也见一些成果了,开发形式是选项卡形式的,最初我采用的依然是我运用比较成熟的RibbonX方法开发,其实我个人认为这个方法是非常好的,因为这个方法比较易学容易上手,而且这个里面的控件也是特别丰富的,做出来界面比较漂亮,适合大部分人学习。这个我认为最主要还是customUI.xml文件的编辑问题,其次当然是写回调的代码。对于这个的学习得益于论坛一篇叫做“细品RibbonX”的帖子。其中一个Word文档就叫"细品RibbonX.doc",读完这篇Word感觉受益匪浅。不多说,相信论坛里很多人都已经掌握这个,我也不再班门弄斧,还没掌握又想学的,可以拿来一读。
链接:细品RibbonX
当我把我允诺要完成的开发内容完成之后,每次打开我开发的最终选项卡文件"*.xlam"加载项格式的,只要打开VBE编辑器就可以看到我的这个工程,而且有人曾当我面破解过我写的VBA程序,所以我心里一直有这个心结。于是,突然之间萌生了一个想法:要写一个dll加载项封装我的代码,这个想法让我为之连续两周熬夜通宵,早上三点半起来写到六点洗脸上班...当然这些只是过程之中,我是干设计行业的,做我们这行的领导经常有一句话就是不看过程,只重结果。还好现在结果还算不错,我心里也觉得舒服很多。(PS:可能某些大神会觉得我不就是会点东西,至于这个样子吗...其实不然的,人总是会进步的,我也有虚荣心,当我进步的时候我也会短暂开心一下再整装待发。所以请大神们不要见怪了。)下面这两篇文章每一篇我都着手去做了尝试,而且最终结果也很成功。非常推荐这两篇优秀的文章。

                                         二、着手开发(这篇非常重要,想学的必须动手一起来做)
  
  着手开发第一件事情当然就是上我们亲爱的EH论坛打开搜索按钮输入"VB开发选项卡"、"VB开发加载项"等等,可是我明明记得论坛里是有关于这样的帖子的,终于被我发现了几篇关于COM加载项开发的,一篇叫"VB6.0制作Excel2010功能区COM加载项及自定义图标"的帖子终于被我想尽各种关键词搜出来了,我不太懂论坛外是不是有人可以用这个帖子里的方法去开发COM加载项,但是我认为这个篇文章在EH里面为COM功能区开发这方面奠定了基础,是一篇非常好的COM加载项开发入门试炼(以上纯属个人见解,如原作者有不同看法在本帖回帖即可(*^__^*) ……)。
  
  为何我个人认为是入门试炼?其实看看帖子里面图文并茂连代码你只需要粘贴复制一下就可以实现功能区开发,这当然太适合初学者做试炼教材了。下面咱们简单对这个几个操作步骤说明一下,跟我一起动手做起来吧。
  
  在做这个之前,我个人把COM加载项开发分为了以下几个步骤,此篇也是按如下步骤来分解进行:
  
       1、基本程序设置
  
       2、功能区界面的实现
  
       3、一个简单的回调Action
  
       4、一个稍高级回调Action封装示例
  
       5、一篇完整我的开发项目封装示例
  
  



补充内容 (2015-6-28 20:01):
感兴趣的加QQ群交流:397245435

评分

14

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-5-20 09:21 | 显示全部楼层
首先我们从"1、基本程序设置"开始


  做这个COM封装,我用的是VB企业版+Office2010开发(个人认为Office版本不必太纠结前期学习,改一下引用即可)。首先打开VB:
   VB选择外接程序.jpg

看上图,我们选择外接程序, 刚进入VB.jpg VB会自动创建两个对象,一个是窗体对象,这个我们删掉即可;另外一个是Connect,这时我们双击他会弹出下面这个界面:
设计器界面.jpg

这里不再重复的谈了,如图一样选择,如果你是Office2007那么应用程序版本就是Microsoft Excel12.0,如果你是Office2015那这里就是Microsoft Excel15.0。设置好之后我们右键 右键.jpg 选择查看代码之后把里面的代码全部清除,这里有重点哦~~请认真听讲初学的同志们...首先我们来看一下我上面第一篇链接里面提到的代码:

  1. '添加 XML 自定义代码
  2. Public Function GetRibbonXML() As String
  3.     Dim sRibbonXML As String
  4.     sRibbonXML = "<customUI xmlns=""http://schemas.microsoft.com/office/2006/01/customui"" >" & _
  5.                   "<ribbon startFromScratch=""false"">" & _
  6.                    "<tabs>" & _
  7.                     "<tab id=""henrylam"" label=""我的工具"">" & _
  8.                      "<group id=""test"" label=""测试"">" & _
  9.                       "<button id=""Button1"" label=""测试内置图标"" size=""large"" imageMso=""HappyFace"" onAction=""test1"" />" & _
  10.                       "<button id=""Button2"" label=""测试自定义图标"" size=""large"" getImage=""GetImage"" onAction=""test2"" />" & _
  11.                      "</group >" & _
  12.                      "<group id=""ExcelHome"" label=""ExcelHome"">" & _
  13.                       "<button id=""Button3"" label=""访问论坛"" size=""large"" getImage=""GetImage"" onAction=""test3"" />" & _
  14.                      "</group >" & _
  15.                     "</tab>" & _
  16.                    "</tabs>" & _
  17.                   "</ribbon>" & _
  18.                  "</customUI>"
  19.     GetRibbonXML = sRibbonXML
  20.    End Function
复制代码
我们可以看一下这里关于XML功能区定义的这个函数,别看他这么长其实他就是一行代码,都是用"-"连接符连接的,我们都知道VB里面每行代码的字符长度是有限制的,那么问题来了,当我们封装的XML功能区非常多的时候相应的XML文本也会多,这时候去封装就会提示字符过长限制。对于这个问题有朋友在此帖中也有反馈,其中76楼雅林源居提到了他的解决办法:

这个简单用解决
sRibbonXML=sRibbonXML&"",后面的&_删除
即可代替&_
其实我是没有去用这个办法尝试的,这里解释一下为什么我没有用这个办法尝试,因为我发现这个问题之后就放弃这种办法开始寻求其他方式解决问题,当找到有其他办法可以解决问题的时候才发现雅林源居在76楼的这个回复。接下楼,分解一下我找到的解决办法...

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2015-5-20 09:32 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
不错,继续

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-5-20 10:17 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
  当我发现这个问题之后又开启了我的论坛搜索之路,最终结果是没有找到解决办法(PS:可能是我搜索关键词不对路),于是我开始使用百度搜索尝试看看有没有其他的人做过这个东西的,终于被我搜索到了一篇关于另外一种封装XML功能区的办法,这个缩缩关键词我已经忘记了,但是这个东西就是咱们论坛里的人做的,这个人就是佛山小老鼠我不禁开始对佛版产生了极大的感谢之情。下面的本人的言论不单单对网上已有教程的粘贴复制,我要表达的是一种对于遇到问题我们寻求解决办法的一种思路还有精神,请之前我引用过所有作者代码以及以下引用过的代码原创作者知悉。
  接着上回说,我们依然把Conect里面所有的代码删掉,然后下面的代码是佛版原封不动的封装代码,请允许我先沾过来我们一起来分析分析:
  1. Implements IDTExtensibility2
  2. Implements IRibbonExtensibility
  3. Public xlapp As Excel.Application
  4. Private Function IRibbonExtensibility_GetCustomUI(ByVal RibbonID As String) As String
  5.     IRibbonExtensibility_GetCustomUI = LoadResString(101)
  6.     '用于从资源文件中载入自定义功能区的xml代码
  7. End Function

  8. Private Sub IDTExtensibility2_OnConnection(ByVal Application As Object, ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, ByVal AddInInst As Object, custom() As Variant)
  9.     Set xlapp = Application '将xlapp赋值为Excel程序
  10. End Sub

  11. Private Sub IDTExtensibility2_OnDisconnection(ByVal RemoveMode As AddInDesignerObjects.ext_DisconnectMode, custom() As Variant)
  12. End Sub
  13. Private Sub IDTExtensibility2_OnAddInsUpdate(custom() As Variant)
  14. End Sub
  15. Private Sub IDTExtensibility2_OnBeginShutdown(custom() As Variant)
  16. End Sub
  17. Private Sub IDTExtensibility2_OnStartupComplete(custom() As Variant)
  18. End Sub
  19. Private Sub IDTExtensibility_OnStartupComplete(custom() As Variant)
  20. End Sub


  21. Public Sub 完美(ByVal control As IRibbonControl)
  22.     Test1
  23. End Sub
  24. Public Sub 视频(ByVal control As IRibbonControl)
  25.     Test2
  26. End Sub
  27. Public Sub EH(ByVal control As IRibbonControl)
  28.     Test3
  29. End Sub

  30. Public Sub 解密(ByVal control As IRibbonControl)
  31.     Test4
  32. End Sub

  33. Public Sub 工作表加密(ByVal control As IRibbonControl)
  34.     Test5
  35. End Sub

  36. Sub Test1()
  37. '完美
  38.     xlapp.ActiveWorkbook.FollowHyperlink _
  39.       Address:="http://www.excelbbs.com/forum.php", _
  40.       NewWindow:=True
  41. End Sub
  42. Sub Test2()
  43. '视频
  44.     xlapp.ActiveWorkbook.FollowHyperlink _
  45.       Address:="http://www.56.com/h48/uv.index.php?user=caomingwumr", _
  46.       NewWindow:=True
  47. End Sub
  48. Sub Test3()
  49. 'EH
  50.     xlapp.ActiveWorkbook.FollowHyperlink _
  51.       Address:="http://club.excelhome.net/", _
  52.       NewWindow:=True
  53. End Sub

  54. Sub Test4()
  55. '解密  备注这个代码是采集EH论坛一个前辈的的
  56. With xlapp
  57.     .ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:=True _
  58.         , AllowFiltering:=True, AllowUsingPivotTables:=True
  59.     .ActiveSheet.Protect DrawingObjects:=False, Contents:=True, Scenarios:= _
  60.         False, AllowFiltering:=True, AllowUsingPivotTables:=True
  61.     .ActiveSheet.Protect DrawingObjects:=True, Contents:=True, Scenarios:= _
  62.         False, AllowFiltering:=True, AllowUsingPivotTables:=True
  63.     .ActiveSheet.Protect DrawingObjects:=False, Contents:=True, Scenarios:= _
  64.         True, AllowFiltering:=True, AllowUsingPivotTables:=True
  65.     .ActiveSheet.UnProtect
  66.     ANS = MsgBox("密码已破解", 48, "佛山小老鼠制作")
  67. End With
  68. End Sub

  69. Sub Test5()
  70.   '工作表加密()
  71.   Dim I As Integer
  72.   For I = 1 To xlapp.Sheets.Count
  73.       xlapp.Sheets(I).Protect Password:="197698"
  74.   Next I
  75. End Sub
复制代码
  我们统观以上代码,发现并没有任何关于XML对功能区定义的字眼,这个要卖个关子下贴分解...首先对比佛版的这个代码与我提到连接里的代码有何不同,我个人认为最主要的是“Implements IDTExtensibility2”,IDTExtensibility2这到底是个什么东东呢?我不解,但是我会用百度。我们直接以“IDTExtensibility2”这个作为关键词老百度搜索一下看看百度里对这个东西有没有讲义,其中有一篇这个文章WPS COM加载项制作连载教程3——详解IDTExtensibility2接口这个文章对于此东东进行了详细的讲解,我们简单对这个东西进行一下学习为一会儿继续我们的封装工作做些准备:
IDTExtensibility2有五个方法成员,也即事件,分别是:
                                                 1、OnConnection
                                                 2、OnDisconnection
                                                 3、OnStartupComplete
                                                 4、OnAddInsUpdate
                                                 5、OnBeginShutdown
我们来看一下那篇文章对这个五个方法成员的讲解:
1.OnConnection 事件
OnConnection 事件在 COM 加载项加载(连接)时发生。可以在OnConnection 事件中实现对WPS的操作,其中使用加载项有以下几种方式:  
当应用程序启动时加载;
用户在“COM 加载项”对话框中加载加载项;
在发布的时候,注册表的LoadBehavior键值表示加载行为,通常是3(启动时加载)。如果想让用户在“COM 加载项”对话框中加载加载项的话键值是8。
2.OnDisconnection 事件
OnDisconnection 事件在卸载 COM 加载项时发生。可以使用 OnDisconnection 事件过程运行能够恢复由加载项对应用程序所作任何更改的代码,或者执行常规清除操作。
卸载加载项和加载行为有对应的几种方式:
用户清除“COM 加载项”对话框中加载项旁边的复选框。
WPS程序关闭时卸载。如果加载项的加载行为设置为“启动”,则WPS 程序再次启动时,就会重新加载加载项。
3.OnStartupComplete 事件
当WPS程序完成启动例程时,就会发生 OnStartupComplete 事件。事件只在“启动时加载COM加载项”的加载行为下发生。如果此事件确实发生,则它将在 OnConnection 事件之后发生。
可以使用 OnStartupComplete 事件与应用程序交互、且在应用程序完成加载后才应运行的代码。例如,如果要显示一个使用户选择在启动WPS文字程序时选择公文模板的窗体,可以将该代码放到 OnStartupComplete 事件过程中。
4.OnBeginShutdown 事件


在WPS程序关闭而 COM 加载项仍处于加载状态的情况下,如果WPS程序开始其关闭例程时就会发生 OnBeginShutdown 事件。如果此事件确实发生,它将在 OnDisconnection 事件之前发生。
用户关闭WPS程序时,可以使用 OnBeginShutdown 事件过程运行代码。例如,可以运行将窗体数据保存到某个文件的代码。
5.OnAddInsUpdate 事件
当一组已加载的 COM 加载项发生更改时,就会发生 OnAddInsUpdate 事件。当某个加载项加载或卸载时,就会在任何其它已加载的加载项中发生 OnAddInsUpdate 事件。例如,如果加载项 A 和 B 当前已加载,然后将加载加载项 C,则 OnAddInsUpdate 事件就会在加载项 A 和 B 中发生。如果 C 已卸载,则加载项 A 和 B 中再次发生 OnAddInsUpdate 事件。

其第一个成员"OnConnection",这个是我此次COM封装中非常重要一个中坚力量,稍后下帖我们会在第一个简单封装示例中对其的应用进行详解。(由于在上班ing...所以发帖速度可能会慢,想学的朋友需静候花开,哈哈(*^__^*)……)

TA的精华主题

TA的得分主题

发表于 2015-5-20 10:30 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
感谢分享,静候花开。

TA的精华主题

TA的得分主题

发表于 2015-5-20 13:03 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-5-20 13:06 | 显示全部楼层
2、功能区界面的实现
接下来我们开始先把封装功能区界面实现,讲Conect里面的代码全部删除之后将下面的代码粘到里面:
  1. Implements IDTExtensibility2
  2. Implements IRibbonExtensibility
  3. Public xlapp As Excel.Application
  4. Private Function IRibbonExtensibility_GetCustomUI(ByVal RibbonID As String) As String
  5.     IRibbonExtensibility_GetCustomUI = LoadResString(101)
  6.     '用于从资源文件中载入自定义功能区的xml代码
  7. End Function

  8. Private Sub IDTExtensibility2_OnConnection(ByVal Application As Object, ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, ByVal AddInInst As Object, custom() As Variant)
  9.     Set xlapp = Application '将xlapp赋值为Excel程序
  10. End Sub

  11. Private Sub IDTExtensibility2_OnDisconnection(ByVal RemoveMode As AddInDesignerObjects.ext_DisconnectMode, custom() As Variant)
  12. End Sub
  13. Private Sub IDTExtensibility2_OnAddInsUpdate(custom() As Variant)
  14. End Sub
  15. Private Sub IDTExtensibility2_OnBeginShutdown(custom() As Variant)
  16. End Sub
  17. Private Sub IDTExtensibility2_OnStartupComplete(custom() As Variant)
  18. End Sub
  19. Private Sub IDTExtensibility_OnStartupComplete(custom() As Variant)
  20. End Sub
复制代码
这里要注意一下这几行代码:
  1. Private Function IRibbonExtensibility_GetCustomUI(ByVal RibbonID As String) As String
  2. IRibbonExtensibility_GetCustomUI = LoadResString(101)
  3. '用于从资源文件中载入自定义功能区的xml代码
  4. End Function
复制代码
里面的注释解释了用于从资源文件载入自定义的XML代码,这个就是解决链接帖里面VB单行字符限制太长的关键之处,下面请跟上我的步伐一起来设置一下你的VB
先单击VB菜单栏的 外接程序.jpg 然后选择外接程序管理器,讲下面这个VB 6 资源管理器的两个复选框全部选中:
资源管理器.jpg

工具.jpg 然后再点击菜单栏工具选项,选择资源管理器按下图进行操作:

ABC.jpg

点击那个abc的小按钮会弹出编辑字符串表这里显示101,双击后面的文本框会让你输入文本,这里我们可以输入自己的XML文本,这里总没有字符长度限制了吧?由此就解决掉了字符长度限制的问题。我这里以我自己以前写的一个Ribbon功能区选项卡的XML文件为例作为说明如下图:

Ztools选项卡.jpg

这个功能区完整的XML代码如下,你直接将其复制到101后面的文本框即可:


  1. 此处因为单帖字符长度限制,请各位下载我提供的XML文件自行复制哦~~
复制代码
添加引用.jpg

然后在工程-引用里面讲我圈出来的引用进去,然后我们就可以编译这个dll了,点击文件-生成MyAddIn,此时打开Excel选择COM加载项,然后添加你的这个dll看一下Excel里面是不是有了刚才那个选项卡呢?

到此呢,我们的这个驱壳是已经搞定了,可是他仅仅是一个行尸走肉,并没有代码回调,也就是还没有灵魂。然后我们来看一看IRibbonExtensibility_GetCustomUI = LoadResString(101)这个代码就容易理解多了他其实是101那输入XML文本的Load功能。下一帖我们来继续说代码的回调如何做,并将用演示一个简单回调程序代码的书写过程。


然后在工程-引用里面讲我圈出来的引用进去,然后我们就可以编译这个dll了,点击文件-生成MyAddIn,此时打开Excel选择COM加载项,然后添加你的这个dll看一下Excel里面是不是有了刚才那个选项卡呢?

到此呢,我们的这个驱壳是已经搞定了,可是他仅仅是一个行尸走肉,并没有代码回调,也就是还没有灵魂。然后我们来看一看IRibbonExtensibility_GetCustomUI = LoadResString(101)这个代码就容易理解多了他其实是101那输入XML文本的Load功能。下一帖我们来继续说代码的回调如何做,并将用演示一个简单回调程序代码的书写过程。

customUI.zip (2.67 KB, 下载次数: 490) 这里是XML文件


TA的精华主题

TA的得分主题

 楼主| 发表于 2015-5-20 13:10 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
带劲儿 发表于 2015-5-20 13:06
2、功能区界面的实现
接下来我们开始先把封装功能区界面实现,讲Conect里面的代码全部删除之后将下面的代 ...

最后两句话多粘了,请无视

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-5-20 13:13 | 显示全部楼层
带劲儿 发表于 2015-5-20 13:10
最后两句话多粘了,请无视

到这一步还没做出选项卡的朋友认真看帖子内容按步骤操作都没有问题的,不要再在帖子里发问为什么不行了,那只能证明你有步骤做的不对路

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-5-20 13:21 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
接下来我们对下面动画演示里的功能进行一个简单VB封装代码以及回调代码的说明,先看下面动画:
文件属性列表.gif

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-18 16:40 , Processed in 0.045198 second(s), 10 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表