none
DataGridViewの全レコードをList<T>型等にしたい RRS feed

  • 質問

  • DataGridViewに表示されている全データをCSVに出力したいと思っていますが、

    DataGridViewの中身を一度List<T>に代入したいのですが、できなくて困っております。

    #CSVHelperでWriteしるためにList型等にしたいです。

    DataGridView.DataSourceはCSVからインポートしたり(CSVHelperを利用しています)、SQLサーバのテーブルから

    LINQで取得したものを表示させたりしています。

    どのように記述したらよいでしょうか?どうかご教授お願い致します。

    2013年10月17日 4:28

回答

  • どのような形でDataGridViewにバインドしているかによります。おそらく現在のバインドしているソースでは、編集は出来ても追加、削除や、並び替えはできないのではないでしょうか? いろいろな種類のものがいろいろな形でバインドするとなると、汎用的にはDataGridViewのRowsコレクションを順に読んでList<T>を作成するのがよいように思います。元々CSVなど、全てstring型でバインドしている感じですし。
    もちろん、Hongliangさんも書かれていますが、DataSourceが特定できているわけですから、そこから作成するのが本来だとは思います。こちらで汎用的にするのであれば、List<T>やBindingList<T>などバインドする型を統一して提供し、かつ、そこからList<T>を書き出すようなヘルパークラスを作成されると良いと思います。
    でも、全てstring型でDataGridViewにバインドしているのであれば、やっぱりDataGridViewのRowsコレクションを順に読んでList<T>を作成するので十分のような気がします。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答の候補に設定 星 睦美 2013年10月18日 6:50
    • 回答としてマーク 星 睦美 2013年10月22日 7:50
    2013年10月17日 5:45
    モデレータ
  • var records = csv.GetRecords<User>().ToList();

    DataGridView1.DataSource = records;

    List<User>は既にこのrecordsが持っていますよね? これをそのまま(あるいはDataGridView1.DataSourceからキャストして)渡せばいいのでは?

    このUserと言う型が、これは単なるサンプルであり実際には静的に解決できないというのならまたそれは別の話になりますが。(その場合はどちらかというとCsvHelperの使い方の話になりそう)

    • 回答の候補に設定 星 睦美 2013年10月18日 6:50
    • 回答としてマーク 星 睦美 2013年10月22日 7:50
    2013年10月18日 5:51

