Excel-DNA で XLL を作る(その7)

 東日本大震災で被災された皆様に、心よりお見舞い申し上げます!
(ほんとにひどい震災でした。少なからずショックで・・・やっとこの言葉を書くことができました)
被災された方々のために、今だれにでも出来る一番身近なことといえば・・・やはり節電でしょう。
そこで・・・微力ながら今回は節電の精神を養うものを作成します!

 以前にも取り上げましたが、Excel-DNA には、ExcelDna.Integeration.dll という DLL が添付されていて、これを使うといろいろと機能の拡張が出来るようになっています。Excel-DNA で XLL を作る(その5)では、ExcelDna 名前空間の、Integration 名前空間にある、ExcelFunctionAttributeクラスと ExcelArgumentAttributeクラスを利用して、作成した関数が Excel で表示される際の情報をコントロールしてみました。今回は、Integration 名前空間にある、Rtd 名前空間を使います。Excel のワークシート関数にも RTDサーバーからデータを取り込む関数(RTD)がありますね♪
RTD というのは、RealTimeData サーバーのことです。あんまり、というか全然使ったことありませんが^^
ネット上にもあまり情報が見当たりません。そこで、今回は RTDサーバーについてほじくってみたいと思います(笑)

 どんなものを作るのかというと、流行りのWebAPI と、JSON を使って(もう古いか・・・)、
「ネット上から定期的にデータを取り込むRTDサーバーを作り、リアルタイムにExcel のシートを更新する」
処理を記述してみます(これが正しいRTDサーバーの使い方かどうかはわかりませんが)。

 使用する WebAPI は東京電力電力供給状況API です。

時刻:2011/4/6 10時台(10時~11時)
計画停電:実施無し
使用率:81.1%
消費電力:3285万kW
供給可能最大電力:4050万kW

上のような感じのデータを、リアルタイムにワークシートの片隅に表示します(笑) 
このAPI の仕様をみると、月・日付・時間指定でのデータも取得できるので、どかっとシート上にデータを取得してグラフ化したりしてみるのも良いかもしれませんね♪ 節電の精神が養われること請け合いです!

 今回利用する API は、JSON でデータ取得が出来ます。XML よりも軽いので良く使われていますが、JSON データを取り扱う処理までゴリゴリ書くのが面倒なので、DyanmicJson を使います。用意するのは、これだけです。

 さっそく作成してみましょう。
いつもどおりにクラスライブラリプロジェクトを作成します。プロジェクト名は「Tepco」 としました。このプロジェクトに、3つのクラスを作成します。

1.Data クラス ~ API にアクセスしてJSON データを解析し、データを保持する
2.TepcoServer クラス ~ RTD サーバーの実装
3.SavePower クラス ~ Excel に公開するメソッドを定義
(それぞれ、名前はなんでもいいのですが^^)

では、記述していきましょう。

1.Data クラス ~ API にアクセスしてJSON データを解析し、データを保持する
 東京電力電力供給状況API の仕様の中から、今回使用するデータをプロパティーとして設定します。このクラスは、TepcoServer クラスからも SavePower クラスからも共通して利用しますので、static(静的な)クラスとしました。データを更新するメソッド(Get) を実装し、Get メソッドを呼ぶと、各プロパティーを最新のデータに更新して保持します。
(こんな感じ↓)

using System;
using System.Net; // WebClient クラスを利用
using Codeplex.Data; // DyanamicJson クラスを利用(参照設定 DynamicJson.dll が必要)
using ExcelDna.Integration; // ExcelFunctionAttribute 属性を利用(参照設定 ExcelDna.Integration.dll が必要)

