概述
支持多sheet導入導出。導出字段過濾,合並行。特性配置導入驗證,非空驗證,唯一驗證,錯誤標注等
用於基礎配置和普通報表的導入導出,對於復雜需求,比如公式,導出圖片等暫不支持
GitHub地址:
https://github.com/Mike-Zrw/ExcelHelper/tree/master
導出配置支持
- HeaderStyleAttribute :列名樣式,(顏色,字體,大小,加粗,對齊)
- StringFormatterAttribute :格式化時間
- ColumnWidthAttribute: 列寬,默認自適應,可通過這個特性配置最小列寬和最大列寬
- RowMergedAttribute: 合並行,需要配合ExportPrimaryKey使用
- ExportTitle:導出標題,標題可選,可設置居中,顏色字體等。
- SheetName sheetName不設置默認為sheet1,sheet2等
- FilterColumn :導出指定列。可根據選中的列名或者屬性名導出指定的列
導入配置支持
- ColumnRegexAttribute:正則判斷,正則表達式判斷單元格內容
- ColumnRequiredAttribute:非空判斷,對於不可為空的類型即使沒有設置該特性,仍會進行非空判斷,所以如果一個可以為空的int類型,請設置字段類型為int?
- ColumnUniqueAttribute:唯一判斷,若不加此特性,默認對所有列進行重復驗證,可選擇性的加在某幾列上組合驗證。通過ImportSheet
的NeedUniqueValidation可配置是否開啟重復驗證,UniqueValidationPrompt設置重復時的提示 - ImportSheet.ValidateHandler : 業務邏輯判斷,業務邏輯判斷在所有判斷之后執行,可以通過IsValidated屬性判斷該行是否通過了其他驗證,SetError()用來追加單元格的錯誤提示
- HeaderRowIndex:列名所在行
- ImportBook.DataErrorForegroundColor: 錯誤前景色(紅)
- ImportBook.RepeatedErrorForegroundColor: 重復前景色(黃)
- ImportBook.DefaultForegroundColor: 默認前景色(白),在驗證未通過時,顏色處於錯誤或重復但驗證通過的單元格顏色將重置為默認前景色。(即第一次導入錯誤,修改之后第二次部分導入正確,則正確的顏色會便會默認前景色)
導入結果說明
- ImportSuccess :是否導入成功
- GetSummaryErrorMessage() : excel中的所有錯誤文字展示
- GetNotDisplayErrorMessage(): 無法在excel中標注的錯誤信息,比如sheet格式不正確,excel格式不正確等
- outPutStream: 錯誤的單元格添加樣式及標注輸出到文件流中。如果不需要輸出excel流,該參數可不傳。
導出示例
var students = new List<ExportStudent>();
var grades = new List<ExportGrade>();
var schools = new List<ExportSchool>();
for (int i = 0; i < 100; i++)
{
students.Add(new ExportStudent
{
Name = i % 6 == 1 ? null : ($"name{i}"),
Age = i,
Phone = i % 8 == 1 ? "adsf123" : $"{1}{new Random().Next(100, 999)}{1}{new Random().Next(100, 999)}{2}{new Random().Next(0, 9)}{3}",
Birthday = i % 13 == 1 ? default(DateTime?) : DateTime.Now.AddDays(i),
Money = Math.Round(new Random(i).NextDouble(), 2),
SchoolDate = DateTime.Now.AddDays(i + 1),
});
grades.Add(new ExportGrade { Code = $"編碼{i}", GradeName = $"{i}年級" });
schools.Add(new ExportSchool { Name = $"{i}號學校", Address = $"學校地址{i}", Price = Math.Round(new Random().NextDouble(), 2) });
}
var exporter = new DefaultExcelExporter();
var stream = new FileStream("D://export.xlsx", FileMode.Create, FileAccess.Write);
//var stream = new MemoryStream();
exporter.Export(new ExportBook()
{
Ext =ExtEnum.XLSX,
Sheets = new List<ExportSheet> {
new ExportSheet(){ SheetName="測試", Data=students},
new ExportSheet(){ Data=grades},
new ExportSheet(){ Data=schools,Title=new ExportTitle("學校列表",true,18,default,Excel.Enums.HorizontalAlignEnum.Center), FilterColumn=new List<string>(){ "學校名稱","price" } },
}
}, stream);
stream.Dispose();
public class ExportStudent : ExportModel
{
[ColumnNameAttribute("名字")]
public string Name { get; set; }
[ColumnNameAttribute("年齡")]
public int Age { get; set; }
[ColumnNameAttribute("生日")]
[StringFormatter("yyyy-MM-dd HH:mm:ss")]
public DateTime? Birthday { get; set; }
[ColumnStyle(FontName = "華文彩雲")]
[ColumnNameAttribute("入學時間")]
[StringFormatter("yyyy-MM-dd")]
public DateTime SchoolDate { get; set; }
[ColumnStyle(FontColor = 211, IsBold = true)]
[ColumnNameAttribute("零花錢")]
public double Money { get; set; }
[ColumnNameAttribute("電話")]
public string Phone { get; set; }
}
合並行導出示例
public void ExportMergeRow()
{
var orders = new List<Order>();
for (int i = 0; i < 100; i++)
{
var index = new Random(i).Next(i + 10, i + 13);
var orderNumber = $"訂單{index}";
orders.Add(new Order()
{
Buyer = $"下單人{index}",
Price = Math.Round(new Random(i).NextDouble(), 2),
BuyQty = new Random(i).Next(1, 10),
ProductName = $"商品{i}",
OrderNumber = orderNumber,
OrderNum2 = orderNumber,
ExportPrimaryKey = orderNumber
});
}
var exporter = new DefaultExcelExporter();
var stream = new FileStream("D://exportorder.xlsx", FileMode.Create, FileAccess.Write);
exporter.Export(new ExportBook()
{
Ext = ExtEnum.XLSX,
Sheets = new List<ExportSheet> { new ExportSheet() { SheetName = "訂單列表", Data = orders } }
}, stream);
stream.Dispose();
}
導入示例
var sheet1 = new ImportSheet<ImportStudent>
{
UniqueValidationPrompt = "零花錢不可重復",
HeaderRowIndex = 0,
SheetIndex = 0,
ValidateHandler = (list) =>
{
foreach (ImportStudent model in list)
{
if (model.IsValidated && model.Name == "name0")
model.SetError(nameof(model.Name), "名字不可為0");
if (model.IsValidated && model.Money < 0.5)
model.SetError(nameof(model.Money), "零花錢不可小於0.5");
}
}
};
var sheet2 = new ImportSheet<ImportGrade>
{
HeaderRowIndex = 0,
SheetIndex = 1
};
var sheet3 = new ImportSheet<ImportSchool>
{
HeaderRowIndex = 1,
SheetIndex = 2,
ValidateHandler = (list) =>
{
foreach (var model in list)
{
if (model.Price > 0.5)
model.SetError(nameof(model.Price), "學費不可大於0.5");
}
}
};
var import = new DefaultExcelImporter();
using var inputStrem = new FileStream("D://export.xlsx", FileMode.OpenOrCreate, FileAccess.Read);
using var outStrem = new FileStream("D://error.xlsx", FileMode.Create, FileAccess.Write);
var bookmodel = new ImportBook();
bookmodel.SetSheetModels(sheet1, sheet2, sheet3);
var ret = import.ImportExcel(inputStrem, ExtEnum.XLSX, bookmodel, outStrem);
var success = ret.ImportSuccess;
var summaryErrorMsg = ret.GetSummaryErrorMessage();
var notDisplayMsg = ret.GetNotDisplayErrorMessage();
Output.WriteLine($"success:{success}");
Output.WriteLine("summaryErrorMsg------------");
Output.WriteLine(summaryErrorMsg);
Output.WriteLine("notDisplayMsg------------");
Output.WriteLine(notDisplayMsg);
public class ImportStudent : ImportModel
{
[ColumnRequired("名字必填")]
[ColumnNameAttribute("名字")]
public string Name { get; set; }
[ColumnNameAttribute("年齡")]
public int Age { get; set; }
[ColumnRequired]
[ColumnNameAttribute("生日")]
public DateTime Birthday { get; set; }
[ColumnNameAttribute("入學時間")]
public DateTime SchoolDate { get; set; }
[ColumnUnique]
[ColumnNameAttribute("零花錢")]
public double Money { get; set; }
[ColumnNameAttribute("電話")]
[ColumnRegex(@"^[1]+[1-9]+\d{9}$", "電話格式不對")]
public string Phone { get; set; }
}
導出結果展示:
導入結果展示: