20 c# vsto excel-2007 visual-studio-2010
我想要做的是使用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
}
}
Run Code Online (Sandbox Code Playgroud)
它编译得很好,当我运行时,Excel弹出一个新的电子表格,当我查看"加载项"列表(在Excel选项中)时,我可以在列表中看到我的加载项(已设置"在启动时加载".但是这里出现了我的问题,当我尝试从Excel中调用我的UDF时,Excel无法找到该方法!
我想象的是错误的,我必须将我的方法标记为Excel UDF(使用方括号 - 例如在编写webservices时完成 - >"[WebService]").但是我无法追踪这个标签(因为我不确定我的预感是否正确),这就是为什么我决定在这里找你这里的好人.
所以我的问题基本上是 - 从我的代码到哪里,有什么简单的方法可以让我的UDF可以访问Excel?如果有,怎么样?
我真的希望保留在VSTO项目类型(插件,工作簿,模板)中,因为我当前项目的总体目标是确定使用VS2010/Excel2007执行C#UDF是否以可接受的速度运行.为了测试这个,我正在使用Windows7RC和VS2010 beta1.
Gov*_*ert 21
VSTO不支持创建Excel UDF.自动化加载项可以在.Net中创建,并且似乎是Microsoft批准的方式.
你应该看一下ExcelDna - http://www.codeplex.com/exceldna.ExcelDna允许托管程序集通过本机.xll接口将用户定义的函数(UDF)和宏公开给Excel.该项目是开源的,可以自由地进行商业用途.您会发现基于.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>
Run Code Online (Sandbox Code Playgroud)
更新:现在,开始使用Excel-DNA的最简单方法是在Visual Studio中创建一个新的类库项目,然后从NuGet添加"ExcelDna.AddIn"包.这使得一个入门加载项 - 只需粘贴您的代码并按F5即可运行.
har*_*316 10
看起来Eric Carter在这里有一个胜利者:
http://blogs.msdn.com/b/eric_carter/archive/2004/12/01/273127.aspx
它是纯.NET - 不依赖于第三方库.
现在给它一个角色......
据我所知,您无法在VSTO中直接创建UDF.
请参阅Paul Stubbs的文章如何在VSTO托管代码中创建Excel UDF,其中他使用VBA加载项来公开VBA UDF,VBA UDF又调用其在VSTO中编写的托管UDF.
但是,在不使用VSTO时,可以使用托管代码创建UDF.有关如何执行此操作的信息,请参阅Eric Carter的文章"在.NET中编写Excel的用户定义函数".
至于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);
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!
麦克风