DioDocs for Excel
DioDocs for Excel
データのインポート
機能 > データのインポート

新しいスプレッドシートやレポートを作成するために、オブジェクトコレクションやデータテーブルから任意のセル範囲にデータをインポートしたい場合があると思います。DioDocs for Excelでは、IRange インタフェースのImportData メソッドを使用することで、さまざまなデータソースからデータをインポートすることが可能です。ImportDataメソッドでは、以下の形式のデータソースをインポートできます。

DioDocs for Excelは、オブジェクトコレクションまたはデータテーブルから範囲にデータをインポートするために、以下のオーバーロードを持つImportDataメソッドを提供します:

オーバーロード パラメータ 説明
ImportData(IEnumerable items, DataImportOptions options = null) items

インポートするデータソース。インポート可能な形式については、前述の通り。

options

インポート時のオプション設定。詳細は後述。

ImportData(DataTable table, DataImportOptions options = null) table

インポートするDataTable。インポートできるDataTableの列データ型は以下の通り。

  • プリミティブ型: SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal, Boolean, DateTime, TimeSpan, CalcError.
  • Null許容 プリミティチE string またはTがプリミティブ型であるNullable{T}
options インポート時のオプション設定。詳細は後述。

オプション設定 オブジェクトコレクションやDataTableから範囲にデータをインポートする際の動作について、DataImportOptions クラスの以下のプロパティを通して設定できます。

プロパティ 説明
InsufficientSpaceHandling このプロパティは、データをインポートする際に十分なスペースがない場合の処理方法を決定します。
IncludeColumnHeader このプロパティは、データをインポートする際に、最初の行として列ヘッダを含めるかどうかを決定します。
ColumnsSelector このプロパティは、インポートする列を選択します。デフォルトではすべてのカラムがインポートされます。
ItemTypeProvider このプロパティは、指定されたSystem.Collections.IEnumerableから項目型を取得します。この型は列の自動生成に使用されます。デフォルトの動作は、generic type パラメータからアイテムの型を取得し、最初のアイテムの型を取得しようとします。

メモ: データのインポートを行う場合、以下の内容に従うことを推奨します。

メモ: DioDocs for Excelでは、コードをクリーンに保つためにオプションビルダーを書くことを推奨しています。詳細については、Builder パターンをご覧ください。


単純な配列を垂直方向にインポートする

単純な配列を垂直方向にインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
// 新しいワークブックを生成します
var workbook = new Workbook();

// 先頭のワークシートを取得します
var worksheet = workbook.Worksheets[0];

// 数値型の一次元配列を生成します
var doubleData = new double[] { 1, 2, 3, 4, 5 };

// 配列を垂直方向にインポートします
worksheet.Range["A1:A5"].ImportData(doubleData);

// ワークブックを保存します
workbook.Save("ImportSimpleEnumerableVertically.xlsx");


単純な配列を水平方向にインポートする

単純な配列を水平方向にインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
// 新しいワークブックを生成します
var workbook = new Workbook();

// 先頭のワークシートを取得します
var worksheet = workbook.Worksheets[0];

// 数値型の一次元配列を生成します
var doubleData = new double[] { 1, 2, 3, 4, 5 };

// 配列を水平方向にインポートします
worksheet.Range["A1:E1"].ImportData(doubleData);

// ワークブックを保存します
workbook.Save("ImportSimpleEnumerableHorizontally.xlsx");


一次元データをインポートする

1次元のデータをインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
// 新しいワークブックを生成します
var workbook = new Workbook();

// ワークブックのカルチャを日本語(JP)に設定します
workbook.Culture = CultureInfo.GetCultureInfo("ja-JP");
var sheet1 = workbook.Worksheets["Sheet1"];
sheet1.Name = "Import1DData";
            
// セル範囲に値を設定します
sheet1.Range["A1"].Value = "Tour Budget Table";

// セル範囲が垂直方向でない場合、一次元配列を水平方向にインポートします
var titles = new[] { "Employee ID", "Adults", "Children", "Rooms", "Spa", "Hotpot", "Budget" };
sheet1.Range["A2:G2"].ImportData(titles);

// テストデータを生成します
var rnd = new Random(1234);
const int rowCount = 20;
var uids = Enumerable.Repeat(0, rowCount).Select(i => rnd.Next(10000, 99999)).ToArray();
var adults = Enumerable.Repeat(0, rowCount).Select(i => rnd.Next(1, 4)).ToArray();
var children = Enumerable.Repeat(0, rowCount).Select(i => rnd.Next(0, 3)).ToArray();
var rooms = adults.Zip(children, (adult, child) => (adult + child) / 2).ToList();
var spa = adults.Zip(children, (adult, child) => Math.Ceiling((adult + child) * rnd.NextDouble())).ToArray();
var hotpot = adults.Zip(children, (adult, child) => adult + child).ToArray();

const int budgetBase = 750;
var budget =
    from i in Enumerable.Range(0, rowCount)
    let adult = adults[i]
    let child = children[i]
    let room = rooms[i]
    let sp = spa[i]
    let hot = hotpot[i]
    select adult * 200 + child * 100 + room * 400 + sp * 188 + hot * 233 + budgetBase;

