VSTO外接程序与VBA的联动尝试

前言

这几天玩VBA,
尝试XML绘制EXCEL主菜单,注入EXCEL,并调用VBA的函数。
众所周知VS的IDE是多强大,我就寻思能不能用C#画界面去控制VBA的插件。这样更新就能单xlam覆盖更新了。
然后开始学习VS的 VSTO外接程序,确实很有意思。

一、第一坑:安装offic2007后excel加载项找不到了

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
至于为什么使用2007,我寻思07上能跑的13、16不得兼任啊。我用13的开发,还得倒回来弄07、10的兼容不是。

二、示例1 通过Ribbon XML自定义Excel主菜单并添加新项

步骤1:创建Ribbon XML定义文件
新建一个XML文件(如customUI.xml),定义以下结构

<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
  <ribbon>
    <tabs>
      <tab id="CustomTab" label="我的工具">
        <group id="CustomGroup" label="数据处理">
          <button 
            id="btnCleanData" 
            label="数据清洗" 
            size="large" 
            onAction="DataCleaningMacro"
            imageMso="DataRefreshAll" />
          <menu id="mnuAdvanced" label="高级操作" imageMso="GroupEdit">
            <button id="btnMerge" label="合并工作表" onAction="MergeSheetsMacro"/>
            <button id="btnSplit" label="拆分数据" onAction="SplitDataMacro"/>
          </menu>
        </group>
      </tab>
    </tabs>
  </ribbon>
</customUI>

关键参数说明:
imageMso:使用Office内置图标(如DataRefreshAll代表刷新图标)3
onAction:绑定VBA回调函数

步骤2:将XML集成到Excel文件
将Excel文件后缀改为.zip
在压缩包内创建路径:customUI/_rels
将customUI.xml放入customUI文件夹
创建关系文件customUI/_rels/customUI.xml.rels:

<?xml version="1.0" encoding="UTF-8"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
  <Relationship Type="http://schemas.microsoft.com/office/2006/relationships/ui/extensibility" 
               Target="/customUI/customUI.xml" 
               Id="RibbonCustomization" />
</Relationships>

步骤3:编写VBA回调函数
在Excel的VBA编辑器中添加模块(需启用宏):

' 按钮点击事件处理
Sub DataCleaningMacro(control As IRibbonControl)
    MsgBox "执行数据清洗操作", vbInformation
    ' 实际功能代码
End Sub

Sub MergeSheetsMacro(control As IRibbonControl)
    MsgBox "执行工作表合并", vbInformation
End Sub

步骤4:验证与调试
通过Custom UI Editor工具直接注入XML(推荐)
使用IRibbonUI.Invalidate方法刷新界面:

Dim MyRibbon As IRibbonUI

Sub ribbonLoaded(ribbon As IRibbonUI)
    Set MyRibbon = ribbon
End Sub

Sub RefreshRibbon()
    MyRibbon.Invalidate
End Sub

二、示例1 总结

这个示例过于复杂,而且卡在第四步,我觉得应该寻找更好、更简单的办法。

三、示例2 创建VSTO外接程序

步骤1:新建解决方案和Excel VSTO 外接程序项目

创建一个Excel VSTO外接程序的新项目,选择“Excel VSTO外接程序(Visual Basic)”模板,命名为“外接程序安装”。VS将显示解决方案名称为“外接程序安装”,包含“外接程序安装”项目。

步骤2:设计Excel VSTO外接程序

主要是设计菜单项和代码。

1.在“外接程序安装”项目上,点击右键,选择“添加”——“类”,在“添加新项-外接程序安装”界面,选择“office/sharepoint”中的“功能区(可视化设计器)”,点击“添加”后默认建立“Ribbon1.vb”的模块。

2.依次右键点击“Group1”、“TabAddins(内置)”,均选择“ 删除”。

(1)点击左侧的“工具箱”,拖拽“Office 功能区控件”中的Tab按钮到“Ribbon1.vb[设计]”中,修改右侧属性的有关值,如Label改为“关于”等。

(2)再次点击左侧的“工具箱”,拖拽“Office 功能区控件”中的Group按钮到“Ribbon1.vb[设计]”的“关于”里面,修改右侧属性的有关值,如Label改为“帮助”等。

