NPOIというExcelデータの読込み方法

仕事としてプログラミングをやってきて、18年経ちます。
プログラミングするときの心構えとして、読みやすく、短くを考慮してここまでやってきたんだけど、どうも自分のプログラミング記述は古いらしい。
長年やってきた当たり前の作り方が、ネットで「今、そんなやり方やってるのは少数!」とか言われる。
例えば…

  • VBなんてダメだC#の方がいい!とか・・・
  • コーディングはハンガリアン記法は使用禁止!とか・・・

自分が信じてここまでやってきた事が、プログラミング界隈でデスられててショックをうける。
でも、プログラムは読みやすく、処理が早く、修正するのが簡単という事を目指すべきだと思う。
なので、いろいろ変わっていくのは仕方ないし、自分が世界に合わせて勉強を続けるしかないな。

そんなプログラム技術で、最近ショックを受けたのがExcel読込み方法だ。
きっかけは、Excelファイルを C# と VB.NET で読み込む “正しい” 方法なのだけど、まさに18年間も不満に思いながらやってきた事が一気に解消されそうな方法だ。
せっかくなので、実際に使った様子をブログにまとめて見る。

今までの読込み「Microsoft.Office.Interop.Excel」の欠点

Excel読込みはお客様からよく要求される処理のひとつで、Excel一覧表からデータを抜き出してデータベースに更新したりする。
自分が今まで使用してきた記述は、「Microsoft.Office.Interop.Excel」というものなんだけど、これが結構やっかいなものだった。

この「Microsoft.Office.Interop.Excel」は、Excelのデータを読込むために、実際にExcelを起動して、セルの情報を取り出す流れになっている。
例えるなら、チョコレートの入った箱(エクセル)からチョコレートの数や種類(セル情報)を調べるために、箱のフタを開るということだ。
実世界なら当たり前の作業だけど、プログラミング世界ではめんどくさい問題が起きる。

まず、チョコレートの詰め合わせ箱を運んできて、フタを開ける動作が必要になる。
この作業に時間が掛るため、プログラムの処理が遅くなる。

次にチョコレートのフタを開ける方法を知っている人がいなくちゃいけない。
パソコンにExcelが入っていないといけないのだ。

そして、チョコレートを数えた終わった後に、箱を片付けないといつまでも残ってること。
プロセスというゴミがパソコンの中に残り、他の仕事の邪魔をしてしまう。

なので、「Microsoft.Office.Interop.Excel」という記述方法は、プログラムを使う上で「遅い」「Excelが必要」「片付けをする」のめんどくさい三重苦を抱えていた。

しかし、NPOIというモノがあった!

NPOIはApachePOI(アパッチ・ポイ)と言うWordやExcelを読み書きできるJavaのライブラリを.NET用に移植したものらしい。
ちなみにPOIは「Poor Obfuscation Implementation (質の悪い難読な実装)」の略らしく、プログラム記述の仕方を皮肉ってこうつけられたとのこと。

そんな名前の由来を持つPOIだけど、名前に似合わず「Microsoft.Office.Interop.Excel」の欠点をすべてクリア出来る。
つまり、チョコレートのフタを開けなくてもチョコレートの種類や数を調べることができて、誰でも箱を開けることができ、片付けもしなくていいわけだ。

導入方法はこちら…

ダウンロード

まずは、バイナリーパッケージをダウンロードしてくる。
https://npoi.codeplex.com/releases

VS(2013)を起動して、参照設定する

メニューの[プロジェクト]-[参照の追加]-[参照(B)…]

VBサンプルコード

''NPOIを使うために必要
Imports NPOI.SS.UserModel

    ''読込み
    Private Sub 読込み()
        Dim WB As IWorkbook = WorkbookFactory.Create("E:\[取込Excel名].xlsx")
        Dim WS As ISheet = WB.GetSheetAt(0)         ''最初のシート取得
        Dim iLastRow As Integer = WS.LastRowNum   ''シートの最終行数取得
    
        ''最終行まで読込み
        For iCount As Integer = 0 To iLastRow - 1
            Dim getRow As IRow = WS.GetRow(iCount) ''行取得
            Dim getCell = getRow.GetCell(0)         ''取得した行のA列取得

            ''セルにデータがあればメッセージ表示
            If getCell IsNot Nothing Then
                Console.WriteLine(getCell.StringCellValue)
            End If 
         Next 
     End Sub 

最後に

導入した感想としては「こいつは楽ちん」の一言。
ソースの長さが短くて、スッキリしてるのがとてもいい。

問題としては、マクロが組み込まれている場合に、エラーを起こすことがあるらしいが、それは今後使って見てどうなるかだろう。

取りあえず動作はしたので、実際に開発をして今後も検証してみたいと思います。
もしExcelの読み込みをする方がいたら参考にしてみて下さい。

 あなたの新しい一歩のお手伝いをします
岩間 崇

目次