// 列ごとにデータをインポートします
/* "rooms"はリストです。一次元配列のようにインポートされます
   "budget"はLINQ結果です。こちらも一次元配列のようにインポートされます。 */
var columns = new IEnumerable[] { uids, adults, children, rooms, spa, hotpot, budget };
for (int i = 0; i < columns.Length; i++)
{
    // セル範囲が垂直方向の場合、一次元配列/リストは垂直方向にインポートされます
    sheet1.Range[2, i, 2, 1].ImportData(columns[i]);
}

// セル範囲のスタイルを設定します
sheet1.Range[1, 0, 1, 7].Style = workbook.Styles["Heading 3"];
sheet1.Range[2, 0, rowCount, 7].Style = workbook.Styles["20% - Accent1"];
sheet1.Range[1, 0, 1, 7].EntireColumn.AutoFit();
sheet1.Range["A1"].Style = workbook.Styles["Heading 1"];
sheet1.Range["1:2"].AutoFit();

// ワークブックを保存します
workbook.Save("Import1DData.xlsx");


二次元データをインポートする

2次元のデータをインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
// 新しいワークブックを生成します
var workbook = new Workbook();

// ワークブックのカルチャを日本語(JP)に設定します
workbook.Culture = CultureInfo.GetCultureInfo("ja-JP");
var sheet1 = workbook.Worksheets["Sheet1"];
sheet1.Name = "Import2DData";
sheet1.Range["A1"].Value = "Tour Budget Table";

// 二次元配列をタイトルとしてインポートします
var titles = new string[,] { { "Employee ID", "Adults", "Children", "Rooms", "Spa", "Hotpot", "Budget" } };
sheet1.Range["A2"].ImportData(titles);

// テストデータを生成します
var rnd = new Random(1234);
const int rowCount = 20;

// 二次元配列からデータをインポートします
var numbers = new double[rowCount, 7];
for (int i = 0; i < rowCount; i++)
{
    int employeeId = rnd.Next(10000, 99999);
    int adults = rnd.Next(1, 4);
    int children = rnd.Next(0, 3);
    int rooms = (adults + children) / 2;
    double spa = Math.Ceiling((adults + children) * rnd.NextDouble());
    int hotpot = adults + children;
    double budget = adults * 200 + children * 100 + rooms * 400 + spa * 188 + hotpot * 233 + 750;

    numbers[i, 0] = employeeId;
    numbers[i, 1] = adults;
    numbers[i, 2] = children;
    numbers[i, 3] = rooms;
    numbers[i, 4] = spa;
    numbers[i, 5] = hotpot;
    numbers[i, 6] = budget;
}
var result = sheet1.Range["A3"].ImportData(numbers);

// セル範囲のスタイルを設定します
sheet1.Range[1, 0, 1, result.ColumnsImported].Style = workbook.Styles["Heading 3"];
sheet1.Range[2, 0, result.RowsImported, result.ColumnsImported].Style = workbook.Styles["20% - Accent1"];
sheet1.Range[1, 0, 1, result.ColumnsImported].EntireColumn.AutoFit();
sheet1.Range["A1"].Style = workbook.Styles["Heading 1"];
sheet1.Range["1:2"].AutoFit();
sheet1.Range[2, 6, result.RowsImported, 1].NumberFormat = "$#,##0.00";
sheet1.Range[2, 6, result.RowsImported, 1].EntireColumn.ColumnWidth = 10;

// ワークブックを保存します
workbook.Save("Import2DData.xlsx");


多次元配列をインポートする

多次元配列をインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
            // 新しいワークブックを生成します
            var workbook = new Workbook();

            // 先頭のワークシートを取得します
            var worksheet = workbook.Worksheets[0];

            // 多次元配列を生成します
            var doubleDataMt = new double[][,]
{
                new double [,] {
                    { 1, 2, 3 },
                    { 4, 5, 6 },
                    { 7, 8, 9 }
                },
                new double [,] {
                    { 10, 11, 12 },
                    { 13, 14, 15 },
                    { 16, 17, 18 }
                },
                new double [,] {
                    { 19, 20, 21 },
                    { 22, 23, 24 },
                    { 25, 26, 27 }
                }
            };

            // 多次元配列をインポートします
            int startRow = 0;
            foreach (var item in doubleDataMt)
            {
                // ワークシートは多次元配列をサポートしません。
                // しかしながら、内部配列を1つずつワークシート上に展開します。
                var imported = worksheet.Range[startRow, 0].ImportData(item);
                startRow += imported.RowsImported;
            }

            // ワークブックを保存します
            workbook.Save("ImportMultidimensionalArray.xlsx");


ジャグ配列をインポートする

ジャグ配列(配列を要素とする配列)をインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
            // 新しいワークブックを生成します
            var workbook = new Workbook();

            // 先頭のワークシートを取得します
            var worksheet = workbook.Worksheets[0];

            // ジャグ配列を生成します
            var doubleDataJagged = new double[][]
{
                new double[] { 1, 2, 3 },
                new double[] { 4, 5 },
                new double[] { 7, 8, 9 }
            };
            
            // 内部配列の要素数が異なっても問題ありません。
            // ただし、パフォーマンスを向上させる場合、各内部配列の要素数を合わせ、二次元配列とすることをお勧めします。
            worksheet.Range["A1"].ImportData(doubleDataJagged);

            // ワークブックを保存します
            workbook.Save("ImportJaggedArrays.xlsx");


