22

私がやろうとしているのは、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]")。しかし、私はこのタグを突き止めることができませんでした (そして、私の予感が正しいかどうかまったく確信が持てないため)。そのため、ここ SO の素晴らしい人々に会いに行くことにしました。

私の質問は基本的に、コードを使用している場所から、UDF を Excel でアクセスできるようにする簡単な方法はありますか? はいの場合、どのように?

現在のプロジェクトの全体的な目標は、VS2010/Excel2007 での C# UDF の実行が許容できる速度で動作するかどうかを確立することであるため、VSTO プロジェクトの種類 (アドイン、ワークブック、テンプレート) 内に留まりたいと考えています。これをテストするために、私は Windows7RC と VS2010 beta1 で作業しています。

4

4 に答える 4

22

VSTO は、Excel UDF の作成をサポートしていません。オートメーション アドインは .Net で作成でき、Microsoft が承認した方法のようです。

ExcelDna - http://www.codeplex.com/exceldnaをご覧ください。ExcelDna を使用すると、マネージ アセンブリは、ネイティブの .xll インターフェイスを通じてユーザー定義関数 (UDF) とマクロを Excel に公開できます。このプロジェクトはオープンソースであり、自由に商用利用できます。また、.Net ベースの UDF のパフォーマンスは、Excel のネイティブ .xll アドインと同様であることがわかります。大きなシート、長い Unicode 文字列、マルチスレッド再計算などの Excel 2007 機能がサポートされています。

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 キーを押すだけで実行できます。

于 2009-06-12T12:38:25.200 に答える
13

エリック・カーターがここで勝者を持っているようです:

https://docs.microsoft.com/en-us/archive/blogs/eric_carter/3-vsto-bug-tracker-a-udf

これは純粋な .NET であり、サード パーティのライブラリに依存しません。

今それを与えます...

于 2011-06-09T00:30:14.383 に答える
9

私の知る限り、VSTO で UDF を直接作成することはできません。

Paul Stubbs の記事「VSTO マネージ コードで Excel UDF を作成する方法」を参照してください。彼は VBA アドインを使用して VBA UDF を公開し、VSTO で記述されたマネージ UDF を呼び出します。

ただし、VSTO を使用しない場合は、マネージ コードを使用して UDF を作成できます。これを行う方法については、 Eric Carter の記事「Writing user defined functions for Excel in .NET in .NET 」を参照してください。

VSTO の実行速度については、ほぼすべてのタスクで問題ないと思います。ただし、既に Excel の弱点となっているセルのループ処理は、実行内容によっては非常に遅くなる場合があります。可能な限りバッチで実行するようにしてください。たとえば、セルを 1 つずつループする代わりに、領域から値の 2 次元配列を返し、配列を処理してから範囲に戻します。

次の例では、領域から値の 2 次元配列を返し、値を処理してから、結果の配列を元の領域に一度に渡します。

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);

お役に立てれば!

マイク

于 2009-06-07T15:59:31.497 に答える