スポンサーリンク

Excel-DNA

Excel-DNAとは

Excel-DNA

Excel-DNAはC#やF#, VBのような.NET Frameworkを使って、xll形式のExcel拡張を作成するためのライブラリ、ツールです。CodePlex上で開発が行われています。ライセンスはオリジナルの物ですので、CodePlexのサイトで確認ください。

xllは基本的にC/C++用のExcel APIを使用したExcelの拡張ライブラリですが、非常に薄いネイティブのラッパを通すことで、高速にExcelから.NETのクラスライブラリを呼び出します。

特に、Excelのユーザー定義関数の作成を.NETの言語で行いたいような場合に非常に強力なツールです。今までの良くあるやり方は、.NETの言語でActiveX DLLを作ってExcelのオートメーションアドインとしてUDFを提供する方式ですが、.NETでActiveX DLLを作るためのお約束が非常に多く、コードも煩雑だし、間にCCWもはいるしなので、あまり見やすい物でも作りやすい物でもありませんでしたが、このExcel-DNAでは最低限のコードで、Excelのユーザー定義関数の開発が行えます。

作業の流れ

Visual Studioで、Excelのユーザー定義関数を開発する場合には以下の手順で、作業を行います。

先ず、クラスライブラリのプロジェクトを作成します。

SnapCrab_新しいプロジェクト_2014-6-27_23-0-32_No-00

プロジェクトが決まったら、NugetでExcel-DNAを追加します。Guiを使う場合にはExcel.DNAで検索をして、下の図のようにExcel-DNAを選択して追加します。

SnapCrab_MyExcelDnaSample1 - NuGet パッケージの管理_2014-6-27_23-2-16_No-00

手動でライブラリの参照を追加した場合には、dllの他にプロジェクトに.dnaというXMLの動作定義ファイルを追加しないといけないのですが、Nugetでのライブラリ追加時にいかのようなそのまま使用できる.dnaファイルが追加されます。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<dnalibrary name="MyExcelDnaSample1 Add-In" runtimeversion="v4.0">
<externallibrary path="MyExcelDnaSample1.dll" loadfrombytes="true" pack="true">
</externallibrary></dnalibrary>
<dnalibrary name="MyExcelDnaSample1 Add-In" runtimeversion="v4.0"> <externallibrary path="MyExcelDnaSample1.dll" loadfrombytes="true" pack="true"> </externallibrary></dnalibrary>

  
  
  

