最近、経済関係の情報を入手するためのソフトウェアを作っているのですが、情報の配信がほとんどxlsファイルでちょっと困り気味。
サーバーでExcelを起動するわけにも行かず、なんかいい方法はないかと調べたらあっさりあった。
ただ、ちょっと面倒かもしれないのでまとめておきます。
ADO.NETを使う
さて、今回の方法はADO.NETを使う方法となります。多分、このページを見ている方ならADO.NETの存在も知っているという方も多いのではないでしょうか。
簡単に言えばデータベースの一種みたいなもの。SQL構文が使えれば簡単に扱う事ができます。
下準備
今回、ADO.NETでExcelファイル(.xls)ファイルを開くにあたってデータベースエンジンを用意しないといけません。
これはMicrosoftOffice Accessに同梱されているもの。「え?Accessなんて普段から使わないし買ってない」っていう方でも大丈夫。無料で配布されています。
Microsoft Access Database Engine 2010 Redistributable
http://www.microsoft.com/en-us/download/details.aspx?id=13255&lc=ja-jp
32ビット版と64ビット版がありますが、64ビットの環境なら64ビットの方がいいと思います。
読み込む
さて、スプレッドシートの形式がものによって違うため、少し前提条件を。
今回のサンプルコードは「東京証券取引所の空売り残高に関する情報」を取得します。
ちなみに形式はこんな感じ
今回のデータだと、データはB~P行、そしてデータは9行目から始まっています。
取得していく手順を順番に紹介して行きます。
xlsファイルに接続する
string path = "C:\test.xls"; string connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=\"Excel 12.0;HDR=YES\";"; connectionString = string.Format(connectionString, path); DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OleDb"); using (var xls_con = factory.CreateConnection()) { xls_con.ConnectionString = connectionString; xls_con.Open(); // .. }
まずADO.NETを使用して接続するにはDbProviderFactoryを使用してコネクションを生成します。
3行目の「string connectionString = …」の所の「Excel 12.0」の所を「Excel 9.0」にすると古いバージョンで接続するようになります。ただ、12.0でも古いバージョンは読み込めるので使用できるならば12.0の方がいいでしょう。
一覧を取得する
using (var com = xls_con.CreateCommand()) { com.CommandText = string.Format("SELECT * FROM [{0}$B:P]", 20150302); // データの日付 using (DbDataReader res = com.ExecuteReader()) { // 通常のデータベースと同じように取得できる } }
通常のSQLと同じように読み込みをすることができます。FROMに指定していしてあるのは「20150302」というシート名のB~P行を取得する。という意味です。
後は通常通りExecuteReaderでいつも通り取得すればいいだけです。res.Read()で次の行、次の行というふうに読み込むことができます。
ちなみに、カラム名はこの例だとほとんど名無しの列名になってしまっています。
なのでres[0]で日付、res[1]で銘柄コード…みたいにインデックスで指定して上げる必要があります。
あと列の名前を指定する方法…
大雑把な画像ですみません。Excelが編集できるソフトがパソコンにないものでして…
このような、1行目にヘッダーを指定してあるテーブルの場合、それが列名として扱うことができます。
例えば「あああ」のデータを取得したければres[“あああ”]で取得できるということです。
まとめ
ADO.NETを使えばExcelを起動しなくともxlsファイルを読み込むことができるということです。
その際にAccessのDBエンジンのインストールをお忘れなく。