Yes, there is. I assembled the Helper below that does it. It is based on the package Epplus. Possibly you will have to change this Helper a little to work properly for your case.
Note that he uses a lot Reflection:
public static class ExcelHelper
{
public static byte[] ExportarListaParaExcel<T>(IEnumerable<T> lista, String tituloPlanilha = "Exportação para Excel")
where T: class, new()
{
using (var excelPackage = new ExcelPackage())
{
excelPackage.Workbook.Properties.Author = "Eu mesmo";
excelPackage.Workbook.Properties.Title = tituloPlanilha;
var sheet = excelPackage.Workbook.Worksheets.Add(tituloPlanilha);
sheet.Name = tituloPlanilha;
var properties = ReflectionUtils.ExtrairPropertiesDeObjeto(new T()).Where(p => !p.Name.EndsWith("Id") && !p.PropertyType.IsGenericType).ToList();
var titulos = properties.Select(p => p.AtributoDisplayName() != null ? p.AtributoDisplayName().DisplayName : p.Name).ToArray();
var i = 1;
foreach (var titulo in titulos)
{
sheet.Cells[1, i++].Value = titulo;
}
var rowIndex = 2;
foreach (var item in lista)
{
var col = 1;
foreach (var prop in properties.Where(p => !p.Name.EndsWith("Id") && !p.PropertyType.IsGenericType))
{
var val = item.GetType().GetProperty(prop.Name).GetValue(item, null);
String str;
if (val == null)
{
str = "";
}
else if (val.GetType().IsPrimitive || val.GetType() == typeof(Decimal) || val.GetType() == typeof(String) || val.GetType() == typeof(DateTime))
{
str = val.ToString();
}
else
{
str = val.GetType().GetProperty("Nome").GetValue(val, null).ToString();
}
sheet.Cells[rowIndex, col++].Value = str ?? "";
}
rowIndex++;
}
return excelPackage.GetAsByteArray();
}
}
public static byte[] ExportarViewModelParaExcel(object viewModel, String tituloPlanilha = "Exportação para Excel")
{
using (var excelPackage = new ExcelPackage())
{
excelPackage.Workbook.Properties.Author = "Eu mesmo";
excelPackage.Workbook.Properties.Title = tituloPlanilha;
foreach (var objeto in ReflectionUtils.ExtrairPropertiesDeObjeto(viewModel).ToList())
{
var sheet = excelPackage.Workbook.Worksheets.Add(objeto.Name);
sheet.Name = objeto.Name;
if (objeto.PropertyType.GetInterfaces().Any(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>)))
{
// É uma lista
var lista = (IEnumerable)objeto.GetValue(viewModel, null);
if (lista == null) continue;
var fields = lista.GetType().GetGenericArguments()[0].GetFields(BindingFlags.Public | BindingFlags.Instance);
var titulos = fields.Select(p => p.AtributoDisplayName() != null ? p.AtributoDisplayName().DisplayName : p.Name).ToArray();
var i = 1;
foreach (var titulo in titulos)
{
sheet.Cells[1, i++].Value = titulo;
}
var rowIndex = 2;
foreach (var item in lista)
{
var col = 1;
foreach (var field in fields)
{
var val = item.GetType().GetField(field.Name).GetValue(item);
String str;
if (val == null)
{
str = "";
}
else if (val.GetType().IsPrimitive || val.GetType() == typeof(Decimal) || val.GetType() == typeof(String) || val.GetType() == typeof(DateTime))
{
str = val.ToString();
}
else
{
str = val.GetType().GetField("Nome").GetValue(val).ToString();
}
sheet.Cells[rowIndex, col++].Value = str ?? "";
}
rowIndex++;
}
}
else
{
// É um objeto
var obj = objeto.GetValue(viewModel, null);
var fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
var titulos = fields.Select(p => new {
Titulo = p.AtributoDisplayName() != null ? p.AtributoDisplayName().DisplayName : p.Name,
Valor = p.GetValue(obj)
}).ToList();
var i = 1;
foreach (var titulo in titulos)
{
sheet.Cells[i, 1].Value = titulo.Titulo;
sheet.Cells[i++, 2].Value = titulo.Valor;
}
}
}
return excelPackage.GetAsByteArray();
}
}
}
The code that adds a new tab is this:
var sheet = excelPackage.Workbook.Worksheets.Add(objeto.Name);
To send to View:
return File(excelPackage.GetAsByteArray(), System.Net.Mime.MediaTypeNames.Application.Octet, "Exemplo-" + DateTime.Now.ToString() + ".xlsx");
To Action can return ActionResult
or FileResult
.
I can apply this concept using Datatable to fill every tab of my report?
– Igor Macedo
Can. Just make a list of
DataTable
s and adapt the code.– Leonel Sanches da Silva
I managed to assemble it well. I’m just having a hard time making the file donwload. I can only use
wb.SaveAs(@"C:\Teste\Export.xlsx");
to download? Or have other ways? @Gypsy– Igor Macedo
@Igormacedo I updated the answer.
– Leonel Sanches da Silva