R.NETをExcelから呼び出す手法は
などで紹介されていますが、最近の環境だと動かなくなっているので、試行錯誤してみた結果を共有します。
ちなみにExcelは事情により2010を使っているので、最新版とかでどうなるかは未検証です。
準備
.NET Framework 4.0
R (https://www.r-project.org/)
試したのは3.3.2です。R.NET (http://rdotnet.codeplex.com/)
NuGetパッケージ(ZIP圧縮)からdllを抽出し、下記DNAファイルと同じ場所に置いておく。DynamicInterop
NuGetパッケージからDynamicInterop.dllを抽出して、下記DNAファイルと同じ場所に置いておく。Excel-DNA (http://excel-dna.net/)
NuGetパッケージからxllとdllとを抽出し、ExcelDna.xllをUsingRdotNet.xllにリネーム。
ExcelDna.Integration.dllを一緒に、下記DNAファイルと同じ場所に置いておく。DNAファイル
下記をテキストファイル(UTF-8推奨)で作成。
UsingRdotNet.dna
<DnaLibrary RuntimeVersion="v4.0" Name="R.NET" Description="R.NETをExcelから動作させる" Language="CS">
<Reference Path="ExcelDna.Integration.dll" />
<Reference Path="RDotNet.NativeLibrary.dll" />
<Reference Path="RDotNet.dll" />
<Reference Path="DynamicInterop.dll" />
<![CDATA[
using System;
using System.IO;
using System.Linq;
using ExcelDna.Integration;
using ExcelDna.Logging;
using RDotNet;
namespace UsingRDotNet
{
public static class MyFunctions
{
static REngine _engine;
static MyFunctions() // 静的コンストラクタ
{
try
{
REngine.SetEnvironmentVariables();
_engine = REngine.GetInstance();
_engine.Initialize();
}
catch (Exception ex)
{
LogDisplay.WriteLine("Error initializing RDotNet: " + ex.Message);
}
}
// Ctrl+Shift+Enter
public static double[] MyRnorm(int number)
{
return (_engine.Evaluate("rnorm(" + number + ")").AsNumeric().ToArray<double>());
}
public static object TestRDotNet()
{
// .NET Framework array to R vector.
NumericVector group1 = _engine.CreateNumericVector(new double[] { 30.02, 29.99, 30.11, 29.97, 30.01, 29.99 });
_engine.SetSymbol("group1", group1);
// Direct parsing from R script.
NumericVector group2 = _engine.Evaluate("group2 <- c(29.89, 29.93, 29.72, 29.98, 30.02, 29.98)").AsNumeric();
// Test difference of mean and get the P-value.
GenericVector testResult = _engine.Evaluate("t.test(group1, group2)").AsList();
double p = testResult["p.value"].AsNumeric().First();
return string.Format("Group1: [{0}], Group2: [{1}], P-value = {2:0.000}", string.Join(", ", group1), string.Join(", ", group2), p);
}
}
}
]]>
</DnaLibrary>
試し方
- 新規Excelブックを開く
- 上記ブックにUsingRdotNet.xllをドラッグ&ドロップし、「このアドインをこのセッションに限り有効にする」を選択
- セルに下記数式を入力
vbnet =TestRDotNet()
- セルの中身が#VALUE!にならなければ成功
- 別のセルを水平に5つ選択した後、
vbnet =MyRnorm(5)
と数式入力し、Ctrl + Shift + Enterを同時押しして「配列数式」にする - セルの中身が#NUM!にならずランダムな数値が5つ埋まっていれば成功
補記
環境によっては、使用するRのパスをREngine.GetInstance()で明示的に指定してやる必要があるようです。
DNAスクリプト(という言い方でいいのだろうか?)の問題点の切り分けにはLogDisplay.WriteLine()が非常に役に立ちました。