LoginSignup
9
14

More than 5 years have passed since last update.

【C#】ClosedXMLでExcelテーブルをIEnumerable<T>オブジェクトに変換

Last updated at Posted at 2016-05-22
CodePage Name DisplayName Note
932 shift_jis Japanese (Shift-JIS)
20932 EUC-JP Japanese (JIS 0208-1990 and 0212-1990)
65001 utf-8 Unicode (UTF-8)

上記のようなテーブルのみ含むExcelファイルをencodings.xlsxという名前でCドライブ直下に保存した場合、下記コードでDisplayNameフィールドの値の一覧を表示することができる。

using ClosedXML.Excel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

class EncodingInfo
{
    public int CodePage { get; set; }
    public string Name { get; set; }
    public string DisplayName { get; set; }
}

class Sample
{
    public static void SetProperty<T>(T obj, string name, object value)
    {
        PropertyInfo property = typeof(T).GetProperty(name,
            BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);

        property?.SetValue(obj, Convert.ChangeType(value, property.PropertyType));
    }

    public static IEnumerable<T> ConvertExcelTable<T>(IXLTable table) where T : new()
    {
        var names = table.Fields.Select(field => field.Name).ToArray();

        foreach (var row in table.DataRange.Rows())
        {
            var obj = new T();
            foreach (var name in names)
            {
                SetProperty(obj, name, row.Field(name).Value);
            }
            yield return obj;
        }
    }

    public static void Main(string[] args)
    {
        var path = @"C:\encodings.xlsx";
        var workbook = new XLWorkbook(path);
        var worksheet = workbook.Worksheet(1);

        foreach(var encoding
            in ConvertExcelTable<EncodingInfo>(worksheet.RangeUsed().AsTable()))
        {
            Console.WriteLine(encoding.DisplayName);
        }
    }
}
  • Excelで数値型はSystem.Doubleであるため、int型プロパティにセットしようとするとSystem.ArgumentException例外が発生する。問題を回避するためにConvert.ChangeTypeメソッドを使用しているが、また別の条件で例外が発生する可能性は十分にある。
  • IXLWorksheet.RangeUsedメソッドは、シート内の使われている範囲のみを取得する便利なメソッド。
  • ConvertExcelTableメソッドの戻り値であるIEnumerable<T>の要素をすべて処理し終える前にworkbookもしくはworksheetを閉じると例外が発生すると思ったけれど、発生しない。具体的には、Mainメソッドの中身を以下に書き換えても問題なく動作する。
var path = @"C:\encodings.xlsx";

IEnumerable<EncodingInfo> enumerable;

using (var workbook = new XLWorkbook(path))
using (var worksheet = workbook.Worksheet(1))
{
    enumerable = ConvertExcelTable<EncodingInfo>(worksheet.RangeUsed().AsTable());
}

foreach (var encoding in enumerable)
{
    Console.WriteLine(encoding.DisplayName);
}
9
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
14