9

説明

COM サーバーでいくつかの Excel UDF を作成しています。fxを押したときに表示される標準のヘルプ (関数の挿入ダイアログ) を取得したいと思います。はい、カテゴリのドロップダウンに自分の COM サーバーが表示されていますが、

  • また、Equals、GetHashCode、GetType、および ToString も表示されます (これらは Excel ユーザーに公開するのはかなり望ましくありません)。
  • COM サーバーを選択すると、*Function Arguments*[1] ダイアログが表示され、引数情報も関数の説明もありません。

これが私が得る不自由です:

関数の挿入ダイアログ http://www.iwebthereforeiam.com/files/Insert%20function%20dialog.gif

Excel 関数の引数ダイアログ http://www.iwebthereforeiam.com/files/Function%20Arguments%20dialog.gif

質問

これを Excel に渡すためにメソッドに設定できる .NET 属性はありますか?

  • 機能の説明を提供できますか?
  • パラメータの説明を提供できますか?
  • 関数にカテゴリ名を付けて、ProgID よりも優れたものを取得できますか?

(ExcelDNA で実行するのは悲しいことに簡単に見えますが、私はその道をたどりません。govert のコード [カスタム属性、ある種のローダーなど] をエミュレートするのはかなり難しいようです。)


追加の背景

以前に Excel + COM サーバーを使用したことがない場合は、速度を上げるために役立つリソースがいくつかあります。

以前の StackOverflow の質問:
VB.NET で記述された COM Server for Excel をインストールしてオートメーション サーバー リストに登録するにはどうすればよいですか?
COM 公開 .NET プロジェクトを VB6 (または VBA) 参照ダイアログに追加する方法

その他のリソース:
.NET で Excel 用のユーザー定義関数を作成
する .NET COM アセンブリをビルドおよびデプロイする
C# でカスタム Excel ワークシート関数を作成する


編集 2009-10-20 14:10

を呼び出してみApplication.MacroOptionsましたSub New()

  1. Sub New() なし
    準許容: 関数はカテゴリ ProgID にリストされています。
  2. Shared Sub New()
    受け入れられません: ビルド時のエラーです。
    アセンブリ "...\Foo.dll" を登録できません。
    呼び出しのターゲットによって例外がスローされました。
  3. Sub New()
    受け入れられません: カテゴリは [関数の挿入] ダイアログに表示されません。

これは、MacroOptions と、Charles が推奨するより複雑なルートの両方に問題があると思われます。


編集 2009-10-20 14:55

良い面としては、実装するインターフェイスを作成するという Mike の推奨により、公開されていた迷惑な余分なメソッドが削除されました。


編集 2009-10-20 15:00

2007 年初頭のこの Microsoft の記事( Mike のリンク経由) は、このトピックに関するかなり完全な回答のようです。

オートメーション アドインと関数ウィザード

各オートメーション アドインには、Excel 関数ウィザードで独自のカテゴリがあります。カテゴリ名はアドインの ProgID です。オートメーション アドイン関数に別のカテゴリ名を指定することはできません。さらに、Function Wizard でオートメーション アドイン関数の関数の説明、引数の説明、またはヘルプを指定する方法はありません。


1ええと、StackOverFlow のバグです。明示的な HTML ul-list 内の文字列をイタリック体にできないようですか?

4

2 に答える 2

11

これの一部は簡単に修正できますが、他の部分はかなり難しいものです。ただし、時間をかければ、すべて実行可能です。

あなたが書いた:

Equals、GetHashCode、GetType、および ToString も表示されます (これらは Excel ユーザーに公開するのはかなり望ましくありません)。

はい、同意しました。これは間違いなく望ましくありませんが、防ぐことができます。これは、すべての .NET クラスと同様に、クラスが「System.Object」から継承しており、COM に公開されている既定のインターフェイスにこれらのメンバーが含まれているために発生します。これは、たとえば、「ClassInterfaceType.AutoDual」設定を使用して「ClassInterfaceAttribute」を使用する場合に発生します。

たとえば、C# の場合:

[ClassInterface(ClassInterfaceType.AutoDual)]

VB.NET の場合:

<ClassInterface(ClassInterfaceType.AutoDual)>

ただし、「System.Object」から継承されたメンバーが公開されるのを防ぐため (および将来の潜在的なバージョン管理の問題を防ぐため)、「ClassInterfaceType.AutoDual」の使用は避ける必要があります。代わりに、独自のインターフェースを定義し、そのインターフェースをクラスに実装してから、'ClassInterfaceType.None' の値を持つ 'ClassInterface' 属性でクラスをマークしてください。

たとえば、C# を使用すると、次のようになります。

[ComVisible(true)]
[Guid("5B88B8D0-8AF1-4741-A645-3D362A31BD37")]
public interface IClassName
{
    double AddTwo(double x, double y);
}

