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

文章目录

  • 前言
  • 一、第一坑:安装offic2007后excel加载项找不到了
  • 二、示例1 通过Ribbon XML自定义Excel主菜单并添加新项
  • 二、示例1 总结
  • 三、示例2 创建VSTO外接程序
  • 三、示例2 总结
  • 四、示例 3 C# VSTO外接程序示例
  • 四、示例 3 总结
  • 五、实现C# 的VSTO调用VBA函数(xlam)
  • 六、结语

前言

这几天玩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 SubSub MergeSheetsMacro(control As IRibbonControl)MsgBox "执行工作表合并", vbInformation
End Sub

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

Dim MyRibbon As IRibbonUISub ribbonLoaded(ribbon As IRibbonUI)Set MyRibbon = ribbon
End SubSub 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();//GetResourceNameStream 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
你们有可以预览的图标库地址,分享一个,万分感谢。

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/79864.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DeepSeek驱动的金市情绪量化:NLP解析贸易政策文本的情绪传导路径

【AI观察】政策信号与市场情绪的量化关联 基于自然语言处理技术对全球财经文本的情绪分析显示&#xff0c;4月30日亚盘时段现货黄金价格波动率较前日下降12.3%&#xff0c;与技术面修正指标呈现强相关性。特政府最新关税政策调整引发市场风险偏好指数&#xff08;RPI&#xff…

期末代码Python

以下是 学生信息管理系统 的简化版代码示例&#xff08;控制台版本&#xff0c;使用文件存储数据&#xff09;&#xff0c;包含核心功能&#xff1a; 1. 定义学生类 class Student: def __init__(self, sid, name, score): self.sid sid # 学号 self.name name # 姓名 self.s…

zotero pdf中英翻译插件使用

最近发现一个pdf中英翻译的神器zotero-pdf2zh&#xff0c;按照官方安装教程走一遍的时候&#xff0c;发现一些流程不清楚的问题&#xff0c; 此文就是整理一些安装需要的文件以及遇到的问题&#xff1a; 相关文件下载地址 Zotero 是一款免费的、开源的文献管理工具&#xff0…

本地MySQL连接hive

1、首先需要修改MySQL的配置&#xff0c;允许远程连接&#xff1a; # 在本地MySQL服务器上执行 sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf找到 bind-address 行&#xff0c;将其修改为&#xff1a; bind-address 0.0.0.02、在本地MySQL中创建用户并授权&#xff08;注意…

Nginx核心功能2

一&#xff1a;正向代理 正向代理&#xff08;Forward Proxy)是一种位于客户端和原始服务器之间的代理服务器&#xff0c;其主要作用是将客户端的请求转发给目标服务器&#xff0c;并将响应返回给客户端Nginx的正向代理充当客户端的“中间人”&#xff0c;代表用户访问外部资源…

高定电视,一场关于生活方式的觉醒

需要有自己的工作室&#xff0c;雇用3个以上专职模特&#xff0c;至少15名全职员工和20名技术工匠‌&#xff1b; 每年都要参加巴黎高级时装周&#xff0c;展示至少50款原创设计&#xff1b; 使用的面料必须高质量、昂贵且不同寻常&#xff0c;设计上注重细节和个性&#x…

用PyTorch搭建卷积神经网络实现MNIST手写数字识别

用PyTorch搭建卷积神经网络实现MNIST手写数字识别 在深度学习领域&#xff0c;卷积神经网络&#xff08;Convolutional Neural Network&#xff0c;简称CNN&#xff09;是处理图像数据的强大工具。它通过卷积层、池化层和全连接层等组件&#xff0c;自动提取图像特征&#xff…

Tensorrt 基础入门

什么是tensorrt? 其他厂商: Qualcomm, Hailo, google TPU tensorrt的优劣势 使用tensorrt的pipeline tensorrt使用中存在的问题以及解决方案 tensorrt的应用场景 自动驾驶模型部署需要关注的问题&#xff1a; 边端硬件资源有限 散热&#xff08;不能水冷&#xff09; 实时性&…

Qt 显示QRegExp 和 QtXml 不存在问题

QRegExp 和 QtXml 问题 在Qt6 中 已被弃用&#xff1b; 1&#xff09;QRegExp 已被弃用&#xff0c;改用 QRegularExpression Qt5 → Qt6 重大变更&#xff1a;QRegExp 被移到了 Qt5Compat 模块&#xff0c;默认不在 Qt6 核心模块中。 错误类型解决方法QRegExp 找不到改用 Q…

玩玩OCR