(3)点击左侧的“工具箱”,拖拽“Office 功能区控件”中的Group按钮到“Ribbon1.vb[设计]”中的帮助里面,修改右侧属性的有关值,如Label改为“版本”,ControlSize改为“RibbonControlSizeLarge”,OfficeImageId改为“Help”等。

3.双击“版本”图标,进入“Ribbon1.vb”的代码编辑界面,在Button1_Click的过程中,输入以下代码

MsgBox(“version 1.0.0.0”)

引用资料: 创建 VSTO 外接程序的windows安装包
https://blog.csdn.net/weixin_45661908/article/details/123310069

三、示例2 总结

跟着做了一遍,在第二条:MsgBox(“version 1.0.0.0”) 这里卡住了。
思路了半天,反应过来,他是用的VB,而我用的C#。 尴尬了
在这里插入图片描述
嗯 最终跟着做完,挺详细、简单的,安装那部分不用过分深入,了解就行。主要是熟悉外接程序的搭建。

四、示例 3 C# VSTO外接程序示例

步骤1:创建一个Excel外接程序:
在这里插入图片描述

步骤2:添加项,添加一个Ribbon菜单:
在这里插入图片描述

步骤3 : 熟悉Tab控件

在这里插入图片描述
在这里插入图片描述
RibbonTab控件是所有控件的容器

步骤4: 熟悉Group控件

Group控件的作用是将我们的功能进行分组。回到我们之前的规划,我们的歪歪插件有财经,地图,天气,关于这几大功能。所以我们需要在界面上放置4个Group控件,并对其进行命名。

在这里插入图片描述

步骤5 :Menu控件和SpliterButton控件

在分好类之后,我们需要对每个分类的细小功能进行设计,这里面我们需要放置各种控件,首先我们可能会接触到的就是Menu控件,里面可以包含Button,SplitButton等。
在这里插入图片描述

步骤6:RibbonXml
在Office中Ribbon菜单时可以通过RibbonXML进行配置,也就是说,上面的可视化界面设计其实是为我们提供了编辑RibbonXML的设计时支持。其实我们也可以直接创建一个XML文件进行设计,然后在代码中进行加载,同样能够实现这样的功能。在有些情况下,比如我们创建SharedAddin程序时,根本没有设计时支持。所以了解RibbonXML对于创建可兼容多版本Excel菜单系统显得尤为重要。

要创建RibbonXML最好的做法是对着新建的可视化菜单,然后右键->将功能区导出到XML。然后项目会自动创建Ribbon.xml和Ribbon.cs文件,其中Ribbon.xml是布局文件,Ribbon.cs是事件处理代码。
在这里插入图片描述

打开Ribbon.xml可以看到如下代码,可以看到这个UI界面的展现即是使用了该XML文件来进行渲染的,其中在XML中还可以声明一些事件,后面会讲。
在这里插入图片描述

现在,如何在我们的应用程序中加载该RibbonXML并渲染出Ribbon菜单呢?首先,我们将之前的添加的可视化设计的Ribbon菜单YYMenu.cs排除到项目外。然后转到ThisAddIn.cs中,覆写Office.IRibbonExtensibility 接口的CreateRibbonExtensibilityObject方法,实例化自动生成的Ribbon类,然后返回。

//ThisAddIn.cs
private Ribbon customerRibbon;

protected override Office.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
    customerRibbon = new Ribbon();
    return customerRibbon;
}

运行程序,即可看到如下效果:

在这里插入图片描述

可以看到图片不见了,这是因为在导出功能区为XML的时候,VS没有帮我们处理图片,所以需要我们自己来添加。在RibbonXML文档中, customUI节点下有loadImage事件,Button有getImage事件和image属性。customUI节点的loadImage方法和子节点的image属性一起使用,image属性作为loadImage方法的参数。

在这里插入图片描述
loadImage方法如下:

//Ribbon.cs
public Image LoadImage(string imageName)
{
    Assembly assembly = Assembly.GetExecutingAssembly();
    //String[] all =assembly.GetManifestResourceNames();//GetResourceName
    Stream stream = assembly.GetManifestResourceStream("YYAddIn.Resources." + imageName);
    return Image.FromStream(stream);
}

其中,imageName即为Button控件的image属性要设置的图片名称。资源文件图片,要设置为嵌入的资源。

引用资料: 浅谈Excel开发:二 Excel 菜单系统
https://blog.csdn.net/dyllove98/article/details/9707613

四、示例 3 总结

