[C#5] コンパイルしないで Excel DNA を使う
Excel VBAのかわりにC#(あるいはF#, VB.NET)でユーザー定義関数が手軽に作成できるツールである Excel DNA について, DLL を作らずに使う方法を記載(残念ながら F# はデフォルトでは Windows にコンパイラが付属しないので, 今回の記事では対象外). 普通に使う方法については公式のドキュメントを参照のこと.
0. 概要
最近の Excel はいろいろ改良されていて, VBAだけで書いてもあんまり不自由は感じないけれど, たまに C#(あるいはF#, VB.NET) でプログラムを書きたい場面がでてくる. そんな時に一番手軽に使えるツールが Excel DNA だと思う. 通常は Visual Studio 等で DLL を作成しそれを読み込む形で使用するが, 実はC#(とVB.NET)の場合には dna ファイルにプログラムを記載すればコンパイル等せずに直接ユーザー定義関数を作成できる. 昔は公式の Getting Started に記載があったが, 今のドキュメントでは DLL を使う方法がデフォルトになっているようなので, 備忘もかねてメモしておくことにした.
この記事では以下の内容について記載する.
- インストール方法
- vscode の設定
- サンプルプログラム(線形補間の関数)
なお, タイトルに「コンパイルしない」と記載したが, 実際には Excel に読み込む際に裏で Windows 付属の C# コンパイラ(csc.exe) を使ってこっそりコンパイルされているため, 使えるC#のバージョンはC#5になる.
1. インストール方法, 使い方
公式の配布サイト(GitHub)から以下のファイルをダウンロードする(ExcelDna.Integration.dll はより高度なことをやろうとするときに必要だが, とりあえずその時になったらダウンロードすればいいと思う, たぶん).
- ExcelDna64.dna
- ExcelDna64.xll
(これは64ビットの Excel 用. Excel が32ビットの場合はファイル名に64がついてないものを使う.)
参考までに GitHub で個別ファイルをダウンロードする方法は以下の通り.
- ファイル名をクリックしてファイルのページに移動
- ダウンロードマーク(Download raw file)をクリック
また, 使用方法は以下のとおり.
- ダウンロードしたファイルを使用したい Excel ファイルと同じフォルダに置く
- ExcelDna64.dna ファイルを編集し, ユーザー定義関数などを記載
- Excel ファイルに ExcelDna64.xll ファイルをドラッグ&ドロップ(もしくは「ファイル名を指定して開く」から ExcelDna64.xll ファイルを開く)
これでC#で記載したユーザー定義関数を Excel で使えるようになる.
2. vscode の設定
拡張子が dna のシンタックスハイライトの設定はないので, かわりにC#のシンタックスハイライトを使えるようにする.
vscode の設定項目のうち, files.associations に設定を加える(*.dna ファイルに csharp のシンタックスハイライトを適用).
自分の場合, これでだいたいシンタックスハイライトが使えている. dna ファイルには Excel DNA 独自の記載があるので, 実は何か不具合があるかもしれない. ただ, 個人的にちょこっといじる程度であれば今のところ十分.
3. サンプルプログラム
実際にユーザー定義関数を作ってみよう.
3.1 dna ファイルの編集
ダウンロードした dna ファイルは以下のようになっている.
<DnaLibrary RuntimeVersion="v4.0" Language="VB" >
<![CDATA[
Public Module Module1
Function AddThem(x, y)
AddThem = x + y
End Function
End Module
]]>
</DnaLibrary>
RuntimeVersion は .NET Framework のバージョンで, デフォルトでは Windows に付属のコンパイラを使用する前提なので v4.0 が指定されている. これはC#でも同じなので, これはこのままでOK. また初期設定の言語は VB になっているので CS (C#) に変更する(残念ながらここを FS としても F# は使えない). サンプルコードは2つの引数を足すだけのものなので, これも消しておく.
<DnaLibrary RuntimeVersion="v4.0" Language="CS" >
<![CDATA[
]]>
</DnaLibrary>
CDATAの中にユーザー定義関数のコードを記載する.
3.2 プログラムのロジック
作成するサンプルプログラムは標本点
念の為, 線形補間のロジックは以下のとおり.
標本点
また補間点の外側(外挿の場合)については端の値を使って定数補間とする.
3.3 サンプルプログラム
このロジックをC#のコードに直す.
<DnaLibrary RuntimeVersion="v4.0" Language="CS" >
<![CDATA[
public class Udf
{
public static double interp(double[,] x, double[,] y, double xx)
{
// assumption: x,y are col vector, n>1
int n=x.GetLength(0);
double yy=0;
if(xx<=x[0,0]){
yy=y[0,0];
}else if(x[n-1,0]<=xx){
yy=y[n-1,0];
}else{
for(int i=1;i<n;i++){
if(xx<=x[i,0]){
yy=(y[i-1,0]*(x[i,0]-xx)+y[i,0]*(xx-x[i-1,0]))
/(x[i,0]-x[i-1,0]);
break;
}
}
}
return yy;
}
}
]]>
</DnaLibrary>
- Excel のワークシート上の列ベクトルは Range オブジェクトであるが, 引数の型は
double[,]
としている. これは VBA で Range オブジェクトを Variant 型で受けたときに2次元配列になるのに似ている. - 入力引数に対する仮定として, 列ベクトルであること, 標本点が2点以上あることを仮定している. これは使う側(自分)が保証する.
- その他エラー処理等はなし.
実際に使ってみた様子は以下のとおり.
ちゃんと補間できてる(\(^o^)/).
4. まとめ
とりあえずテキストエディタ(メモ帳でもOK)さえあれば, C# で Excel のユーザー定義関数を作れる. お手軽ですね.
ところで Excel DNA の開発者の Govert さんは某有名ゲームの配管工のおじさんにしか見えない(笑). Thanks, Govert!
Discussion