我有如下所示的代码(我已经将其泛化并简化为只代表手头的问题)。该代码工作,即它接受一个DataGridView.DataSource,并最终使用EPPlus将数据输出到一个Excel文件。我想,我的问题是关于协方差以及如何使用它。
因此,您可以看到它基于在newList中找到的类型构建DataSource。然后再往下一点,它使用属性添加数据,属性是这种类型特有的someClassObject.Name, .Address and .Phone。
我的问题是,大约有75个不同的类可以通过DataGridView参数传入。尽管给定DataGridView.DataSource中的所有对象都属于同一个类,但每个类都有自己独特的属性(即名称、地址和电话)。
我可以有一个基于的巨大的开关语句,然后每个语句都有自己的for循环来将属性值分配给单元格。这是可行的,但将是难以置信的麻烦。有更好的方法吗?
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
...
}发布于 2016-06-24 21:46:02
与在此函数中创建DataRow不同,您可以使用公共接口将其移到类实现中来强制执行,例如:
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修饰符并将其添加到您的接口中,但是我更喜欢在这个实例中静态使用它,因为它不依赖于类的实例和所涉及的数据,只依赖于结构。
无论哪种方式,您都可以修改上面的代码,如下所示:
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());
}如果您需要一个递增的id列,您可以很容易地将它添加到GetDataTable/GetDataRow函数中,并像上面一样更新它们。
这只是一个快速的例子,它很可能被清理和优化一些,但它仍然传达了这个想法。希望它能帮你解决问题。
https://stackoverflow.com/questions/38022273
复制相似问题