.Net Core OfficeOpenXml создание excel файла из коллекции типизированной базовым классом
class Product
{
public int Id {get:set;}
}
class Car : Product
{
public string Name {get;set;}
}
var products = new List<Product>();
var car = new Car();
products.Add(car);
Потом из products создаю excel файл, но в нем нет поля Name. Избавится от восходящего преобразования проблематично. Можно ли с помощью OfficeOpenXml получить адекватный результат?
Такая же проблема с либой LinqToCsv . System.Xml.Serialization работает адекватно.
Пример кода для воспроизведения:
using OfficeOpenXml;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var products = new List<Product>();
var car = new Car
{
Id = 1,
Name = "лада"
};
products.Add(car);
var plane = new Airplane
{
Id = 2,
Speed = 500
};
products.Add(plane);
var stream = Convert(products);
var fstream = new FileStream("products.xlsx", FileMode.OpenOrCreate);
stream.WriteTo(fstream);
stream.Close();
fstream.Close();
}
public static MemoryStream Convert(IEnumerable<Product> collection)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
var result = new MemoryStream();
using (var pck = new ExcelPackage())
{
AddSheet(pck, collection, "машины", typeof(Car));
AddSheet(pck, collection, "самолеты", typeof(Airplane));
pck.SaveAs(result);
}
return result;
}
private static void AddSheet(in ExcelPackage pck, IEnumerable<Product> collection, string sheetName, Type productType)
{
var products = collection.Where(p => p.GetType() == productType);
if (products.FirstOrDefault() != null)
{
ExcelWorksheet tyreSheet = pck.Workbook.Worksheets.Add(sheetName);
var tableRange = tyreSheet.Cells["A1"].LoadFromCollection(products, true);
tableRange.AutoFilter = true;
tableRange.AutoFitColumns();
}
}
}
class Product
{
public int Id { get; set; }
}
class Car : Product
{
public string Name { get; set; }
}
class Airplane : Product
{
public int Speed { get; set; }
}
}
Ответы (1 шт):
Автор решения: aepot
→ Ссылка
Данный конкретный случай можно решить вот так:
static void Main(string[] args)
{
var products = new List<Product>();
var car = new Car
{
Id = 1,
Name = "лада"
};
products.Add(car);
var plane = new Airplane
{
Id = 2,
Speed = 500
};
products.Add(plane);
using (var ms = Convert(products))
using (var fs = File.Create("products.xlsx"))
{
ms.WriteTo(fs);
}
Process.Start(new ProcessStartInfo { FileName = "products.xlsx", UseShellExecute = true });
}
public static MemoryStream Convert(IEnumerable<Product> collection)
{
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
var result = new MemoryStream();
using (var pck = new ExcelPackage())
{
AddSheet(pck, collection.OfType<Car>(), "машины");
AddSheet(pck, collection.OfType<Airplane>(), "самолеты");
pck.SaveAs(result);
}
return result;
}
private static void AddSheet<T>(in ExcelPackage pck, IEnumerable<T> collection, string sheetName)
{
if (collection.Any())
{
ExcelWorksheet tyreSheet = pck.Workbook.Worksheets.Add(sheetName);
var tableRange = tyreSheet.Cells["A1"].LoadFromCollection(collection, true);
tableRange.AutoFilter = true;
tableRange.AutoFitColumns();
}
}
То есть использовать непосредственно то обобщение, которое нужно.