一、Tesseract: 1.下载windows版&#xff1a; tesseract 2. 安装并记下路径&#xff0c;等会要填 3.保存.py文件 import pytesseract from PIL import Image def ocr_local_image(image_path):try:pytesseract.pytesseract.tesseract_cmd rD:\Programs\Tesseract-OCR\tesse…

Dify 完全指南(一):从零搭建开源大模型应用平台(Ollama/VLLM本地模型接入实战)》

文章目录 1. 相关资源2. 核心特性3. 安装与使用&#xff08;Docker Compose 部署&#xff09;3.1 部署Dify3.2 更新Dify3.3 重启Dify3.4 访问Dify 4. 接入本地模型4.1 接入 Ollama 本地模型4.1.1 步骤4.1.2 常见问题 4.2 接入 Vllm 本地模型 5. 进阶应用场景6. 总结 1. 相关资源…

C++ Windows 打包exe运行方案(cmake)

文章目录 背景动态库梳理打包方案一、使用 Vcpkg 安装静态库&#xff08;关键基础配置&#xff09;1. 初始化 Vcpkg2. 安装静态库&#xff08;注意 x64-windows-static 后缀&#xff09; 二、CMakeLists.txt 关键配置三、编译四、验证 不同平台代码兼容\_\_attribute\_\_((pack…

Java学习手册:Hibernate/JPA 使用指南

一、Hibernate 和 JPA 的核心概念 实体&#xff08;Entity&#xff09; &#xff1a;实体是 JPA 中用于表示数据库表的 Java 对象。通过在实体类上添加 Entity 注解&#xff0c;JPA 可以将实体类映射到数据库表。例如&#xff0c;定义一个 User 实体类&#xff1a; import ja…

字符串匹配 之 拓展 KMP算法(Z算法)

文章目录 习题2223.构造字符串的总得分和3031.将单词恢复初始状态所需的最短时间 II 灵神代码模版 区别与KMP算法 KMP算法可用于求解在线性时间复杂度0(n)内求解模式串p在主串s中匹配的未知当然&#xff0c;由于在KMP算法中&#xff0c;预处理求解出了next数组&#xff0c;也就…

安全为上,在系统威胁建模中使用量化分析

*注&#xff1a;Open FAIR™ 知识体系是一种开放和独立的信息风险分析方法。它为理解、分析和度量信息风险提供了分类和方法。Open FAIR作为领先的风险分析方法论&#xff0c;已得到越来越多的大型组织认可。 在数字化风险与日俱增的今天&#xff0c;企业安全决策正面临双重挑战…

游戏引擎学习第259天:OpenGL和软件渲染器清理

回顾并为今天的内容做好铺垫 今天&#xff0c;我们将对游戏的分析器进行升级。在之前的修复中&#xff0c;我们解决了分析器的一些敏感问题&#xff0c;例如它无法跨代码重新加载进行分析&#xff0c;以及一些复杂的小问题。现在&#xff0c;我们的分析器看起来已经很稳定了。…

讯睿CMS模版常用标签参数汇总

一、模板调用标签 1、首页 网站名称&#xff1a;{SITE_NAME} 标题&#xff1a;{$meta_title}&#xff08;列表页通用&#xff09; Keywords&#xff1a;{$meta_keywords} Description&#xff1a;{$meta_description}2、列表页 迅睿cms调用本栏目基础信息标签代码 当前栏目…

【C#】Buffer.BlockCopy的使用

Buffer.BlockCopy 是 C# 中的一个方法&#xff0c;用于在数组之间高效地复制字节块。它主要用于操作字节数组&#xff08;byte[]&#xff09;&#xff0c;但也可以用于其他类型的数组&#xff0c;因为它直接基于内存操作。 以下是关于 Buffer.BlockCopy 的详细说明和使用示例&…

记一次pdf转Word的技术经历

一、发现问题 前几天在打开一个pdf文件时&#xff0c;遇到了一些问题&#xff0c;在Win10下使用WPS PDF、万兴PDF、Adobe Acrobat、Chrome浏览器打开都是正常显示的&#xff1b;但是在macOS 10.13中使用系统自带的预览程序和Chrome浏览器&#xff08;由于macOS版本比较老了&am…

在Laravel 12中实现4A日志审计

以下是在Laravel 12中实现4A&#xff08;认证、授权、账户管理、审计&#xff09;日志审计并将日志存储到MongoDB的完整方案&#xff08;包含性能优化和安全增强措施&#xff09;&#xff1a; 一、环境配置 安装MongoDB扩展包 composer require jenssegers/mongodb配置.env …