[ComVisible(true)]
[Guid("010B0245-55BB-4485-ABAF-46DF4356DB7B")]
[ProgId("ProjectName.ClassName")]
[ComDefaultInterface(typeof(IClassName))]
[ClassInterface(ClassInterfaceType.None)]
public class ClassName : IClassName
{
    public double AddTwo(double x, double y)
    {
        return x + y;
    }
}

VB.NET の使用:

<ComVisible(True)> _
<Guid("5B88B8D0-8AF1-4741-A645-3D362A31BD37")> _
Public Interface IClassName
    Function AddTwo(ByVal x As Double, ByVal y As Double) As Double
End Interface

<ComVisible(True)> _
<Guid("010B0245-55BB-4485-ABAF-46DF4356DB7B")> _
<ProgId("ProjectName.ClassName")> _
<ComDefaultInterface(GetType(IClassName))> _
<ClassInterface(ClassInterfaceType.None)> _
Public Class ClassName
    Implements IClassName

    Public Function AddTwo(ByVal x As Double, ByVal y As Double) As Double _
        Implements IClassName.AddTwo
        Return x + y
    End Function
End Class

'ClassInterfaceType.None' の値を持つ 'ClassInterfaceAtribute' を使用することにより、継承された 'System.Object' メンバーは除外されます。これは、クラスのインターフェイスが COM 可視にならないためです。代わりに、実装されたインターフェイス (この例では「IClassName」) のみが COM にエクスポートされます。

上記も「ComDefaultInterfaceAttribute」を利用しています。これはあまり重要ではなく、この例のように 1 つのインターフェイスのみを実装する場合は何もしませんが、IDTExtensibility2 などのインターフェイスを後で追加する場合は、これをお勧めします。

詳細については、次を参照してください。

(1) Andrew Whitechapel によるマネージド オートメーション アドイン。

(2) Gabhan Berry によるC# でのカスタム Excel ワークシート関数の記述。

さて、難しい部分に移ります。あなたが書いた:

COM サーバーを選択する と、引数情報も関数の説明もないFunction Arguments [1] ダイアログが表示されます。

機能の説明を提供できますか?

パラメータの説明を提供できますか?

関数にカテゴリ名を付けて、ProgID よりも優れたものを取得できますか?

ここでの最も簡単な方法は、Application.MacroOptionsメソッドを利用することです。このメソッドを使用すると、関数の説明を提供し、表示するカテゴリを指定できます。残念ながら、このアプローチでは、関数パラメーターの情報を指定することはできませんが、それを可能にする手法は非常に複雑です。これについては後で説明します。[訂正: 'Application.MacroOptions' メソッドは、VBA 経由で作成された UDF に対してのみ機能し、オートメーション アドインには使用できません。自動化アドインに含まれる UDF の登録を処理するためのより複雑なアプローチについては、以下をお読みください -- Mike Rosenblum 2009.10.20]

Excel 2003ヘルプ ファイルと Excel 2007のヘルプ ファイルには、選択したカスタム カテゴリ名を提供するために、カテゴリ引数に文字列を指定できることが記載されていることに注意してください。ただし、 Excel 2002のヘルプ ファイルには含まれていないことに注意してください。これが Excel 2002 ヘルプ ファイルの省略なのか、それとも Excel 2003 の新しい機能なのかはわかりません。後者だと推測していますが、確認するためにテストする必要があります。

Function Wizard にパラメーター情報を取得する唯一の方法は、'Excel.Application.ExecuteExcel4Macro' メソッドを含むかなり複雑な手法を使用することです。ただし、注意してください: 多くの Excel MVP はこのアプローチに苦労しており、信頼できる結果を出すことができませんでした。しかし最近では、Jan Karel Pieterse (JKP) がそれを解決し、ここで詳細を公開したようです: Registering a User Defined Function with Excel .

その記事に目を通すと、気弱な人向けではないことがわかります。問題の一部は、彼が VBA / VB 6.0 用に作成したため、すべてのコードを VB.NET または C# に変換する必要があることです。ただし、重要なコマンドは、.NET に公開されている 'Excel.Application.ExecuteExcel4Macro' メソッドであるため、すべて正常に動作するはずです。

ただし、実際問題として、単純で信頼できる「Excel.Application.MacroOptions」アプローチを使用することを非常に好みます。パラメーター情報は提供されませんが、「ExecuteExcel4Macro」アプローチを採用するように動機付けする強い必要性はまだありません。

ですから、これで頑張ってください。ただし、時間単位で支払われている場合を除き、'MacroOptions' を利用することをお勧めします。;-)

-- マイク

ヒューの返信のフォローアップ

Sub New() で Application.MacroOptions を呼び出してみました。

Sub New() なし 準許容: 関数はカテゴリ ProgID にリストされています。

Shared Sub New() 受け入れられません: ビルド時のエラーです。アセンブリ "...\Foo.dll" を登録できません。呼び出しのターゲットによって例外がスローされました。

Sub New() 受け入れられません: カテゴリは [関数の挿入] ダイアログに表示されません。これは、MacroOptions と、Charles が推奨するより複雑なルートの両方に問題があると思われます。