エンティティデータをインポートする

エンティティからデータをインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
class Program
{
    static void Main(string[] args)
    {
        // 新しいワークブックを生成します
        var workbook = new Workbook();

        // ワークブックのカルチャを日本語(JP)に設定します
        workbook.Culture = CultureInfo.GetCultureInfo("ja-JP");
        var sheet1 = workbook.Worksheets["Sheet1"];
        sheet1.Name = "ImportEntities";
        sheet1.Range["A1"].Value = "Tour Budget Table";

        // テストデータを生成します
        var rnd = new Random(1234);
        const int rowCount = 20;

        // "TourBudget"エンティティのリストを生成します
        var tourBudgets = new List<TourBudget>();

        for (int i = 0; i < rowCount; i++)
        {
            int employeeId = rnd.Next(10000, 99999);
            int adults = rnd.Next(1, 4);
            int children = rnd.Next(0, 3);
            int rooms = (adults + children) / 2;
            double spa = Math.Ceiling((adults + children) * rnd.NextDouble());
            int hotpot = adults + children;
            double budget = adults * 200 + children * 100 + rooms * 400 + spa * 188 + hotpot * 233 + 750;

            // エンティティをリストに追加します
            tourBudgets.Add(new TourBudget
            {
                EmployeeID = employeeId,
                Adults = adults,
                Children = children,
                Rooms = rooms,
                Spa = spa,
                Hotpot = hotpot,
                Budget = budget
            });
        }

        // リストをワークシートにインポートします
        var result = sheet1.Range["A2"].ImportData(tourBudgets);

        // セル範囲のスタイルを設定します
        sheet1.Range[1, 0, 1, result.ColumnsImported].Style = workbook.Styles["Heading 3"];
        sheet1.Range[2, 0, result.RowsImported - 1, result.ColumnsImported].Style = workbook.Styles["20% - Accent1"];
        sheet1.Range[1, 0, result.RowsImported, result.ColumnsImported].EntireColumn.AutoFit();
        sheet1.Range["A1"].Style = workbook.Styles["Heading 1"];
        sheet1.Range["1:2"].AutoFit();
        sheet1.Range[2, 6, result.RowsImported, 1].NumberFormat = "$#,##0.00";
        sheet1.Range[2, 6, result.RowsImported, 1].EntireColumn.ColumnWidth = 10;

        // ワークブックを保存します
        workbook.Save("ImportDataFromEntities.xlsx");

    }


}

// エンティティのためのクラスを定義します
public class TourBudget
{
    public int EmployeeID { get; set; }
    public int Adults { get; set; }
    public int Children { get; set; }
    public int Rooms { get; set; }
    public double Spa { get; set; }
    public int Hotpot { get; set; }
    public double Budget { get; set; }
}


エンティティデータをフィルタしてインポートする

行と列を選択してインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
class Program
{
    static void Main(string[] args)
    {
        // 新しいワークブックを生成します
        var workbook = new Workbook();

        // ワークブックのカルチャを日本語(JP)に設定します
        workbook.Culture = CultureInfo.GetCultureInfo("ja-JP");
        var sheet1 = workbook.Worksheets["Sheet1"];
        sheet1.Name = "ImportEntities";
        sheet1.Range["A1"].Value = "Tour Budget Table";

        // テストデータを生成します
        var rnd = new Random(1234);
        const int rowCount = 20;

        // "TourBudget"エンティティのリストを生成します
        var tourBudgets = new List<TourBudget>();

        for (int i = 0; i < rowCount; i++)
        {
            int employeeId = rnd.Next(10000, 99999);
            int adults = rnd.Next(1, 4);
            int children = rnd.Next(0, 3);
            int rooms = (adults + children) / 2;
            double spa = Math.Ceiling((adults + children) * rnd.NextDouble());
            int hotpot = adults + children;
            double budget = adults * 200 + children * 100 + rooms * 400 + spa * 188 + hotpot * 233 + 750;

            // エンティティをリストに追加します
            tourBudgets.Add(new TourBudget
            {
                EmployeeID = employeeId,
                Adults = adults,
                Children = children,
                Rooms = rooms,
                Spa = spa,
                Hotpot = hotpot,
                Budget = budget
            });
        }

        // "budget"の値が高い順に並べ、上位5行を取得します
        var top5 = tourBudgets.OrderByDescending(t => t.Budget).Take(5);

        // 取得結果をインポートします。
        // (特定の項目のみ、カスタマイズしたヘッダー付きで表示します).
        var result = sheet1.Range["A2"].ImportData(top5, new DataImportOptions
        {
            ColumnsSelector = items =>
            {
                if (!(items is IEnumerable<TourBudget>)) return null;
                return new (string, Delegate)[]
                {
                ("Employee ID", new Func<TourBudget, int>(item => item.EmployeeID)),
                ("Adults", new Func<TourBudget, int>(item => item.Adults)),
                ("Children", new Func<TourBudget, int>(item => item.Children)),
                ("Budget", new Func<TourBudget, double>(item => item.Budget))
                };
            }
        });

        // セル範囲のスタイルを設定します
        sheet1.Range[1, 0, 1, result.ColumnsImported].Style = workbook.Styles["Heading 3"];
        sheet1.Range[2, 0, result.RowsImported - 1, result.ColumnsImported].Style = workbook.Styles["20% - Accent1"];
        sheet1.Range[1, 0, result.RowsImported, result.ColumnsImported].EntireColumn.AutoFit();
        sheet1.Range["A1"].Style = workbook.Styles["Heading 1"];
        sheet1.Range["1:2"].AutoFit();
        sheet1.Range[2, 3, result.RowsImported, 1].NumberFormat = "$#,##0.00";
        sheet1.Range[2, 3, result.RowsImported, 1].EntireColumn.ColumnWidth = 10;

        // ワークブックを保存します
        workbook.Save("ImportDataFromEntitiesSelectRowsColumns.xlsx");
    }


}