namespace Tepco
{
    public static class Data
    {
        public static string access_time; // データを取得した時刻
        public static string year;  // 対象期間の年
        public static string month; // 対象期間の月
        public static string day;  // 対象期間の日
        public static string hour; // 対象期間の時刻
        public static string capacity; // 供給可能電力量
        public static string usage; // 使用電力
        public static string saving; // 計画停電実施の有無
        [ExcelFunctionAttribute(IsHidden = true)]
        public static bool Get() // API からデータを取得・更新する
        {
            access_time = DateTime.Now.ToString();
            try
            {
       // API から JSON データを取得
                var json_data = new WebClient().DownloadString(@"http://tepco-usage-api.appspot.com/latest.json");
       // JSON データを DynamicJson で解析
                var status = DynamicJson.Parse(json_data);
       // 必要なデータを変数に代入
                if (status.year != null)
                {
                    year = status.year.ToString();
                }
                if (status.month != null)
                {
                    month = status.month.ToString();
                }
                if (status.day != null)
                {
                    day = status.day.ToString();
                }
                if (status.hour != null)
                {
                    hour = status.hour.ToString();
                }
                if (status.capacity != null)
                {
                    capacity = status.capacity.ToString();
                }
                if (status.usage != null)
                {
                    usage = status.usage.ToString();
                }
                if (status.saving != null)
                {
                    saving = status.saving.ToString();
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }
}

2.TepcoServer クラス ~ RTD サーバーの実装
 RTD サーバークラスは、ExcelDNA のRTDサンプルフォルダのファイルから必要な部分を流用しちゃいます(笑)
これで、RTD サーバーを作成する方法にある IRTDServer インターフェイスは実装されています♪
(こんな感じ↓)

using System;
using System.Windows.Forms; // Timer クラスを利用(参照設定 System.Windows.Forms が必要)
using ExcelDna.Integration.Rtd; // IRtdServer インターフェースを利用(参照設定 ExcelDna.Integration.dll が必要)

    public class TepcoServer : IRtdServer // IRtdServerインターフェースを継承
    {
        private IRTDUpdateEvent _callback; // コールバック変数
        private Timer _timer; // データ更新イベント発生用タイマ
        private int _topicId; // Excel から受け取る TopicID
        private const int INTERVAL = 300000; // 更新周期設定用定数 (ms)

        public object ConnectData(int topicId, ref Array Strings, ref bool GetNewValues)
        {
            _topicId = topicId;
            _timer.Start();
            return 1;
        }
        public void DisconnectData(int topicId)
        {
            _timer.Stop();
        }
        public int Heartbeat()
        {
            return 1;
        }
        public Array RefreshData(ref int topicCount)
        {
            Data.Get();
            object[,] results = new object[2, 1];
            results[0, 0] = _topicId;
            results[1, 0] = GetTime();
            topicCount = 1;
            _timer.Start();
            return results;
        }
        public int ServerStart(IRTDUpdateEvent CallbackObject)
        {
            Data.Get();
            _callback = CallbackObject;
            _timer = new Timer();
            _timer.Tick += Callback;
            _timer.Interval = INTERVAL;
            return 1;
        }
        public void ServerTerminate()
        {
            if (_timer != null)
            {
                _timer.Dispose();
                _timer = null;
            }
        }
        private string GetTime()
        {
            return DateTime.Now.ToString("HH:mm:ss.fff");
        }
        private void Callback(object sender, EventArgs e)
        {
            _timer.Stop();
            _callback.UpdateNotify();
        }
    }

上記のコードでは

 private const int INTERVAL = 300000; // 更新周期設定用定数( ms )


と、5分ごとにデータ更新を実行しています。API 作者さんの解説にもあるように、東京電力のサイトの更新は1時間に一度なので、5~10分ごとに更新すれば十分でしょう。というか、いずれの時刻でも15~30分 の間で更新されるようですのでその他の時刻に更新しても無駄です・・・(笑)

3.SavePower クラス ~ Excel に公開するメソッドを定義する
 最後に、Excel ワークシート関数として公開する関数を定義します。
(こんな感じ↓)

    public static class SavePower
    {
        [ExcelCommand(MenuName = "&TestOnRecalc", MenuText = "&Enable Beep")]
        public static void EnableBeep() //  更新時にビープ音を発生させるようにする
        {
            XlCall.Excel(XlCall.xlcOnRecalc, null, "Beep");
        }
        public static void Beep()  // ビープ音をならす
        {
            Console.Beep();
        }

        public static object AccessTime() // データ取得時刻を返す
        {
            object x = XlCall.RTD("TepcoServer", null, "");
            return Data.access_time;
        }
        public static object Span() // データの対象期間を返す
        {
            object x = XlCall.RTD("TepcoServer", null, "");
            return "時刻:" + Data.year + "/" + Data.month + "/" + Data.day + "/" +
                Data.hour + "時台 (" + Data.hour + "時~" + (int.Parse(Data.hour) + 1).ToString() + "時)";
        }
        public static object Saving() // 計画停電の有無を返す
        {
            object x = XlCall.RTD("TepcoServer", null, "");
            if (Data.saving == "False")
            {
                return "計画停電:実施無し";
            }
            return "計画停電:実施中";
        }
        public static object Percentage() // 使用電力の供給可能電力に対する比率を計算して返す
        {
            object x = XlCall.RTD("TepcoServer", null, "");
            double usage = double.Parse(Data.usage);
            double capacity = double.Parse(Data.capacity);
            return "使用率:" + (usage / capacity).ToString("P");
        }
        public static object Usage() // 使用電力量を返す
        {
            object x = XlCall.RTD("TepcoServer", null, "");
            return "消費電力:" + Data.usage + "万Kw";
        }
        public static object Capacity() // 供給可能電力量を返す
        {
            object x = XlCall.RTD("TepcoServer", null, "");
            return "供給可能最大電力:" + Data.capacity + "万Kw";
        }
    }

 以上で、完成です(笑) ビルドして実行してみましょう。 Tepco.dna ファイルにはこのように記述します。
(こんな感じ↓)

<DnaLibrary RuntimeVersion="v4.0">
<ExternalLibrary Path="Tepco.dll" /> 
</DnaLibrary>


(Excel x64 で動作させるためには、.Net4.0 が必要なので RuntimeVersion=”v4.0″ としています)

 作成したTepco.dll と同じフォルダに、Tepco.dna と Tepco.xll を置きます。Excel を開いて、Tepco.xll をドラッグ&ドロップします。「数式」→「関数の挿入」の一番下に、Tepco という分類が出来ているので、そこにある関数を入力してみましょう。
(こんな感じ↓)

 一時間に一度、東京電力の公開しているデータが更新されると、この表示は自動的に最新のものに更新されます。

いかがでしたか? ちゃんと動きましたか~? ちゃんと動いたら、ちゃんと節電してくださいね^^
(今回作成したプロジェクトはこちらからダウンロードできます。プロジェクトに含まれているTepco.xll は ExcelDna.xll の名前を変更したものです。Excel(x64)で利用する場合は、ExcelDna64.xll の名前を変更して利用してください。)

「WebAPI で JSON を取得・解析して、欲しいデータを Excel のシートにリアルタイムに表示する」
なんてことも、.NetFramework と Excel-DNA を使って簡単に出来ちゃいますね~♪
株価をリアルタイムで取得できる API があったら・・・。なんちゃって^^

さて、ちゃんと動いたところでPCの電源を落として節電することにします!(キリッ

では、また(笑)

カテゴリー: Excel, .NetFramework タグ: , , パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です