すべての返信

  • どう書いて、どうできなかったのでしょうか?

    DataSourceに設定しているってことは、何かするまでもなく既に必要なデータを持っているようにも読み取れますが……。

    2013年10月17日 5:02
  • どのような形でDataGridViewにバインドしているかによります。おそらく現在のバインドしているソースでは、編集は出来ても追加、削除や、並び替えはできないのではないでしょうか? いろいろな種類のものがいろいろな形でバインドするとなると、汎用的にはDataGridViewのRowsコレクションを順に読んでList<T>を作成するのがよいように思います。元々CSVなど、全てstring型でバインドしている感じですし。
    もちろん、Hongliangさんも書かれていますが、DataSourceが特定できているわけですから、そこから作成するのが本来だとは思います。こちらで汎用的にするのであれば、List<T>やBindingList<T>などバインドする型を統一して提供し、かつ、そこからList<T>を書き出すようなヘルパークラスを作成されると良いと思います。
    でも、全てstring型でDataGridViewにバインドしているのであれば、やっぱりDataGridViewのRowsコレクションを順に読んでList<T>を作成するので十分のような気がします。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    • 回答の候補に設定 星 睦美 2013年10月18日 6:50
    • 回答としてマーク 星 睦美 2013年10月22日 7:50
    2013年10月17日 5:45
    モデレータ
  • NuGetからCSVHelperを入れまして、CSVデータをインポートしDataGridViewに表示するコードを記述しました。

    var csv = new CsvReader(new StreamReader("ファイルのパス"));
    csv.Configuration.RegisterClassMap<CustomClassMap>(); 
    var records = csv.GetRecords<User>().ToList();
    
    DataGridView1.DataSource = records;
    


    CSVデータのカラムのマッピングはUserクラスを作成してマッピングしています。

    class User 
    {
        public int Id { get; set; }
        //こんな感じで型を合わせて実装
    }

    この場合はCSVデータをDataSourceに設定していますが、CSVHelperのWriteを使うには

    using (var writer = new CsvWriter(new StreamWriter("書き出しファイル名")))
    {
        writer.WriteRecords(list);
    //このlistがList型じゃないとだめっぽいです。
    }

    WriteRecordsメソッドのパラメーターがList型じゃないと吐き出せないっぽく、そこで詰まっております。

    DataGridViewの中には、CSVからインポートしたデータやSQLからLINQでもってきたデータを入れる予定でどんなデータが入るか

    わかりません。とにかく、表示してあるデータをそのままCSVに落とし込みたいと思っております。

    なので、DataGridViewの中身をすべてコレクションにいれたいのですが、ループを回す以外で何か方法がないかと思いまして。。。

    RowとColumnのカウントを取得し、Forで回すのはなんとかできている状態ですが、もっとスッキリ入れられないかと思っている次第です。

    何かアイデアあればご教示お願い致します。

    ご回答ありがとうございました。

    2013年10月18日 5:41
  • ご回答ありがとうございます。

    実際の実装はHongliangさんの回答で記載しましたが、やはりforで回すのが一番汎用的なのですね。

    今現在は、こんな形でなんとか動いている状態ですが、DataGridViewの中をいっきにToListとかできないものかと思いまして・・

                using (StreamWriter sw = new StreamWriter(fp, false, Encoding.GetEncoding("SHIFT-JIS")))
                {
                    for (int i = 0; i < DataGridView.Rows.Count; i++)
                    {
                        StringBuilder dt = new StringBuilder();
    
                        for (int j = 0; j < DataGridView.Columns.Count; j++)
                        {
                            if (j == 0 || j == 1) { }
                            
                            else
                            {
                                if (DataGridView[j, i].Value != null)
                                    dt.Append(DataGridView[j, i].Value.ToString());
    
                                if (j < DataGridView.Columns.Count - 1)
                                    dt.Append(",");
                            }
                        }
                        sw.Write(dt.ToString() + System.Environment.NewLine);
                    }
                    sw.Close();
                }

    型はCSVからインポートする場合もSQLからとってくる場合もデータベースのテーブル構造のままDataSourceに入れ込んでいます。

    やはりヘルパークラスやメソッドを書くのが一番なんですね。

    上記コードの中に改善点あれば、ご教示いただけるととても嬉しいです。

    ありがとうございました。

    2013年10月18日 5:47
  • var records = csv.GetRecords<User>().ToList();

    DataGridView1.DataSource = records;

    List<User>は既にこのrecordsが持っていますよね? これをそのまま(あるいはDataGridView1.DataSourceからキャストして)渡せばいいのでは?

    このUserと言う型が、これは単なるサンプルであり実際には静的に解決できないというのならまたそれは別の話になりますが。(その場合はどちらかというとCsvHelperの使い方の話になりそう)

    • 回答の候補に設定 星 睦美 2013年10月18日 6:50
    • 回答としてマーク 星 睦美 2013年10月22日 7:50
    2013年10月18日 5:51
  • 星 様

    回答ありがとうございます。

    とても説明足らずで本当に申し訳ないですが、

    たしかにCSVインポートしてきたデータはすべて変数recordsの中に入っているので、そのままエクスポートすれば

    吐き出せると思います。

    今回、悩んでいるのが、DataGridViewの中にSQLサーバーからのデータを入れた場合についてでございます。

    Linq to SQLのデータモデルからDataGridViewにデータを流し込むということを頻繁に行います。

    (中にはWhere句を指定してデータのフィルタリングも行います)

    using(var hogeDB = new データモデル名())
    {
          var result = hogeDB.TablePiyo.Select(x => x);
          //ここでWhere句を指定することもあります
    
          DataGridView1.DataSource = result;
    
    }

    //こんな感じのことをやってます。

    この時表示されているデータをCSVに吐き出したいのですが、いまのところDataGrieViewのRowデータをForでループさせて

    CSVに吐き出しているのですが、CSVHelperを利用して簡単に出せないかと思いまして・・・

    DataGridViewで表示されているものを、List<T>型にいれられなく、CSVHelperのWriteメソッドが使えない状況です。

    Forで回すようなヘルパークラスやヘルパーメソッドを書かないとだめなようでしたら、今のままで対応するしかないのですが、簡単に

    DataGridViewの中身をコレクション型に入れられないのかと思った次第です。



    • 編集済み naoki_ 2013年10月18日 7:20
    2013年10月18日 7:16
  • List<T>にするのはLinq to SQLの結果をToList()するだけですが。

    DataSourceを使われていないのでしょうか?

    2013年10月18日 7:23
  • おそらくご質問の意味は、将来的にどのような形でDataGridViewに表示するかわからないが、とにかく表示されているままをCSVに書き出したいということでしょうか?
    であれば、やはり私が先に書いたようにする他ないと思います。DataGridViewに表示されている値をCSVに書き出す簡単な方法はありません。DataGridViewにCSVを書き出す拡張メソッドを追加することもできます。 もちろん、内部的にはDataGridViewのRowsコレクションをループで回しながらListへ貯めて行くことになりそうですが・・・
    もしくは、CSVHelperがどのような型を求めているのかわからないのですが、例えばLINQを使って以下のようなのでもいいのでしょうか?

    var list = (from DataGridViewRow r in dataGridView1.Rows select r.Cells).ToList();


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/

    2013年10月18日 8:32
    モデレータ