ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

VSTO4.0类库制作EXCEL自定义函数

[复制链接]

TA的精华主题

TA的得分主题

发表于 2011-1-18 15:56 | 显示全部楼层 |阅读模式
本帖已被收录到知识树中,索引项:VSTO开发
       前段时间装了个visual studio 2010,试着用里面的VSTO4.0,但是对如何生成一个自定义函数始终搞不明白(之前也看了《VSTO开发指南》,但觉得里面所讲的东西太泛了,而且版本不一样,形式也改变了不少),终于在网上看到有人写出一个完整的过程(原文请看http://www.cnblogs.com/brooks-do ... /01/16/1936871.html),但在实操中还是遇到不少问题,但经过多次尝试,终于解决了这些困难,现在我就根据原文的内容以及建立过程中所遇到的问题,完整描述一个自定义函数的制作过程。

一、启动VS2010,(这里尝试着用C#来编写)新建一个类库,填好名称之后按确定,开始编码。


二、进入编程界面后,先引用必须的类库
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using Microsoft.Win32;

设置GUID及COM的一些特性
[Guid("A4AAE79B-9587-4014-BABB-966C5DF76C83")]
[ClassInterface(ClassInterfaceType.AutoDual),ComVisible(true)]
如图示:


Guid这个标识码可用LINQPad程序来获取(可从http://www.linqpad.net/下载)

在类中,除了有函数主体外,还必须有注册及注销时的行为语句,所以必须添加以下语句:
       #region COM Related
        [ComRegisterFunction]
        public static void RegisterFunction(Type type)
        {
            Registry.ClassesRoot.CreateSubKey(GetSubKeyName(type, "Programmable"));
            var key = Registry.ClassesRoot.OpenSubKey(GetSubKeyName(type, "InprocServer32"), true);
            key.SetValue("", Environment.SystemDirectory + @"\mscoree.dll", RegistryValueKind.String);
        }

        [ComUnregisterFunction]
        public static void UnregisterFunction(Type type)
        {
            Registry.ClassesRoot.DeleteSubKey(GetSubKeyName(type, "Programmable"), false);
        }

        private static string GetSubKeyName(Type type, string subKeyName)
        {
            var s = new System.Text.StringBuilder();
            s.Append(@"CLSID\{");
            s.Append(type.GUID.ToString().ToUpper());
            s.Append(@"}\");
            s.Append(subKeyName);
            return s.ToString();
        }
        #endregion
        如图示:


三、这些准备工作完毕后就可以写自己的函数主体了,这里以一个自定义的字符串联结为例:
        public string MyConcate(params Object[] values)
        {
            string iStr = "";
            Range iRng;
            for (int iStep = 0; iStep < values.Length; iStep++)
            {
                if (values[iStep].ToString() == "System.__ComObject")
                {
                    iRng = (Range)values[iStep];
                    if (iRng.Count > 1)
                    {
                        foreach(Range cRng in iRng)
                        {
                            iStr += Convert.ToString(cRng.Value);
                        }
                    }
                    else
                    {
                        iStr += Convert.ToString(iRng.Value);
                    }
                }
                else
                {
                    iStr += values[iStep].ToString();
                }
            }
            return iStr;
        }
        注:由于这里是用了params来传递不定数量的参数,所以需要把Object强制转换为Range类型,否则直接写iStr += values[iStep].ToString(); 只能获取到一个“System.__ComObject”字符串,由于需要强制转换,所以要加入另外一个引用 using Microsoft.Office.Interop.Excel;(此引用需事先在解决方案资源管理器那里添加,否则无法引用)

四、编写函数完毕,即可进行编译生成,在编译之前,有必要设置一些选项。
进入菜单栏-》项目-》(项目名称)属性


打开属性设置窗体,进入“生成”项

其中的“为COM互操作注册”,如果你的系统是WIN7,那就不要选择此项,你选择了的话,由于权限问题,在编译的时候就会出现错误,导致无法编译成功,但即使是在XP的情况下,编译成功了,但在加载的时候仍不能自动注册,导致加载不成功,不知道是不是VSTO4.0的缘故,所以这项如果选了的话就把它取消。

如果你想调试程序,那么就可以进入“调试”项,选择“启动外部程序”然后选择EXCEL程序作为函数调试的实体


设置好后就可以生成项目了。


五、注册加载DLL
注册与注销DLL需要一个regasm程序来完成,如果你装的是.NetFrameWork4.0,那么这个程序就在%windir%\Microsoft.NET\Framework\v4.0.30319文件夹下,我们打开CMD,进入此文件夹,如图示:


这里要注意的一点是,如果你的系统是Win7或Vista,那么你运行CMD时必须是以管理员的身份运行,否则的话会因为权限问题,在注册时无法向注册表写入数据导致注册不成功。


进入文件夹后,输入注册语句为DLL进行注册,如图示:


Regasm有多个运行参数,详细可通过帮助查看 /help

回车运行后,显示如下信息:


因为是未签名程序集,所以会有警告,你在项目属性那里设置好签名就不会有这样的警告了。

现在这个DLL已经注册成功,可以在EXCEL中引用这个DLL并使用其中所写的自定义函数了。以EXCEL2003为例来使用刚注册的这个DLL(2007、2010只是在引用的操作上有所不同),打开EXCEL,(菜单栏)工具-》加载宏-》自动化

在弹出的窗口中找到并选择刚才自己写的那个类文件,按两次确定后,即加载成功

加载完毕就可以在工作页面中使用所编写的自定义函数了。

至此,一个由C#编写的自定义函数就可以正常使用了。

六、注销DLL
当这个自定义的DLL不再需要时,该如何注销呢,其过程跟注册差不多,只是在应用regasm时的参数有所不同而已:regasm /unregister "D:\My Documents\Visual Studio 2010\Projects\ExcelFunc\ExcelFunc\obj\Debug\ExcelFunc.dll"


[ 本帖最后由 chentx 于 2011-1-21 21:00 编辑 ]

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2011-1-18 16:00 | 显示全部楼层
非常感谢分享.
看来要有空真的要 研究一下 VSTO了..感觉好像落伍了一样.

TA的精华主题

TA的得分主题

发表于 2011-1-18 16:02 | 显示全部楼层
谢谢分享,支持一下,虽然看不懂

TA的精华主题

TA的得分主题

发表于 2011-1-18 16:05 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
这位同学,图呢?

TA的精华主题

TA的得分主题

发表于 2011-1-18 16:07 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
现在好像流行VSTO了,看来我们落伍了,要跟上,谢谢楼主

TA的精华主题

TA的得分主题

发表于 2011-1-18 18:36 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助

回复 5楼 zm0115 的帖子

MS还没有流行起来吧。。。
不过提前看总是好的。

TA的精华主题

TA的得分主题

 楼主| 发表于 2011-1-18 21:22 | 显示全部楼层
VSTO会是一种趋势,毕竟它有着比VBA更优秀的编程环境,不过说到要取代VBA暂时我想还是做不到的,毕竟VBA你装了EXCEL就基本可以用起来,但VSTO还要这样那样的支持才可以用得了,但相信它会越来越方便,期待微软对它的改良与发展。

TA的精华主题

TA的得分主题

发表于 2011-10-2 19:13 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2011-10-2 21:46 | 显示全部楼层
VSTO一个早就提到但始终没有太多人用的东西。一直在找相关的资料想学一下,但始终没有找到好的资料。《VSTO开发指南》也看过,但似乎讲得并不好。
顶楼主,希望有好的东西可以交流交流。

TA的精华主题

TA的得分主题

发表于 2011-10-2 21:47 | 显示全部楼层
我认为VSTO对机器环境的要求可能是阻止发展的最大原因。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-12-22 16:55 , Processed in 0.045293 second(s), 14 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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