Ich habe Code wie unten (ich habe es generifiziert und reduziert, um nur das Problem zur Verfügung zu stellen). Der Code funktioniert, das heißt, er nimmt eine DataGridView.DataSource
und ulitmatly, EPPlus
, die Daten in eine Excel-Datei ausgibt. Meine Frage bezieht sich auf Kovarianz und wie man sie benutzt, denke ich.DataGridView mit Kovarianz?
Sie sehen also, es baut newList
basierend auf dem Typ, den es in der DataSource
gefunden hat. Dann fügen Sie die Daten mit den Eigenschaften someClassObject.Name, .Address and .Phone
, die für diesen Typ eindeutig sind, etwas weiter unten hinzu.
Mein Problem ist, dass es etwa 75 verschiedene Klassen gibt, die über den Parameter DataGridView
übergeben werden könnten. Jede Klasse hat ihre eigenen einzigartigen Eigenschaften (d. H. Nicht notwendigerweise Name, Adresse, Telefon), obwohl alle Objekte in gegebenen DataGridView.DataSource
derselben Klasse angehören.
Ich könnte eine Riese Switch-Anweisung basierend auf type.FullName
haben und dann jeder würde seine eigene for-Schleife haben, um die Eigenschaft Werte der Zelle zuzuweisen. Das würde funktionieren, wäre aber unglaublich umständlich. Gibt es einen besseren Weg, dies zu tun?
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
...
}
Für die Klassen, die Sie übergeben, könnten Sie diese ändern, um eine Schnittstelle zu implementieren, die eine 'GetDataRow()' (oder etwas ähnliches) Funktion hat, so dass Sie diesen Code dann in der Klassenimplementierung selbst haben können Hier tun Sie einfach 'dataTable.Rows.Add (someClassObject.GetDataRow())'. Und sei damit fertig. Dies würde Sie davon abhalten, einen "switch" - oder "if/else" -Block zu benötigen, da die Einzelheiten zum Erzeugen des 'DataRow' direkt mit der Klasse verbunden sind, die die gewünschten Spalten als Eigenschaften enthält. – gmiley