原來的導出方式比較適用於比較簡單的導出,每一條數據在一行,數據列雖然自定義程度比較高,如果要一條數據對應多行就做不到了,於是就想支持根據模板導出,在 1.8.0 版本中引入了根據模板導出的功能 ...
WeihanLi.Npoi 根據模板導出Excel
Intro
原來的導出方式比較適用於比較簡單的導出,每一條數據在一行,數據列雖然自定義程度比較高,如果要一條數據對應多行就做不到了,於是就想支持根據模板導出,在 1.8.0 版本中引入了根據模板導出的功能
使用示例
示例模板
模板規劃的可以有三種數據:
- Global:一個是導出的時候可以指定一些參數,作為 Global 參數,預設參數格式使用:
$(Global:PropName)
的格式 - Header:配置的對應屬性的顯示名稱,預設是屬性名稱,預設參數格式:
$(Header:PropName)
- Data:對應數據的屬性值,預設參數格式:
$(Data:PropName)
預設模板參數格式(從 1.8.2 版本開始支持通過 TemplateHelper.ConfigureTemplateOptions
方法來自定義):
- Global 參數:
$(Global:{0})
- Header 參數:
$(Header:{0})
- Data 參數:
$(Data:{0})
- Data Begin:
<Data>
- Data End:
</Data>
模板規範:
模板需要通過 Data Begin 和 Data End 來配置數據模板的開始和結束以識別每一個數據對應的開始行和結束行
示例代碼
示例配置
var setting = ExcelHelper.SettingFor<TestEntity>();
// ExcelSetting
setting.HasAuthor("WeihanLi")
.HasTitle("WeihanLi.Npoi test")
.HasDescription("WeihanLi.Npoi test")
.HasSubject("WeihanLi.Npoi test");
setting.HasSheetConfiguration(0, "SystemSettingsList", 1, true);
setting.Property(_ => _.SettingId)
.HasColumnIndex(0);
setting.Property(_ => _.SettingName)
.HasColumnTitle("SettingName")
.HasColumnIndex(1);
setting.Property(_ => _.DisplayName)
.HasOutputFormatter((entity, displayName) => $"AAA_{entity.SettingName}_{displayName}")
.HasInputFormatter((entity, originVal) => originVal.Split(new[] { '_' })[2])
.HasColumnTitle("DisplayName")
.HasColumnIndex(2);
setting.Property(_ => _.SettingValue)
.HasColumnTitle("SettingValue")
.HasColumnIndex(3);
setting.Property(x => x.Enabled)
.HasColumnInputFormatter(val => "啟用".Equals(val))
.HasColumnOutputFormatter(v => v ? "啟用" : "禁用");
setting.Property("HiddenProp")
.HasOutputFormatter((entity, val) => $"HiddenProp_{entity.PKID}");
setting.Property(_ => _.PKID).Ignored();
setting.Property(_ => _.UpdatedBy).Ignored();
setting.Property(_ => _.UpdatedTime).Ignored();
根據模板導出示例代碼:
var entities = new List<TestEntity>()
{
new TestEntity()
{
PKID = 1,
SettingId = Guid.NewGuid(),
SettingName = "Setting1",
SettingValue = "Value1",
DisplayName = "ddd1"
},
new TestEntity()
{
PKID=2,
SettingId = Guid.NewGuid(),
SettingName = "Setting2",
SettingValue = "Value2",
Enabled = true
},
};
var csvFilePath = $@"{tempDirPath}\test.csv";
entities.ToExcelFileByTemplate(
Path.Combine(ApplicationHelper.AppRoot, "Templates", "testTemplate.xlsx"),
ApplicationHelper.MapPath("templateTestEntities.xlsx"),
extraData: new
{
Author = "WeihanLi",
Title = "導出結果"
}
);
導出結果
More
為了方便使用,增加了一些方便的擴展方法:
public static int ToExcelFileByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, string templatePath, string excelPath, int sheetIndex = 0, object extraData = null);
public static int ToExcelFileByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, byte[] templateBytes, string excelPath, ExcelFormat excelFormat = ExcelFormat.Xls, int sheetIndex = 0, object extraData = null);
public static int ToExcelFileByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, IWorkbook templateWorkbook, string excelPath, int sheetIndex = 0, object extraData = null);
public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, string templatePath, int sheetIndex = 0, object extraData = null);
public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, byte[] templateBytes, ExcelFormat excelFormat = ExcelFormat.Xls, int sheetIndex = 0, object extraData = null);
public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, Stream templateStream, ExcelFormat excelFormat = ExcelFormat.Xls, int sheetIndex = 0, object extraData = null);
public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, IWorkbook templateWorkbook, int sheetIndex = 0, object extraData = null);
public static byte[] ToExcelBytesByTemplate<TEntity>([NotNull]this IEnumerable<TEntity> entities, ISheet templateSheet, object extraData = null);
Reference
- https://github.com/WeihanLi/WeihanLi.Npoi
- https://github.com/WeihanLi/WeihanLi.Npoi/blob/917e8fb798e9cbae52d121a7d593e37639870911/samples/DotNetCoreSample/Program.cs#L94