mengineer's blog

ニッチなネタばかりですが。

C#からExcelのLINEST関数を呼び出す

前回の続き、画像データを取り込む部分はC#でプログラムしているので、
C#からExcelの関数を呼び出してR2を取得する、というのが、今回のお題。

大きく、下記2つの手法が有るようです。

  1. Excel Object Library を使用する方法

  2. "ClosedXML"を使う方法

2.の方が扱いやすそうなのですが、C#の開発環境がVisualStudio2005と旧く(泣)、
ClosedXMLは未対応だったので、1.の方法で対応することにしました。

この場合ローカルにインストールされたExcelを使用するため、
異なるExcelバージョンの環境だと動きませんので要注意!

まず前準備として、C#のプロジェクトでExcelの参照設定が必要ですが、
c# excel 操作”等で検索すると、判りやすい説明が色々出てきます、
そちらを参照して下さい。(以下、その辺の内容は割愛しています)

Excelの関数を呼び出すには?

これも検索して下記の記事を発見しました、ずばりそのものビンゴ!

http://memo-memo-and-memo.asablo.jp/blog/2013/02/15/6721444

後半部分で、CoefficientsClassというクラスが有るので流用しました、
更にExcelアプリケーションの後始末の処理を追加したものが下記。

static public class CoefficientsClass
{
    static Excel.Application oXL = new Excel.Application();           //Excelアプリ本体
    static Excel.WorksheetFunction funk = oXL.WorksheetFunction;   //Excelの関数
    public static Array GetCoefficients(Array y, Array x, bool a, bool b)
    {
        System.Object coefficients = funk.LinEst(y, x, a, b);         //LINEST関数
        Array coeffArray = (Array)coefficients;
        return coeffArray;
    }
    public static void CloseExcelApp()
    {
    oXL.Quit();
        System.Runtime.InteropServices.Marshal.ReleaseComObject(oXL);
        oXL = null;
    }
}

oXLでExcelのアプリケーションを定義すると、oXL.WorksheetFunctionで、
Excelの任意の関数を呼び出せるようです、今回はLINEST関数を使いたいので、
GetCoefficients(Array y, Array x, bool a, bool b)内で、funk.LinEstを定義。

Excel同様に各パラメータを渡すと、計算結果(配列)がcoeffArrayに戻って来ます。

その都度Excelが起動することも無く、関数だけ呼べるので便利だったのですが、
タスクマネージャーにExcelのアプリが残ってしまう場合が有り、気になったので、
Excelを終了する処理を追加したのが、CloseExcelApp()の部分です。

簡単なソフトで試してみます、button1を押すと前回の簡単なサンプルデータ5個を
GetCoefficientsに渡して計算し、label1にR2の値を表示するもの。

f:id:mengineer:20160531123337p:plainf:id:mengineer:20160530222257p:plain

button1を押した時の処理です。

private void button1_Click(object sender, EventArgs e)
{
       label1.Text = "";
       int[,] X = new int[2, 5];       //X軸データ

       X[0, 0] = 1;                    //X
       X[0, 1] = 2;
       X[0, 2] = 3;
       X[0, 3] = 4;
       X[0, 4] = 5;

       X[1, 0] = 1;                    //Xの二乗
       X[1, 1] = 4;
       X[1, 2] = 9;
       X[1, 3] = 16;
       X[1, 4] = 25;

       int[] Y = new int[] { 11, 19, 30, 41, 48 }; //Y軸データ

       Array coeffArray = CoefficientsClass.GetCoefficients(Y, X, true, true);
       double R2 = (double)coeffArray.GetValue(3, 1);  //R2の値を取り出す
       label1.Text = R2.ToString("F4");
       CoefficientsClass.CloseExcelApp();              //Excel終了処理
}

Xは二次元配列で、X軸の値と二乗した値を入れます、YはY軸のデータをそのまま、
CoefficientsClass.GetCoefficients(Y, X, true, true); で、LINEST関数を実行します。

戻ってきたcoeffArrayから、R2をcoeffArray.GetValue(3, 1)で取り出し、
labelに表示させます、最後にCoefficientsClass.CloseExcelApp()で終了処理。

button1を押した後の画面がこちら、無事にR2を取得することが出来ました!

f:id:mengineer:20160531125142p:plain

当然、最初にExcelのグラフで表示させた結果とも合致しています。

f:id:mengineer:20160530201329p:plain

これにて一件落着、めでたしめでたし。