2016-06-24 3 views
0

私は以下のようなコードを持っています。コードは、DataGridView.DataSourceに入り、EPPlusを使用してulitmatelyし、Excelファイルにデータを出力します。私の質問は、共分散とその使い方に関するものだと私は思います。共分散を持つDataGridView?

DataSourceで見つかったタイプに基づいて、newListが作成されています。次に、このタイプに固有のプロパティ、someClassObject.Name, .Address and .Phoneを使用してデータを追加します。

私の問題は、DataGridViewパラメータで渡すことができる約75種類のクラスがあることです。指定されたDataGridView.DataSourceのすべてのオブジェクトは同じクラスですが、各クラスは固有のプロパティを持ちます(つまり、名前、住所、電話である必要はありません)。

type.FullNameに基づくスイッチステートメントをとすることができ、各セルにプロパティ値を割り当てるための独自のforループがあります。それはうまくいくが、信じられないほど厄介なことになるだろう。これを行うより良い方法はありますか?代わりに、この関数内DataRow作成を行うの

public void openExcelReport(ref DataGridView dataGridView, bool bolSave = false, bool bolOpen = true, string pageTitle = "EXPORTED DATA") 
{ 
    // put dataGridView.DataSource into a List 
    object firstItem = null; 
    var myDataSource = dataGridView.DataSource; 
    var myList = ((System.Windows.Forms.BindingSource)dataGridView.DataSource).List; 
    firstItem = ((System.Collections.IList)myList)[0]; 
    var type = firstItem.GetType(); 

    Type PROJECT1_TYPE = typeof(Project1.SomeClass); 
    Type PROJECT2_TYPE = typeof(Project2.SomeOtherClass); // many more of these 

    dynamic newList = null; 

    if (type.FullName.Equals(PROJECT1_TYPE.FullName)) 
    { 
     newList = new List<Project1.SomeClass>(); 
     foreach (Project1.SomeClass someClassObject in myList) 
     { 
      newList.Add(someClassObject); 
     } 
    } 

    ExcelPackage package = new ExcelPackage(); 
    using ((package)) // use EPPlus 
    { 
     // Create the worksheet 
     ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Worksheet 1"); 

     // Load the datatable into the sheet, starting from cell A1. Print the column names on row 1 

     System.Data.DataTable dataTable = new System.Data.DataTable(); 

     dataTable.Columns.Add("Id"); 
     dataTable.Columns.Add("FirstColumn", typeof(string)); 
     dataTable.Columns.Add("SecondColumn", typeof(string)); 
     dataTable.Columns.Add("ThirdColumn", typeof(string)); 

     dataTable.Columns[0].AutoIncrement = true; 

     var column_id = 0; 
     foreach (Project1.SomeClass someClassObject in "FirstColumn") 
     { 
      DataRow dataRow = dataTable.NewRow(); 

      dataRow["FirstColumn"] = someClassObject.Name; 
      dataRow["SecondColumn"] = someClassObject.Address; 
      dataRow["ThirdColumn"] = someClassObject.Phone 

      dataTable.Rows.Add(dataRow); 

      column_id += 1; 

     } 

     // worksheet is now populated, so save Excel File  
     ... 

} 
+1

あなたが渡しているクラスでは、 'GetDataRow()'(またはそれに類似した)関数を持つインターフェースを実装して、クラス実装自体にそのコードを持つことができるようにすることができますか?ここでは単に 'dataTable.Rows.Add(someClassObject.GetDataRow())'を実行します。そしてそれでやります。これは 'switch'または' if/else'ブロックを必要としないようにします。なぜなら、 'DataRow'を生成するための詳細は、対象となる列を含むクラスにプロパティとして直接関連付けられているからです。 – gmiley

答えて

2

、あなたは、例えば、それを強制するために、共通のインタフェースを使用して、クラスの実装にそれを移動することができ:

public interface DataRowConvertable 
{ 
    DataRow GetDataRow(); 
} 

public class SomeClass : DataRowConvertable 
{ 
    public SomeClass() { } 
    public SomeClass(string name, string address, string phone) 
    { 
     Name = name; 
     Address = address; 
     Phone = phone; 
    } 

    public string Name { get; set; } 
    public string Address { get; set; } 
    public string Phone { get; set; } 

    public DataRow GetDataRow() 
    { 
     DataRow row = GetDataTable().NewRow(); 
     row["Name"] = this.Name; 
     row["Address"] = this.Address; 
     row["Phone"] = this.Phone; 
     return row; 
    } 

    public static DataTable GetDataTable() 
    { 
     DataTable table = new DataTable("SomeClassTable"); 
     table.Columns.Add("Name", typeof(string)); 
     table.Columns.Add("Address", typeof(string)); 
     table.Columns.Add("Phone", typeof(string)); 
     return table; 
    } 
} 

あなたはさらにそれを取ることができ、しかし、これはあなたに良い選択肢とスタート地点を与えるはずです。 GetDataTable関数を公開したままにしておき、それを使ってテーブルインスタンスを作成するか、それを非公開にして内部でのみ使用することもできます。私は前者を選択し、それを使用する前にテーブルを初期化するために関数内で使用します。 staticモディファイアを取り除いてインターフェイスに追加することもできますが、構造体だけに関連するクラスやデータのインスタンスに依存しないため、このインスタンスの静的な使用が好まれます。あなたはインクリメントid列が必要な場合は、あなたが簡単にGetDataTable/GetDataRow機能でそれを追加し、それらを更新することができ

ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Worksheet 1"); 
System.Data.DataTable dataTable = Project1.SomeClass.GetDataTable(); 

foreach (Project1.SomeClass someClassObject in myList) 
{ 
    dataTable.Rows.Add(someClassObject.GetDataRow()); 
} 

いずれかの方法で、あなたは、あなたがこのように見えるように上記の必要があり、コードを変更することができますあなたと同じように

これは単なるクイックな例であり、クリーンアップされ、最適化されている可能性がありますが、それでもやはりその考え方を伝えます。それがあなたを助けてくれることを願っています。

+0

ありがとうございます。私は他の何も考慮しなかった "共分散"にとても集中していました。私はこれを実装しようとし、あなたに戻ってきます。 –