// エンティティのためのクラスを定義します
public class TourBudget
{
    public int EmployeeID { get; set; }
    public int Adults { get; set; }
    public int Children { get; set; }
    public int Rooms { get; set; }
    public double Spa { get; set; }
    public int Hotpot { get; set; }
    public double Budget { get; set; }
}


Option Builderを使用してエンティティデータをインポートする

"Builder"デザインパターンを使用して行と列を選択し、データをインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
class Program
{
    static void Main(string[] args)
    {
        // 新しいワークブックを生成します
        var workbook = new Workbook();

        // ワークブックのカルチャを日本語(JP)に設定します
        workbook.Culture = CultureInfo.GetCultureInfo("ja-JP");
        var sheet1 = workbook.Worksheets["Sheet1"];
        sheet1.Name = "DataImportOptionsBuilder";
        sheet1.Range["A1"].Value = "GPU Performance Test Result";
        sheet1.Range["A1:B1"].Merge();
        sheet1.Range["A1:B1"].Style = workbook.Styles["Heading 1"];

        // テストデータを生成します
        var frameRateResults = new FrameRateTestResult[]
        {
        new FrameRateTestResult { GpuName = "GeForce RTX 4090", FrameRate = 154.1, Workload = "1080p Ultra" },
        new FrameRateTestResult { GpuName = "Radeon RX 7900 XTX", FrameRate = 149.0, Workload = "1080p Ultra" },
        new FrameRateTestResult { GpuName = "GeForce RTX 4080 Super", FrameRate = 148.3, Workload = "1080p Ultra" },
        new FrameRateTestResult { GpuName = "Radeon RX 7900 XT", FrameRate = 143.9, Workload = "1080p Ultra" },
        new FrameRateTestResult { GpuName = "GeForce RTX 4090", FrameRate = 146.1, Workload = "1440p Ultra" },
        new FrameRateTestResult { GpuName = "Radeon RX 7900 XTX", FrameRate = 135.3, Workload = "1440p Ultra" },
        new FrameRateTestResult { GpuName = "GeForce RTX 4080 Super", FrameRate = 133.0, Workload = "1440p Ultra" },
        new FrameRateTestResult { GpuName = "Radeon RX 7900 XT", FrameRate = 125.9, Workload = "1440p Ultra" },
        new FrameRateTestResult { GpuName = "GeForce RTX 4090", FrameRate = 114.5, Workload = "4K Ultra" },
        new FrameRateTestResult { GpuName = "Radeon RX 7900 XTX", FrameRate = 95.1, Workload = "4K Ultra" },
        new FrameRateTestResult { GpuName = "GeForce RTX 4080 Super", FrameRate = 91.9, Workload = "4K Ultra" },
        new FrameRateTestResult { GpuName = "Radeon RX 7900 XT", FrameRate = 81.2, Workload = "4K Ultra" },
        };

        // DataImportOptionsBuilderクラスを使用してインポート設定を定義します。
        // メモ:このサンプルコード内ではDataImportOptionsBuilderクラスはカスタムクラスです。パブリックAPIではありません。.
        double maxFrameRateOfGroup = 0;
        var importOptions = new DataImportOptionsBuilder()
            .HasColumnsSelector<FrameRateTestResult>(it => it
                .Bind("Graphics Card", item => item.GpuName)
                .Bind("Frame Rate", item => $"{item.FrameRate / maxFrameRateOfGroup:P1}({item.FrameRate:N1}fps)"))
            .Build();

        // グループ化されたデータをインポートし、スタイルを適用します
        int curRow = 2;

        // (フレームレートの結果をワークロードごとにグループ化します)
        var groupedResults = frameRateResults.GroupBy(it => it.Workload);

        foreach (var group in groupedResults)
        {
            // (グループヘッダを設定します)
            sheet1.Range[curRow, 0].Value = group.Key;
            sheet1.Range[curRow, 0].Style = workbook.Styles["Heading 2"];
            curRow++;

            // (データをフレームレートの降順で並べ替え、最大フレームレートを更新します)
            var sortedData = group.OrderByDescending(it => it.FrameRate);
            maxFrameRateOfGroup = group.Max(it => it.FrameRate);

            // (オプション設定にしたがってインポートします)
            DataImportResult result = sheet1.Range[curRow, 0].ImportData(sortedData, importOptions);

            // (インポートされたセル範囲にスタイルを設定します)
            sheet1.Range[curRow, 0, 1, result.ColumnsImported].Style = workbook.Styles["Accent1"];
            curRow += result.RowsImported + 1;
        }

        // 範囲のレイアウトを調整します
        var usedRange = sheet1.UsedRange;
        usedRange.EntireRow.AutoFit();
        usedRange.EntireColumn.AutoFit();

        // ワークブックを保存します
        workbook.Save("ImportDataFromEntitiesSelectRowsColumnsBuilder.xlsx");

    }


}