クラスを COM に公開するときに、共有 (別名「静的」) クラスまたはコンストラクターを使用することはできません。これは、COM がこの概念を認識していないため、コンパイルできないことがわかったからです。少なくともコンパイルできるようにするために、値が「False」の「COMVisibleAttribute」を共有コンストラクターに適用できる場合があります。しかし、とにかく、これはこの場合には役に立ちません...

オートメーション アドイン自体を介してオートメーション アドインを登録しようとすると、注意が必要になる場合があります。単一のスタンドアロン コンポーネントとして維持するためには、これが望ましいことは理解していますが、不可能な場合もあります。または、少なくともこれは簡単ではありません。

問題は、オートメーション アドインがデマンド ロードされることです。つまり、Excel がオートメーション アドインから最初のワークシート関数にアクセスしようとするまで、実際には存在しません。これに関連する 2 つの問題があります。

(1) クラスのコンストラクター内に登録コードを配置すると、定義上、関数が初めて呼び出されるまで、関数ウィザードの情報は存在できません。

(2) Excel が自動化コマンドを受け入れる準備ができていないときに、コンストラクターが実行されている可能性があります。たとえば、オートメーション アドインで定義されているユーザー定義関数 (UDF) のいずれかの名前をユーザーが入力し始めると、通常、オートメーション アドインはデマンド ロードされます。その結果、オートメーション アドインが最初に読み込まれるとき、セルは編集モードになります。編集モード中にコンストラクター内に自動化コードがある場合、多くのコマンドが失敗します。「Excel.Application.MacroOptions」または「Excel.Application.Excel4Macro」メソッドに問題があるかどうかはわかりませんが、セルが編集モードのときに実行しようとすると、多くのコマンドが停止します。また、Function Wizard が開いているときにオートメーション アドインが呼び出されて初めて読み込まれる場合、これらのメソッドが正しく機能するかどうかはわかりません。

オートメーション アドインを他のサポートなしで完全にスタンドアロンにしたい場合、これに対する簡単な解決策はありません。ただし、Excel の起動時に 'Excel.Application.MacroOptions' または 'Excel.Application.Excel4Macro' アプローチを使用してオートメーション アドインを登録するマネージ COM アドインを作成することはできます。マネージ COM アドイン クラスは、オートメーション アドインと同じアセンブリに含めることができるため、必要なアセンブリは 1 つだけです。

ちなみに、VBA ワークブックまたは .XLA アドインを使用して同じことを行うこともできます。VBA の Workbook.Open イベントを使用して、登録コードを呼び出します。Excel の起動時に登録コードを呼び出す必要があるだけですこの場合に VBA を使用する利点は、Jan Karel Pieterse の記事「ユーザー定義関数を Excel に登録する」のコードを .NET に変換せずにそのまま利用できることです。

良い面としては、実装するインターフェイスを作成するという Mike の推奨により、公開されていた迷惑な余分なメソッドが削除されました。

笑、私は何かがうまくいったことをうれしく思います!

2007 年初頭のこの Microsoft の記事 (Mike のリンク経由) は、このトピックに関するかなり完全な回答のようです。

オートメーション アドインと関数ウィザード

各オートメーション アドインには、Excel 関数ウィザードで独自のカテゴリがあります。カテゴリ名はアドインの ProgID です。オートメーション アドイン関数に別のカテゴリ名を指定することはできません。また、Function Wizard でオートメーション アドイン関数の関数の説明、引数の説明、またはヘルプを指定する方法はありません。

これは、'Excel.Application.MacroOptions' アプローチのみの制限です。(申し訳ありませんが、上記の最初の回答を書いたときに、自動化アドインに関する「Excel.Application.MacroOptions」メソッドのこの制限を忘れていました。)より複雑な「Excel.Application. ただし、ExecuteExcel4Macro ' アプローチは、オートメーション アドインに対しては確実に機能します。Excel は、VB 6.0/C++ で作成された COM オートメーション アドインと、VB 6.0/C++ を使用して作成されたマネージ COM オートメーション アドインを読み込んでいるかどうかを判断できないため、.NET (「マネージ」) オートメーション アドインでも機能するはずです。 VB.NET/C#。Excel は .NET が何であるか、または .NET が存在することすら知らないため、フェンスの COM 側から見たメカニズムはまったく同じです。

そうは言っても、「Excel.Application.Excel4Macro」アプローチは間違いなく大変な作業になるでしょう...

于 2009-10-20T15:51:47.610 に答える
3

ExcelDNA や ADDIN Express などの .Net Excel システムのいずれかを使用するか、VBA/VB6 ソリューションのいずれかを適用してみてください。Laurent Longre の FunCustomise http://xcell05.free.fr/english/index.htmlを参照してください。または、 http: //www.jkp-ads.com/Articles/RegisterUDF00.asp にある Jan Karel Pieterse の記事で は、関数のオーバーロード ハックが使用されています。

于 2009-10-20T15:11:18.620 に答える