読者です 読者をやめる 読者になる 読者になる

kurukuru-papaのブログ

主に、ソフトウェア開発に関連したメモを書き溜めたいと思います。

Excelファイル読み込み方法(遅延バインディング方式)

Visual C#にて、Excelファイルを読み込む処理を書いてみました。

ここでは、遅延バインディング方式と呼ばれる方法を使っています。これにより、実行時に、アプリケーションと、ExcelのDLL(Microsoft Excel XXX Object Library。XXXはバージョン)との参照設定が解決されることになるため、開発環境と実行環境にインストールされているExcelのバージョンが異なっていても動作する可能性があります。

たとえば、下記に紹介するプログラムは、Excel2007の環境で開発したのですが、その環境でビルドした実行ファイルを、Excel2003がインストールされている環境で動作させても正常に動きました。

ただし、Excelのバージョンが異なることで、プログラムの仕方も変わるような場合は、どこかで例外が発生すると思います。(試してはいないですが・・・)

using System;
using System.Collections;
using System.Reflection;

    /// <summary>
    /// Excelファイルを読み込む
    /// </summary>
    /// <param name="path">Excelファイルパス</param>
    public string ReadExcelFile(string path)
    {
        string result = "";
        object app = null;

        try
        {
            object[] args = null;

            // Excelアプリケーションを起動する
            Type classType = Type.GetTypeFromProgID("Excel.Application");
            app = Activator.CreateInstance(classType);

            // Excelファイルを開く
            object books = app.GetType().InvokeMember("Workbooks", BindingFlags.GetProperty, null, app, null);
            args = new object[15];
            args[0] = path;
            for (int i = 1; i < 15; i++)
            {
                args[i] = Type.Missing;
            }
            object book = books.GetType().InvokeMember("Open", BindingFlags.InvokeMethod, null, books, args);

            // ファイル内容を読み込む
            object sheets = book.GetType().InvokeMember("Sheets", BindingFlags.GetProperty, null, book, null);
            object sheetCount = sheets.GetType().InvokeMember("Count", BindingFlags.GetProperty, null, sheets, null);
            foreach (object sheet in (IEnumerable)sheets)
            {
                result += GetSheetContent(sheet);
            }
        }
        finally
        {
            if (app != null)
            {
                app.GetType().InvokeMember("Quit", BindingFlags.InvokeMethod, null, app, null);
            }
        }

        return result;
    }

    private string GetSheetContent(object sheet)
    {
        string result = "";
        object[] args = null;

        // シート名を取得する
        object sheetName = sheet.GetType().InvokeMember("Name", BindingFlags.GetProperty, null, sheet, null);
        result += "SheetName: " + sheetName + "\r\n";

        // 最終行、最終列を取得する
        // Excelを編集中の場合、正しい値を読み込めない場合がある。
        object cells = sheet.GetType().InvokeMember("Cells", BindingFlags.GetProperty, null, sheet, null);
        args = new object[2];
        args[0] = 11; //xlCellTypeLastCell
        args[1] = Type.Missing;
        object lastCell = cells.GetType().InvokeMember("SpecialCells", BindingFlags.InvokeMethod, null, cells, args);
        int maxRow = (int)lastCell.GetType().InvokeMember("Row", BindingFlags.GetProperty, null, lastCell, null);
        int maxColumn = (int)lastCell.GetType().InvokeMember("Column", BindingFlags.GetProperty, null, lastCell, null);

        // シートの内容をCSV形式で文字列化する。
        for (int row = 1; row <= maxRow; row++)
        {
            string line = "";
            for (int column = 1; column <= maxColumn; column++)
            {
                // セルのインデックスは、1始まり。
                args = new object[2];
                args[0] = row;
                args[1] = column;
                object cell = cells.GetType().InvokeMember("Item", BindingFlags.GetProperty, null, cells, args);

                if (column > 1)
                {
                    line += ", ";
                }
                object text = cell.GetType().InvokeMember("Text", BindingFlags.GetProperty, null, cell, null);
                line += text.ToString();
            }

            result += row + ": " + line + "\r\n";
        }

        return result;
    }

動作確認環境

  • OS : Windows 7
  • Excel : Version 2007
  • 開発環境 : Microsoft Visual C# 2008 Express Edition