// エンティティのためのクラスを定義します
public class FrameRateTestResult
{
    public string GpuName { get; set; }
    public double FrameRate { get; set; }
    public string Workload { get; set; }
}

// 複雑なカスタムインポート設定を行うためのDataImportOptionsBuilderクラスを定義します
public class DataImportOptionsBuilder
{
    private readonly List<Func<object, IEnumerable>> _columnsSelectors = new List<Func<object, IEnumerable>>();
    private bool _includeColumnsHeader = true;
    private InsufficientSpaceHandling _insufficientSpaceHandling;
    private readonly List<Func<IEnumerable, Type>> _itemTypeProviders = new List<Func<IEnumerable, Type>>();

    public DataImportOptionsBuilder HasColumnsSelector<TObject>(Action<ObjectColumnSelectorBuilder<TObject>> configureSelector)
    {
        var builder = new ObjectColumnSelectorBuilder<TObject>();
        configureSelector(builder);
        _columnsSelectors.Add(builder.Build());
        return this;
    }

    public DataImportOptionsBuilder HasColumnsSelector(Predicate<object> collectionCheck, params int[] indexes)
    {
        _columnsSelectors.Add(items => collectionCheck(items) ? indexes : null);
        return this;
    }

    public DataImportOptionsBuilder HasColumnsSelector(Predicate<object> collectionCheck, params string[] indexes)
    {
        _columnsSelectors.Add(items => collectionCheck(items) ? indexes : null);
        return this;
    }

    public DataImportOptionsBuilder HasColumnsSelector(Predicate<object> collectionCheck, params DataColumn[] indexes)
    {
        _columnsSelectors.Add(items => collectionCheck(items) ? indexes : null);
        return this;
    }

    public DataImportOptionsBuilder ExcludeColumnsHeader()
    {
        _includeColumnsHeader = false;
        return this;
    }

    public DataImportOptionsBuilder OnInsufficientSpace(InsufficientSpaceHandling handling)
    {
        _insufficientSpaceHandling = handling;
        return this;
    }

    public DataImportOptionsBuilder HasItemTypeProvider(Action<ItemTypeProviderBuilder> configureProvider)
    {
        var builder = new ItemTypeProviderBuilder();
        configureProvider(builder);
        _itemTypeProviders.Add(builder.Build());
        return this;
    }

    public DataImportOptions Build()
    {
        return new DataImportOptions
        {
            ColumnsSelector = _columnsSelectors.Count > 0
                ? new Func<object, IEnumerable>(obj => _columnsSelectors
                    .Select(selector => selector(obj))
                    .FirstOrDefault(result => result != null))
                : null,
            IncludeColumnsHeader = _includeColumnsHeader,
            InsufficientSpaceHandling = _insufficientSpaceHandling,
            ItemTypeProvider = _itemTypeProviders.Count > 0
                ? new Func<IEnumerable, Type>(obj => _itemTypeProviders
                    .Select(prov => prov(obj))
                    .FirstOrDefault(itemType => itemType != null))
                : null
        };
    }
}

public class ObjectColumnSelectorBuilder<T>
{
    private readonly List<(string, Delegate)> _items = new List<(string, Delegate)>();
    private readonly List<Delegate> _anonymous = new List<Delegate>();

    public ObjectColumnSelectorBuilder<T> Bind<TProperty>(string displayName, Func<T, TProperty> getter)
    {
        _items.Add((displayName, getter));
        return this;
    }

    public ObjectColumnSelectorBuilder<T> BindAnonymous<TProperty>(Func<T, TProperty> getter)
    {
        _anonymous.Add(getter);
        return this;
    }

    public Func<object, IEnumerable> Build()
    {
        return items => items is IEnumerable<T>
            ? _items.Count == 0 ? (IEnumerable)_anonymous : _items
            : null;
    }
}

public class ItemTypeProviderBuilder
{
    private readonly List<Func<IEnumerable, Type>> _itemTypeProvider = new List<Func<IEnumerable, Type>>();

    public ItemTypeProviderBuilder ProvideItemType(Func<IEnumerable, Type> itemTypeProvider)
    {
        _itemTypeProvider.Add(itemTypeProvider);
        return this;
    }

    public Func<IEnumerable, Type> Build()
    {
        return item => _itemTypeProvider
            .Select(prov => prov(item))
            .FirstOrDefault(it => it != null);
    }
}