ライブラリをNugetで追加したら、以下のようにC#のコードで実際のExcel関数を追加します。このとき、クラスとExcel関数となるメソッドはStaticで記述します。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-keyword">namespace</span> <span class="hljs-title">MyExcelDnaSample1</span>
{
<span class="hljs-keyword">using</span> ExcelDna.Integration;
<span class="hljs-comment"><span class="hljs-doctag">///</span> </span><summary>
<span class="hljs-comment"><span class="hljs-doctag">///</span> Excel DNAを使用してExcelのユーザー定義関数(UDF)を作成するサンプル</span>
<span class="hljs-comment"><span class="hljs-doctag">///</span> UDFはstaticなクラスにstaticなメソッドとして記述する。</span>
<span class="hljs-comment"><span class="hljs-doctag">///</span> </span></summary>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyExcelDnaSample1</span>
{
<span class="hljs-comment"><span class="hljs-doctag">///</span> </span><summary>
<span class="hljs-comment"><span class="hljs-doctag">///</span> 引数の名前にHelloを言う</span>
<span class="hljs-comment"><span class="hljs-doctag">///</span> </span></summary>
<span class="hljs-comment"><span class="hljs-doctag">///</span> </span><param name="name"><span class="hljs-comment">あいさつの相手</span>
<span class="hljs-comment"><span class="hljs-doctag">///</span> </span><returns><span class="hljs-comment">あいさつ</span></returns>
[<span class="hljs-meta">ExcelFunction(Description = <span class="hljs-meta-string">"引数にHelloを言う。"</span>, Category = <span class="hljs-meta-string">"Tadahiro Lib."</span>)</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">string</span> <span class="hljs-title">SayHello</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> name</span>)</span>
{
<span class="hljs-keyword">return</span> <span class="hljs-string">"Hello "</span> + name;
}
}
}
<span class="hljs-keyword">namespace</span> <span class="hljs-title">MyExcelDnaSample1</span> { <span class="hljs-keyword">using</span> ExcelDna.Integration; <span class="hljs-comment"><span class="hljs-doctag">///</span> </span><summary> <span class="hljs-comment"><span class="hljs-doctag">///</span> Excel DNAを使用してExcelのユーザー定義関数(UDF)を作成するサンプル</span> <span class="hljs-comment"><span class="hljs-doctag">///</span> UDFはstaticなクラスにstaticなメソッドとして記述する。</span> <span class="hljs-comment"><span class="hljs-doctag">///</span> </span></summary> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyExcelDnaSample1</span> { <span class="hljs-comment"><span class="hljs-doctag">///</span> </span><summary> <span class="hljs-comment"><span class="hljs-doctag">///</span> 引数の名前にHelloを言う</span> <span class="hljs-comment"><span class="hljs-doctag">///</span> </span></summary> <span class="hljs-comment"><span class="hljs-doctag">///</span> </span><param name="name"><span class="hljs-comment">あいさつの相手</span> <span class="hljs-comment"><span class="hljs-doctag">///</span> </span><returns><span class="hljs-comment">あいさつ</span></returns> [<span class="hljs-meta">ExcelFunction(Description = <span class="hljs-meta-string">"引数にHelloを言う。"</span>, Category = <span class="hljs-meta-string">"Tadahiro Lib."</span>)</span>] <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">string</span> <span class="hljs-title">SayHello</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> name</span>)</span> { <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello "</span> + name; } } }
namespace MyExcelDnaSample1
{
    using ExcelDna.Integration;

    /// 
    /// Excel DNAを使用してExcelのユーザー定義関数(UDF)を作成するサンプル
    /// UDFはstaticなクラスにstaticなメソッドとして記述する。
    /// 
    public static class MyExcelDnaSample1
    {
        /// 
        /// 引数の名前にHelloを言う
        /// 
        /// あいさつの相手
        /// あいさつ
        [ExcelFunction(Description = "引数にHelloを言う。", Category = "Tadahiro Lib.")]
        public static string SayHello(string name)
        {
            return "Hello " + name;
        }
    }
}

3行目で、Excel.Dnaへの参照を追加しています。
12行目のExcelFunctionよいうAttributeはなくてもPublicでStaticなメソッドはExcelはユーザー定義関数と認識しますが、このAttributeを使って説明とカテゴリを設定しておけば、Excelの関数のウイザードでそれらが表示されます。

これをビルドしてみましょう。以下がビルド結果です。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<span class="hljs-number">1</span>>------ ビルド開始: プロジェクト:MyExcelDnaSample1, 構成:Debug Any CPU ------
<span class="hljs-meta">1> </span> MyExcelDnaSample1 -> d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll
<span class="hljs-meta">1> </span> D:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\packages\Excel-DNA.<span class="hljs-number">0.32</span>.<span class="hljs-number">0</span>\tools\ExcelDna.xll
<span class="hljs-meta">1> </span> <span class="hljs-number">1</span> 個のファイルをコピーしました
<span class="hljs-meta">1> </span> D:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn.dna
<span class="hljs-meta">1> </span> <span class="hljs-number">1</span> 個のファイルをコピーしました
<span class="hljs-meta">1> </span> D:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\packages\Excel-DNA.<span class="hljs-number">0.32</span>.<span class="hljs-number">0</span>\tools\ExcelDna64.xll
<span class="hljs-meta">1> </span> 共有違反です
<span class="hljs-meta">1> </span> <span class="hljs-number">0</span> 個のファイルをコピーしました
<span class="hljs-meta">1> </span> Using base add-in d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn.xll
<span class="hljs-meta">1> </span> -> Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.INTEGRATION, Length: <span class="hljs-number">60383</span>
<span class="hljs-meta">1> </span> ~~> ExternalLibrary path MyExcelDnaSample1.dll resolved to d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll.
<span class="hljs-meta">1> </span> -> Updating resource: Type: ASSEMBLY_LZMA, Name: MYEXCELDNASAMPLE1, Length: <span class="hljs-number">1571</span>
<span class="hljs-meta">1> </span> -> Updating resource: Type: DNA, Name: __MAIN__, Length: <span class="hljs-number">433</span>
<span class="hljs-meta">1> </span> Completed Packing d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn-packed.xll.
<span class="hljs-meta">1> </span> Using base add-in d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn64.xll
<span class="hljs-meta">1> </span> -> Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.INTEGRATION, Length: <span class="hljs-number">60383</span>
<span class="hljs-meta">1> </span> ~~> ExternalLibrary path MyExcelDnaSample1.dll resolved to d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll.
<span class="hljs-meta">1> </span> -> Updating resource: Type: ASSEMBLY_LZMA, Name: MYEXCELDNASAMPLE1, Length: <span class="hljs-number">1571</span>
<span class="hljs-meta">1> </span> -> Updating resource: Type: DNA, Name: __MAIN__, Length: <span class="hljs-number">433</span>
<span class="hljs-meta">1> </span> Completed Packing d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn64-packed.xll.
========== ビルド: <span class="hljs-number">1</span> 正常終了、<span class="hljs-number">0</span> 失敗、<span class="hljs-number">0</span> 更新不要、<span class="hljs-number">0</span> スキップ ==========
<span class="hljs-number">1</span>>------ ビルド開始: プロジェクト:MyExcelDnaSample1, 構成:Debug Any CPU ------ <span class="hljs-meta">1> </span> MyExcelDnaSample1 -> d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll <span class="hljs-meta">1> </span> D:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\packages\Excel-DNA.<span class="hljs-number">0.32</span>.<span class="hljs-number">0</span>\tools\ExcelDna.xll <span class="hljs-meta">1> </span> <span class="hljs-number">1</span> 個のファイルをコピーしました <span class="hljs-meta">1> </span> D:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn.dna <span class="hljs-meta">1> </span> <span class="hljs-number">1</span> 個のファイルをコピーしました <span class="hljs-meta">1> </span> D:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\packages\Excel-DNA.<span class="hljs-number">0.32</span>.<span class="hljs-number">0</span>\tools\ExcelDna64.xll <span class="hljs-meta">1> </span> 共有違反です <span class="hljs-meta">1> </span> <span class="hljs-number">0</span> 個のファイルをコピーしました <span class="hljs-meta">1> </span> Using base add-in d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn.xll <span class="hljs-meta">1> </span> -> Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.INTEGRATION, Length: <span class="hljs-number">60383</span> <span class="hljs-meta">1> </span> ~~> ExternalLibrary path MyExcelDnaSample1.dll resolved to d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll. <span class="hljs-meta">1> </span> -> Updating resource: Type: ASSEMBLY_LZMA, Name: MYEXCELDNASAMPLE1, Length: <span class="hljs-number">1571</span> <span class="hljs-meta">1> </span> -> Updating resource: Type: DNA, Name: __MAIN__, Length: <span class="hljs-number">433</span> <span class="hljs-meta">1> </span> Completed Packing d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn-packed.xll. <span class="hljs-meta">1> </span> Using base add-in d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn64.xll <span class="hljs-meta">1> </span> -> Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.INTEGRATION, Length: <span class="hljs-number">60383</span> <span class="hljs-meta">1> </span> ~~> ExternalLibrary path MyExcelDnaSample1.dll resolved to d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll. <span class="hljs-meta">1> </span> -> Updating resource: Type: ASSEMBLY_LZMA, Name: MYEXCELDNASAMPLE1, Length: <span class="hljs-number">1571</span> <span class="hljs-meta">1> </span> -> Updating resource: Type: DNA, Name: __MAIN__, Length: <span class="hljs-number">433</span> <span class="hljs-meta">1> </span> Completed Packing d:\documents\visual studio <span class="hljs-number">2013</span>\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn64-packed.xll. ========== ビルド: <span class="hljs-number">1</span> 正常終了、<span class="hljs-number">0</span> 失敗、<span class="hljs-number">0</span> 更新不要、<span class="hljs-number">0</span> スキップ ==========
1>------ ビルド開始: プロジェクト:MyExcelDnaSample1, 構成:Debug Any CPU ------
1>  MyExcelDnaSample1 -> d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll
1>  D:\documents\visual studio 2013\Projects\MyExcelDnaSample1\packages\Excel-DNA.0.32.0\tools\ExcelDna.xll
1>  1 個のファイルをコピーしました
1>  D:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn.dna
1>  1 個のファイルをコピーしました
1>  D:\documents\visual studio 2013\Projects\MyExcelDnaSample1\packages\Excel-DNA.0.32.0\tools\ExcelDna64.xll
1>  共有違反です
1>  0 個のファイルをコピーしました
1>  Using base add-in d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn.xll
1>    ->  Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.INTEGRATION, Length: 60383
1>    ~~> ExternalLibrary path MyExcelDnaSample1.dll resolved to d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll.
1>    ->  Updating resource: Type: ASSEMBLY_LZMA, Name: MYEXCELDNASAMPLE1, Length: 1571
1>    ->  Updating resource: Type: DNA, Name: __MAIN__, Length: 433
1>  Completed Packing d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn-packed.xll.
1>  Using base add-in d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn64.xll
1>    ->  Updating resource: Type: ASSEMBLY_LZMA, Name: EXCELDNA.INTEGRATION, Length: 60383
1>    ~~> ExternalLibrary path MyExcelDnaSample1.dll resolved to d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1.dll.
1>    ->  Updating resource: Type: ASSEMBLY_LZMA, Name: MYEXCELDNASAMPLE1, Length: 1571
1>    ->  Updating resource: Type: DNA, Name: __MAIN__, Length: 433
1>  Completed Packing d:\documents\visual studio 2013\Projects\MyExcelDnaSample1\bin\Debug\MyExcelDnaSample1-AddIn64-packed.xll.
========== ビルド: 1 正常終了、0 失敗、0 更新不要、0 スキップ ==========

手でExcel-DNAのライブラリを参照追加した場合、最終的なxllとする作業は手作業になってしまうのですが、NuGetでライブラリ追加した場合はプロジェクトのビルド時にPowerShellスクリプトが呼び出されてパッケージ化の作業まで実行してくれます。

ビルドが成功したら、ターゲット先のフォルダを開いて、.xllをダブルクリックするか、Excelを起動してドラッグ&ドロップしてください。.xllはExcelのプロセッサアーキテクチャにあわせた方を選択してください。

SnapCrab_Debug_2014-6-27_23-7-14_No-00

以下のようなダイアログが表示される場合には、左側のこのアドインをこのセッションに限り有効とするをクリックします。

SnapCrab_Microsoft Excel のセキュリティに関する通知_2014-6-27_23-7-34_No-00

Excelが起動したらCtrl + Nで新規のワークブックを開きます。

適当なセルで=をおしてSayHello(“Tadahiro”)と入力すれば、自分がC#で作成したユーザー定義関数が動作することを確認できると思います。

SnapCrab_Book1 - Excel_2014-6-28_0-7-6_No-00_01

SnapCrab_NoName_2014-6-28_0-10-15_No-00

関数の挿入ボタンを押して、ウインドウを表示させると、先ほどExcelFunctionで設定したDescriptionの内容が表示されています。

SnapCrab_NoName_2014-6-28_0-12-21_No-00

何もないセルで関数の挿入を選択すると、以下のようにExcelFunctionで設定されたカテゴリを確認することが出来ます。ちなみにカテゴリを設定しなかった場合には、xllの名前がカテゴリになります。

SnapCrab_関数の挿入_2014-6-28_0-13-45_No-00

まとめ

  • Excel-DNAは.NET FrameworkでExcel拡張を作成するための、ライブラリ、ツール。
  • Excel-DNAを使用すると非常に少ない労力でExcelユーザー定義関数の開発が行え、関数自体の実装に集中できる。
  • Automationアドインでは無く、xllとして実装される。
  • Nugetを使用するともっと労力を減らせる。

また、CodePlexのサイトからZIPをダウンロードすることもあわせてお勧めします。豊富なサンプルがありますので、参考になると思います。

Visual Studio Tools for Officeで何故かユーザー定義関数の開発がサポートされていないとか、そもそもいけていないとか、Automationアドインの開発の煩雑さに辟易とか、既存の.NEtでのExcel拡張の開発に嫌気がさしたそういうみなさんは、一度Excel限定ではありますが、Excel-DNAを試してみてはいかがでしょう。

今回のコードは以下を参照。

GitHub - ishisaka/ExcelDnaSample1: Excel-DNA Code Sample.
Excel-DNA Code Sample. Contribute to ishisaka/ExcelDnaSample1 development by creating an account on GitHub.

コメント

タイトルとURLをコピーしました