示例3是最符合我需求的测试,它为我初衷‘便捷的调用VBA 创造了可能’。当然也遇到一些问题。

问题1:老是被EXCEL 的加载项禁用,需要手动解除。不然就尴尬了
在这里插入图片描述
在这里插入图片描述
问题2:步骤6,图片出不来,忘记设置本地资源属性设置造成的。

在这里插入图片描述
在这里插入图片描述

五、实现C# 的VSTO调用VBA函数(xlam)

C#调用VBA(xlam)的代码我会放文末。不管作用大小,好歹是个思路。主要代码如下。

步骤1:添加一个测试项目 test2,做界面就是group里加个button,然后生成XML

步骤2:我的测试界面生成的XML
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<customUI onLoad="Ribbon_Load" xmlns="http://schemas.microsoft.com/office/2006/01/customui"  loadImage="LoadImage">
    <ribbon>
        <tabs>
            <tab id="tab1" label="mytest2">
                <group id="group1" label="group1">
                    <button id="button1" label="button1" size="large"   image="exlLogo.jpg"  onAction="testdo1" />
                </group>
            </tab>
        </tabs>
    </ribbon>
</customUI>

XML 中加入LoadImage、testdo1 ,LoadImage加载图片、testdo1是我想调用的xlam函数。

步骤3: 项目中排除界面文件Ribbon1.cs,
ThisAddIn.cs 中添加 启用XML生成

private Ribbon customerRibbon;

protected override Office.IRibbonExtensibility CreateRibbonExtensibilityObject()
{
   customerRibbon = new Ribbon();
   return customerRibbon;
}

步骤4:Ribbon.cs写入 本地图片加载

public Image LoadImage(string imageName) 
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            //String[] all = assembly.GetManifestResourceNames();//GetResourceName
            //return null;
            Stream stream = assembly.GetManifestResourceStream("test2.Resources." + imageName);
            return Image.FromStream(stream);
            
        }

步骤5:建一个测试VBA 函数 并保存为 ‘我的测试.xlam’
在这里插入图片描述
在这里插入图片描述
不需要添加到excel加载项,因为这样外接程序也读取不到,我测试过了。

步骤6:修改按钮事件响应

将Ribbon.cs 的 GetCustomUI 用下面代码覆盖掉

 Microsoft.Office.Interop.Excel.Application excelApp = null;
 public string GetCustomUI(string ribbonID)
        {
            excelApp = Globals.ThisAddIn.Application;
            // 加载xlam文件(若未自动加载)
            excelApp.Workbooks.Open(@"C:\Users\cs\Desktop\我的测试.xlam", ReadOnly: true);
            
            return GetResourceText("test2.Ribbon.xml");
           
        }
 public void testdo1(Office.IRibbonControl control)
        {
            excelApp.Run("我的测试.xlam!模块1.testdo1");
            /*
            // 方式2:传递参数调用
            object arg1 = "参数1";
            object arg2 = 100;
            excelApp.Run("MyMacro.xlam!Module1.ProcessData", arg1, arg2);

            // 方式3:使用动态类型(需引用Microsoft.CSharp)
            dynamic excel = excelApp;
            excel.Run("MyMacro.xlam!Module1.AdvancedCalc", 15.5, DateTime.Now);
             */
              /* try
            {
                if (control.Id.Equals("btntest"))
                {
                }
            }
            catch (COMException ex)
            {
                Console.WriteLine("Create CTP encounter errors: " + ex.ToString());
            }
            */
        }

运行效果:
在这里插入图片描述

六、结语

1、最终,贴一下本文的测试代码下载
C# 的VSTO调用VBA函数(xlam)示例代码
https://download.csdn.net/download/yqsy123123/90724022

我也不知道直接更新覆盖VBA的文件夹、和写一个自动更新的程序哪个更复杂,主要是想到了看能不能实现,还是挺有意思的

2、至于,写好的VSTO如何注入EXCEL,那就得参考示例2 的安装部分了。
创建 VSTO 外接程序的windows安装包
https://blog.csdn.net/weixin_45661908/article/details/123310069

3、标记一个EXCEL内置图标的,
兼容Office和WPS中Word图标库
https://blog.csdn.net/weixin_45055317/article/details/133832128

你们有可以预览的图标库地址,分享一个,万分感谢。

再次感谢本文引用资源的作者。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值