カスタムオブジェクトからデータをインポートする

弱く型指定されたコレクションのカスタムオブジェクトからデータをインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
internal class Program
{
    static void Main(string[] args)
    {
        // 新しいワークブックを生成します
        var workbook = new Workbook();

        // 先頭のワークシートを取得します
        var worksheet = workbook.Worksheets[0];

        // カスタムオブジェクトを生成します("Cat"クラスと"Dog"クラス)
        var cat1 = new Cat
        {
            Name = "Christopher",
            Age = 3,
            IsIndoor = true,
            FavoriteToy = "Feather Whip"
        };
        var cat2 = new Cat
        {
            Name = "Richter",
            Age = 2,
            IsIndoor = false,
            FavoriteToy = "Laser Pointer"
        };
        var dog1 = new Dog
        {
            Name = "Julius",
            Age = 5,
            IsTrained = true
        };
        var dog2 = new Dog
        {
            Name = "Leon",
            Age = 4,
            IsTrained = false
        };

        // ArrayListを生成します
        var animals = new ArrayList { cat1, cat2, dog1, dog2 };

        // コレクションからデータをインポートします
        worksheet.Range["A1"].ImportData(animals, new DataImportOptions
        {
            ItemTypeProvider = items =>
            {
                // 項目は弱く型指定されたコレクション内に格納されています。
                // デフォルトの型は最初の項目で決定されますが、オーバーライドされます。.
                if (items.Cast<object>().FirstOrDefault() is Animal)
                {
                    return typeof(Animal);
                }
                return null;
            }
        });

        // ワークブックを保存します
        workbook.Save("ImportCustomObjectsfromWeaklyTypedCollection.xlsx");
    }
}

// "Animal"クラスを定義します
class Animal
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// "Animal"クラスを継承して、"Cat"クラスを定義します
class Cat : Animal
{
    public bool IsIndoor { get; set; }
    public string FavoriteToy { get; set; }
}

// "Animal"クラスを継承して、"Dog"クラスを定義します
class Dog : Animal
{
    public bool IsTrained { get; set; }
}


型が不明なカスタムオブジェクトからデータをインポートする

型が不明な(ダック・タイピングな)コレクションのカスタムオブジェクトからデータをインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
internal class Program
{
    static void Main(string[] args)
    {
        // 新しいワークブックを生成します
        var workbook = new Workbook();

        // 先頭のワークシートを取得します
        var worksheet = workbook.Worksheets[0];

        // カスタムオブジェクトを生成します("Cat"クラスと"Dog"クラス)
        var cat1 = new Cat
        {
            Name = "Christopher",
            Age = 3,
            IsIndoor = true,
            FavoriteToy = "Feather Whip"
        };
        var cat2 = new Cat
        {
            Name = "Richter",
            Age = 2,
            IsIndoor = false,
            FavoriteToy = "Laser Pointer"
        };
        var dog1 = new Dog
        {
            Name = "Julius",
            Age = 5,
            IsTrained = true
        };
        var dog2 = new Dog
        {
            Name = "Leon",
            Age = 4,
            IsTrained = false
        };

        // ArrayListを生成します
        var animals = new ArrayList { cat1, cat2, dog1, dog2 };

        // コレクションからデータをインポートします
        worksheet.Range["A1"].ImportData(animals, new DataImportOptions
        {
            ItemTypeProvider = items => typeof(object),
            ColumnsSelector = items =>
            {
                return new string[]
                {
                    nameof(Animal.Name), nameof(Animal.Age),
                    nameof(Cat.IsIndoor), nameof(Cat.FavoriteToy),
                    nameof(Dog.IsTrained)
                };
            }
        });

        // ワークブックを保存します
        workbook.Save("ImportDatafromUnknownTypeofCustomObjectsDuckTyping.xlsx");
    }
}

// "Animal"クラスを定義します
class Animal
{
    public string Name { get; set; }
    public int Age { get; set; }
}

// "Animal"クラスを継承して、"Cat"クラスを定義します
class Cat : Animal
{
    public bool IsIndoor { get; set; }
    public string FavoriteToy { get; set; }
}

// "Animal"クラスを継承して、"Dog"クラスを定義します
class Dog : Animal
{
    public bool IsTrained { get; set; }
}


動的オブジェクトをインポートする

動的オブジェクトからデータをインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
// 新しいワークブックを生成します
var workbook = new Workbook();

// 先頭のワークシートを取得します
var worksheet = workbook.Worksheets[0];

// ディクショナリを生成します
var customers = new Dictionary<string, object>[]
{
    new Dictionary<string, object> { { "CustomerID", 1 }, { "Name", "John" }, { "CompanyName", "Arasaka"  }, { "Contact", "john240891@arasaka.co.jp"} },
    new Dictionary<string, object> { { "CustomerID", 2 }, { "Name", "Mary" }, { "CompanyName", "Militech" }, { "Contact", "mary327670@militech.com" } },
};

