I'm building a tool to simply the exporting to excel for later re-use. One of the issues I'm running into is an easy, and reliable way of passing around an object that contains my cell data.
The class that contains my cell data looks like:
public interface IExcelCell {
}
public class ExcelCell<T> : IExcelCell
{
public T Value { get; set; }
}
And I'm using it like so:
private void GenerateCell(IExcelCell cell, int currentColumn)
{
// check type of Value, apply optional formatting
}
Essentially what I need to do is check if the incoming data is of a certain data-type, e.g. string, double, DateTime. Is there a convenient way of doing this?
Edit
This is the relevant exportation code to illustrate somewhat of what I'm trying to do:
public class ExcelExporter
{
private ExcelPackage excelPackage;
private OfficeOpenXml.ExcelWorksheet currentWorksheet;
private int currentRow;
public ExcelPackage ExportExcelWorkbook(ExcelWorkbook workbook)
{
excelPackage = new ExcelPackage();
GenerateWorkbook(workbook);
return excelPackage;
}
private void GenerateWorkbook(ExcelWorkbook workbook)
{
foreach (var worksheet in workbook.Worksheets)
{
GenerateWorksheet(worksheet);
}
}
private void GenerateWorksheet(ExcelWorksheet worksheet)
{
currentWorksheet = excelPackage.Workbook.Worksheets.Add(worksheet.Name);
currentRow = 1;
foreach (var section in worksheet.Sections)
{
GenerateSection(section);
}
}
private void GenerateSection(ExcelSection section)
{
if (!section.Name.IsNullOrEmpty())
{
currentWorksheet.Cells[currentRow, 1].Value = section.Name;
currentRow++;
}
if (section.Headers != null && section.Headers.Any())
{
GenerateHeaders(section.Headers);
currentRow++;
}
foreach (var row in section.Rows)
{
GenerateRow(row);
currentRow++;
}
}
private void GenerateHeaders(IEnumerable<string> headers)
{
var enumerable = headers as IList<string> ?? headers.ToList();
for (var i = 0; i < enumerable.Count(); i++)
{
currentWorksheet.Cells[currentRow, i + 1].Value = enumerable[i];
}
}
private void GenerateRow(ExcelRow row)
{
var currentColumn = 0;
foreach (var cell in row.RowData)
{
GenerateCell(cell, currentColumn);
currentColumn++;
}
}
private void GenerateCell(IExcelCell cell, int currentColumn)
{
var excelCell = (ExcelCell<object>) cell;
if (excelCell.Value is DateTime)
{
currentWorksheet.Cells[currentRow, currentColumn].Style.Numberformat.Format = "mm/dd/yyyy";
}
currentWorksheet.Cells[currentRow, currentColumn].Value = excelCell.Value;
}
}
Edit 2
Taking Gilad's advice from his answer, I came up with a slightly different solution:
// interface
public interface IExcelCell {
object Value { get; set; }
string NumberFormat { get; }
}
// implementation
public class ExcelCell : IExcelCell
{
public object Value { get; set; }
public string NumberFormat => null;
}
public class DateTimeExcelCell : IExcelCell
{
public object Value { get; set; }
public string NumberFormat => "mm/dd/yyyy";
}
// Cell generation
private void GenerateCell(IExcelCell cell, int currentColumn)
{
if (cell.NumberFormat != null)
{
currentWorksheet.Cells[currentRow, currentColumn].Style.Numberformat.Format = cell.NumberFormat;
}
currentWorksheet.Cells[currentRow, currentColumn].Value = cell.Value;
}
if (call is DateTime)?if (((ExcelCell<object>) cell).Value is DateTime). This just seems to be a bit convoluted, and I'm sure there's a better way.IExcelCell<T>.