如何使用 VSTO 插件项目轻松创建 Excel UDF
Posted
技术标签:
【中文标题】如何使用 VSTO 插件项目轻松创建 Excel UDF【英文标题】:How to easily create an Excel UDF with VSTO Add-in project 【发布时间】:2009-06-05 19:07:15 【问题描述】:我要做的是使用 VSTO 的 C#“Excel 2007 插件”项目类型为 Excel 创建用户定义函数 (UDF)(因为我只想生成一些通用 UDF)。因为我只是想学习基础知识(无论如何在这个阶段),这就是我的代码的样子:
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Linq;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Tools.Excel;
using Microsoft.Office.Tools.Excel.Extensions;
using System.Runtime.InteropServices;
namespace ExcelAddIn1
public partial class ThisAddIn
private void ThisAddIn_Startup(object sender, System.EventArgs e)
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
//My UDF
public static double HeronicCal(int a, int b, int c)
//first compute S = (a+b+c)/2
double S = (a + b + c) / 2;
double area = Math.Sqrt(S * (S - a) * (S - b) * (S - c));
return area;
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
#endregion
它编译得很好,当我运行它时,Excel 会弹出一个新的电子表格,当我查看“加载项”列表(在 Excel 选项中)时,我可以在列表中看到我的加载项(设置为“启动时加载”。但是我的问题来了,当我尝试从 Excel 中调用我的 UDF 时,Excel 找不到方法!
我想错了,我必须将我的方法标记为 Excel UDF(使用方括号 - 例如在编写 Web 服务时所做的 -> “[WebService]”)。但是我一直没能找到这个标签(因为我根本不确定我的预感是否正确),这就是为什么我决定去找你们这里的好人。
所以我的问题基本上是——从我的代码那里,有没有什么简单的方法可以让 Excel 访问我的 UDF?如果是,如何?
我真的很想留在 VSTO 项目类型(加载项、工作簿、模板)中,因为我当前项目的总体目标是确定使用 VS2010/Excel2007 执行 C# UDF 是否工作在可接受的范围内速度。为了测试这一点,我正在使用 Windows7RC 和 VS2010 beta1。
【问题讨论】:
【参考方案1】:VSTO 不支持创建 Excel UDF。可以在 .Net 中创建自动化加载项,并且似乎是 Microsoft 认可的执行方式。
您应该看看 ExcelDna - http://www.codeplex.com/exceldna。 ExcelDna 允许托管程序集通过本机 .xll 接口向 Excel 公开用户定义的函数 (UDF) 和宏。该项目是开源的,可以免费用于商业用途。您会发现基于 .Net 的 UDF 的性能类似于 Excel 的原生 .xll 插件。支持 Excel 2007 的大型工作表、长 Unicode 字符串和多线程重新计算等功能。
使用 ExcelDna,您上面发布的函数将在没有 VSTO 的情况下向 Excel 公开 - 您可以将代码放入基于 xml 的 .dna 文件或将其编译为 .dll。
暴露 UDF 的 .dna 文件如下所示:
<DnaLibrary Language="C#">
using System;
using ExcelDna.Integration;
public class MyFunctions
[ExcelFunction(Description="Calculate Stuff", Category="Cool Functions")]
public static double HeronicCal(int a, int b, int c)
//first compute S = (a+b+c)/2
double S = (a + b + c) / 2;
double area = Math.Sqrt(S * (S - a) * (S - b) * (S - c));
return area;
</DnaLibrary>
更新:如今,开始使用 Excel-DNA 的最简单方法是在 Visual Studio 中创建一个新的类库项目,然后从 NuGet 添加“ExcelDna.AddIn”包。这就是一个入门插件 - 只需粘贴您的代码并按 F5 即可运行。
【讨论】:
【参考方案2】:看起来埃里克·卡特在这里赢得了胜利:
https://docs.microsoft.com/en-us/archive/blogs/eric_carter/3-vsto-bug-tracker-a-udf
它是纯 .NET - 不依赖第三方库。
现在给它一个树瘤......
【讨论】:
恕我直言,这个答案应该更高。没有 3d 派对库和很少的样板是大优点。 链接失效 我相信这是@harvest316 参考的文章。 docs.microsoft.com/en-us/archive/blogs/eric_carter/….【参考方案3】:据我所知,您不能直接在 VSTO 中创建 UDF。
请参阅 Paul Stubbs 的文章 How to create Excel UDFs in VSTO managed code,其中他使用 VBA 插件来公开 VBA UDF,而这反过来又调用了他用 VSTO 编写的托管 UDF。
但是,在不使用 VSTO 时,您可以使用托管代码来创建 UDF。请参阅 Eric Carter 的文章 Writing user defined functions for Excel in .NET,了解如何执行此操作。
至于 VSTO 的执行速度,我想您会发现它几乎适用于所有任务。然而,循环遍历已经是 Excel 的弱点的单元格可能会非常缓慢,具体取决于您在做什么。尽量批量执行。例如,不是逐个循环遍历单元格,而是从一个区域返回一个二维值数组,处理该数组,然后将其传递回该区域。
为了演示,下面将从一个区域返回一个二维值数组,处理这些值,然后将结果数组一次性传回原始区域:
Excel.Range rng = myWorksheet.get_Range("A1:D4", Type.Missing);
//Get a 2D Array of values from the range in one shot:
object[,] myArray = (object[,])rng.get_Value(Type.Missing);
// Process 'myArray' however you want here.
// Note that the Array returned from Excel is base 1, not base 0.
// To be safe, use GetLowerBound() and GetUpperBound:
for (int row = myArray.GetLowerBound(0); row <= myArray.GetUpperBound(0); row++)
for (int column = myArray.GetLowerBound(1); column <= myArray.GetUpperBound(1); column++)
if (myArray[row, column] is double)
myArray[row, column] = (double)myArray[row, column] * 2;
// Pass back the results in one shot:
rng.set_Value(Type.Missing, myArray);
希望这会有所帮助!
迈克
【讨论】:
【参考方案4】:我发现效果很好的是将 UDF 保留为 VB 模块以避免 COM 对象的问题。
我有大量的 C# 代码正在运行,当我准备好构建版本时,我会执行以下操作: 1.添加模块: 开发人员 [Excel 中的选项卡] | Visual Basic -> 项目窗口,右键单击,插入模块 - 只需在此处复制/粘贴 VB 代码 2. 包含相应的参考库(工具在同一 VB 窗口中) 3. 将 Excel 文件另存为 .xlsm(即启用宏)
然后您可以删除 .xlsx 文件。
我所做的是压缩整个目录(例如,“发布”)并将其发送给我们的用户。
【讨论】:
以上是关于如何使用 VSTO 插件项目轻松创建 Excel UDF的主要内容,如果未能解决你的问题,请参考以下文章