// ディクショナリからデータをインポートします
worksheet.Range["A1"].ImportData(customers,
    new DataImportOptions
    {
        ColumnsSelector = items =>
        {
            if (items is Dictionary<string, object>[])
            {
                // ディクショナリは動的オブジェクトとして扱われます。
                // 結果を取得するためには列名を明示的に設定する必要があります。
                // (キーは順番が一定ではなく、値も存在しない場合があるため)
                return new[] { "CustomerID", "Name", "CompanyName", "Contact" };
            }
            return null;
        }
    });

// ワークブックを保存します
workbook.Save("ImportDynamicObjects.xlsx");


DataTableをインポートする

DataTableからデータをインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
// 新しいワークブックを生成します
var workbook = new Workbook();

// ワークブックのカルチャを日本語(JP)に設定します
workbook.Culture = CultureInfo.GetCultureInfo("ja-JP");
var sheet1 = workbook.Worksheets["Sheet1"];
sheet1.Name = "ImportDataTable";
sheet1.Range["A1"].Value = "Tour Budget Table";

// DataTableを生成し、列を定義します
var dataTable = new DataTable();
dataTable.Columns.Add("EmployeeID", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Adults", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Children", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Rooms", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Spa", typeof(double)).AllowDBNull = false;
dataTable.Columns.Add("Hotpot", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Budget", typeof(double)).AllowDBNull = false;

// テストデータを生成します
var rnd = new Random(1234);
const int rowCount = 20;

for (int i = 0; i < rowCount; i++)
{
    int employeeId = rnd.Next(10000, 99999);
    int adults = rnd.Next(1, 4);
    int children = rnd.Next(0, 3);
    int rooms = (int)Math.Floor((adults + children) / 2.0);
    double spa = Math.Ceiling((adults + children) * rnd.NextDouble());
    int hotpot = adults + children;
    double budget = adults * 200 + children * 100 + rooms * 400 + spa * 188 + hotpot * 233 + 750;

    // DataTableに行を追加します
    dataTable.Rows.Add(employeeId, adults, children, rooms, spa, hotpot, budget);
}

// DataTableからデータをインポートします
var result = sheet1.Range["A2"].ImportData(dataTable);

// セル範囲のスタイルを設定します
sheet1.Range[1, 0, 1, result.ColumnsImported].Style = workbook.Styles["Heading 3"];
sheet1.Range[2, 0, result.RowsImported - 1, result.ColumnsImported].Style = workbook.Styles["20% - Accent1"];
sheet1.Range[1, 0, result.RowsImported, result.ColumnsImported].EntireColumn.AutoFit();
sheet1.Range["A1"].Style = workbook.Styles["Heading 1"];
sheet1.Range["1:2"].AutoFit();
sheet1.Range[2, 6, result.RowsImported, 1].NumberFormat = "$#,##0.00";
sheet1.Range[2, 6, result.RowsImported, 1].EntireColumn.ColumnWidth = 10;

// ワークブックを保存します
workbook.Save("ImportDataTable.xlsx");


DataViewからデータをインポートする

DataViewからデータをインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
// 新しいワークブックを生成します
var workbook = new Workbook();

// ワークブックのカルチャを日本語(JP)に設定します
workbook.Culture = CultureInfo.GetCultureInfo("ja-JP");
var sheet1 = workbook.Worksheets["Sheet1"];
sheet1.Name = "ImportDataView";
sheet1.Range["A1"].Value = "Tour Budget Table";

// DataTableを生成し、列を定義します
var dataTable = new DataTable();
dataTable.Columns.Add("EmployeeID", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Adults", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Children", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Rooms", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Spa", typeof(double)).AllowDBNull = false;
dataTable.Columns.Add("Hotpot", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Budget", typeof(double)).AllowDBNull = false;

// テストデータを生成します
var rnd = new Random(1234);
const int rowCount = 20;

for (int i = 0; i < rowCount; i++)
{
    int employeeId = rnd.Next(10000, 99999);
    int adults = rnd.Next(1, 4);
    int children = rnd.Next(0, 3);
    int rooms = (int)Math.Floor((adults + children) / 2.0);
    double spa = Math.Ceiling((adults + children) * rnd.NextDouble());
    int hotpot = adults + children;
    double budget = adults * 200 + children * 100 + rooms * 400 + spa * 188 + hotpot * 233 + 750;

    // DataTableに行を追加します
    dataTable.Rows.Add(employeeId, adults, children, rooms, spa, hotpot, budget);
}

// DataViewを生成し、DataTableのデフォルトビューとします
DataView dataView = dataTable.DefaultView;

// DataViewからデータをインポートします
var result = sheet1.Range["A2"].ImportData(dataView);

// セル範囲のスタイルを設定します
sheet1.Range[1, 0, 1, result.ColumnsImported].Style = workbook.Styles["Heading 3"];
sheet1.Range[2, 0, result.RowsImported - 1, result.ColumnsImported].Style = workbook.Styles["20% - Accent1"];
sheet1.Range[1, 0, result.RowsImported, result.ColumnsImported].EntireColumn.AutoFit();
sheet1.Range["A1"].Style = workbook.Styles["Heading 1"];
sheet1.Range["1:2"].AutoFit();
sheet1.Range[2, 6, result.RowsImported, 1].NumberFormat = "$#,##0.00";
sheet1.Range[2, 6, result.RowsImported, 1].EntireColumn.ColumnWidth = 10;

// ワークブックを保存します
workbook.Save("ImportDataView.xlsx");


DataTableの特定の行・列のみをインポートする

DataViewを使用して、DataTable内の特定の行・列のみをインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
// 新しいワークブックを生成します
var workbook = new Workbook();

// ワークブックのカルチャを日本語(JP)に設定します
workbook.Culture = CultureInfo.GetCultureInfo("ja-JP");
var sheet1 = workbook.Worksheets["Sheet1"];
sheet1.Name = "ImportDataTable";
sheet1.Range["A1"].Value = "Tour Budget Table";

// DataTableを生成し、列を定義します
var dataTable = new DataTable();
dataTable.Columns.Add("EmployeeID", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Adults", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Children", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Rooms", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Spa", typeof(double)).AllowDBNull = false;
dataTable.Columns.Add("Hotpot", typeof(int)).AllowDBNull = false;
dataTable.Columns.Add("Budget", typeof(double)).AllowDBNull = false;

// テストデータを生成します
var rnd = new Random(1234);
const int rowCount = 20;

for (int i = 0; i < rowCount; i++)
{
    int employeeId = rnd.Next(10000, 99999);
    int adults = rnd.Next(1, 4);
    int children = rnd.Next(0, 3);
    int rooms = (int)Math.Floor((adults + children) / 2.0);
    double spa = Math.Ceiling((adults + children) * rnd.NextDouble());
    int hotpot = adults + children;
    double budget = adults * 200 + children * 100 + rooms * 400 + spa * 188 + hotpot * 233 + 750;

    // DataTableに行を追加します
    dataTable.Rows.Add(employeeId, adults, children, rooms, spa, hotpot, budget);
}

// DataViewを生成し、DataTableと関連付けます
// "budget"列の降順で並び替えます。
var orderedView = new DataView(dataTable)
{
    Sort = "Budget DESC"
};

// 上位5行のみ取得します。
var first5 = orderedView.Cast<DataRowView>().Take(5);

// DataViewの特定の列からデータをインポートします。
var result = sheet1.Range["A2"].ImportData(first5,
    new DataImportOptions
    {
        ColumnsSelector = items =>
        {
            if (!(items is IEnumerable<DataRowView>)) return null;
            return new[] { "EmployeeID", "Adults", "Children", "Budget" };
        }
    });

// セル範囲のスタイルを設定します
sheet1.Range[1, 0, 1, result.ColumnsImported].Style = workbook.Styles["Heading 3"];
sheet1.Range[2, 0, result.RowsImported - 1, result.ColumnsImported].Style = workbook.Styles["20% - Accent1"];
sheet1.Range[1, 0, result.RowsImported, result.ColumnsImported].EntireColumn.AutoFit();
sheet1.Range["A1"].Style = workbook.Styles["Heading 1"];
sheet1.Range["1:2"].AutoFit();
sheet1.Range[2, 3, result.RowsImported, 1].NumberFormat = "$#,##0.00";
sheet1.Range[2, 3, result.RowsImported, 1].EntireColumn.ColumnWidth = 10;

// ワークブックを保存します
workbook.Save("ImportDataTableSelectRowsColumns.xlsx");


セルを挿入してデータをインポートする

インポートするデータに対して、インポート先の範囲が足りない場合に、セルを挿入してインポートすることが可能です。具体的な方法については、次のサンプルコードを参照してください。

C#
コードのコピー
// 新しいワークブックを生成します
var workbook = new Workbook();

// 先頭のワークシートを取得します
var worksheet = workbook.Worksheets[0];

// 数値型の一次元配列を生成します
var doubleData = new double[] { 1, 2, 3, 4, 5 };
            
// "A5"セルに固定文字列「Shift Down」を設定します
worksheet.Range["A5"].Value = "Shift Down";

// データに合わせて新しいセルを追加しながら配列をインポートします
// (このサンプルの場合、セルが挿入され、A5セルが下に移動します)
worksheet.Range["A1:A4"].ImportData(doubleData, new DataImportOptions
{
    InsufficientSpaceHandling = InsufficientSpaceHandling.InsertCells
});

// ワークブックを保存します
workbook.Save("InsertCellsIfInsufficientSpace.xlsx");


データを挿入する範囲を制限する

限定された範囲にデータをインポートする方法については、次のサンプルコードを参照してください。

C#
コードのコピー
// 新しいワークブックを生成します
var workbook = new Workbook();

// 先頭のワークシートを取得します
var worksheet = workbook.Worksheets[0];

// 数値型の一次元配列を生成します
var doubleData = new double[] { 1, 2, 3, 4, 5 };

// "A5"セルに固定文字列「Existing Data」を設定します
worksheet.Range["A5"].Value = "Existing Data";

// インポート先のセル範囲の値にあわせて、配列のデータを切り捨ててインポートします
worksheet.Range["A1:A4"].ImportData(doubleData, new DataImportOptions
{
    InsufficientSpaceHandling = InsufficientSpaceHandling.Truncate
});

// ワークブックを保存します
workbook.Save("LimitFillRangeofData.xlsx");