對於EXCEL的導入、導出,我以前已分享過屢次,好比:html
第一種方案:《我寫的一個ExcelHelper通用類,可用於讀取或生成數據》這個主要是利用把EXCEL當成一個DB來進行獲取數據,導出則是採用拼接成HTML TABLE的方式,這種在ASP.NET,ASP.NET CORE 中也是能夠的,簡單方便,依賴Office Excel組件,僅適用於網站服務端。 推薦指數:♥♥♥
git
第二種方案:《MVC導出數據到EXCEL新方法:將視圖或分部視圖轉換爲HTML後再直接返回FileResult》這個主要是實現導出EXCEL的方法,依賴MVC框架,利用視圖引擎解析渲染View(view也主要是HTML表格模板)得到HTML TABLE,本質與第一種的導出相同,只是這裏不用代碼去拼接HTML TABLE而是寫View HTML模板便可,簡單方便,適用於ASP.NET MVC、ASP.NET MVC CORE; 推薦指數:♥♥♥♥github
第三種方案:《NPOI導入導出EXCEL通用類,供參考,可直接使用在WinForm項目中》這個實現了EXCEL的導入、導出方法,依賴NPOI,優勢是:無需安裝EXCEL也能操做EXCEL,文中的實現方案及示例主要是用在C/S中,對B/S 支持不夠友好,固然能夠進行適當修改就能兼容WEB版。推薦指數:♥♥♥♥
服務器
第四種方案:《分享我基於NPOI+ExcelReport實現的導入與導出EXCEL類庫》這個完美的靈活實現了EXCEL的各類導入、導出方法,支持基於模板導出,格式自定義等 特色,依賴:ExcelReport、NPOI、NPOI.Extend,支持C/S、B/S(C/S特有的方法除外),適用於企業級EXCEL操做比較複雜的場景:ExcelUtility,推薦指數:♥♥♥♥♥,git地址:https://gitee.com/zuowj/ExcelUtilityapp
第五種方案:就是本文即將介紹的,依賴NPOI,實現EXCEL的導入、導出、上傳等常見方法,充分借鑑第三種、第四種方案,抽出核心的實現方法,並進行適當改造,以知足絕大部份的EXCEL場景,輕量、簡單、易用,支持鏈式操做,類庫名:ExcelEasyUtil,故名思義:EXCEL簡單實用工具類庫。框架
該類庫主要是基於NPOI的IWorkbook進行擴展,擴展方法實現了常見的幾種導出EXCEL、導入EXCEL數據的方法:基於類型集合,基於DataTable,NPOIExtensions完整實現代碼以下:工具
using Newtonsoft.Json.Linq; using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq.Expressions; using System.Net.Http; using System.Net.Http.Headers; using System.Reflection; using System.Text; namespace ExcelEasyUtil { /// <summary> /// NPOI擴展類 /// author:zuowenjun /// 2019-5-21 /// </summary> public static class NPOIExtensions { /// <summary> /// 將一個實體數據對象填充到一個EXCEL工做表中(可連續填充多個sheet,如:FillSheet(...).FillSheet(..) ) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="book"></param> /// <param name="sheetName"></param> /// <param name="headerColNames"></param> /// <param name="excelData"></param> /// <param name="getCellValueFunc"></param> /// <returns></returns> public static IWorkbook FillSheet<T>(this IWorkbook book, string sheetName, IList<T> excelData, IList<string> headerColNames, Func<T, List<object>> getCellValuesFunc, IDictionary<string, string> colDataFormats = null) where T : class { var sheet = book.CreateSheet(sheetName); IRow rowHeader = sheet.CreateRow(0); var headerCellStyle = GetCellStyle(book, true); Dictionary<int, ICellStyle> colStyles = new Dictionary<int, ICellStyle>(); List<Type> colTypes = new List<Type>(); Type strType = typeof(string); for (int i = 0; i < headerColNames.Count; i++) { ICell headerCell = rowHeader.CreateCell(i); headerCell.CellStyle = headerCellStyle; string colName = headerColNames[i]; if (colName.Contains(":")) { var colInfos = colName.Split(':'); colName = colInfos[0]; colTypes.Add(GetColType(colInfos[1])); } else { colTypes.Add(strType); } headerCell.SetCellValue(colName); if (colDataFormats != null && colDataFormats.ContainsKey(colName)) { colStyles[i] = GetCellStyleWithDataFormat(book, colDataFormats[colName]); } else { colStyles[i] = GetCellStyle(book); } } //生成excel內容 for (int i = 0; i < excelData.Count; i++) { IRow irow = sheet.CreateRow(i + 1); var row = excelData[i]; var cellValues = getCellValuesFunc(row); for (int j = 0; j < headerColNames.Count; j++) { ICell cell = irow.CreateCell(j); string cellValue = string.Empty; if (cellValues.Count - 1 >= j && cellValues[j] != null) { cellValue = cellValues[j].ToString(); } SetCellValue(cell, cellValue, colTypes[j], colStyles); } } return book; } /// <summary> /// 將一個實體數據對象填充到一個EXCEL工做表中(可連續填充多個sheet,如:FillSheet(...).FillSheet(..) ) /// </summary> /// <typeparam name="T"></typeparam> /// <param name="book"></param> /// <param name="sheetName"></param> /// <param name="colMaps"></param> /// <param name="excelData"></param> /// <returns></returns> public static IWorkbook FillSheet<T>(this IWorkbook book, string sheetName, IList<T> excelData, IDictionary<string, Expression<Func<T, dynamic>>> colMaps, IDictionary<string, string> colDataFormats = null ) where T : class { var sheet = book.CreateSheet(sheetName); var headerColNames = new List<string>(); var propInfos = new List<PropertyInfo>(); foreach (var item in colMaps) { headerColNames.Add(item.Key); var propInfo = GetPropertyInfo(item.Value); propInfos.Add(propInfo); } var headerCellStyle = GetCellStyle(book, true); Dictionary<int, ICellStyle> colStyles = new Dictionary<int, ICellStyle>(); IRow rowHeader = sheet.CreateRow(0); for (int i = 0; i < headerColNames.Count; i++) { ICell headerCell = rowHeader.CreateCell(i); headerCell.CellStyle = headerCellStyle; headerCell.SetCellValue(headerColNames[i]); if (colDataFormats != null && colDataFormats.ContainsKey(headerColNames[i])) { colStyles[i] = GetCellStyleWithDataFormat(book, colDataFormats[headerColNames[i]]); } else { colStyles[i] = GetCellStyle(book); } } //生成excel內容 for (int i = 0; i < excelData.Count; i++) { IRow irow = sheet.CreateRow(i + 1); var row = excelData[i]; for (int j = 0; j < headerColNames.Count; j++) { var prop = propInfos[j]; ICell cell = irow.CreateCell(j); string cellValue = Convert.ToString(propInfos[j].GetValue(row, null)); SetCellValue(cell, cellValue, prop.PropertyType, colStyles); } } return book; } /// <summary> /// 將一個數據表(DataTable)對象填充到一個EXCEL工做表中(可連續填充多個sheet,如:FillSheet(...).FillSheet(..) ) /// </summary> /// <param name="book"></param> /// <param name="sheetName"></param> /// <param name="excelData"></param> /// <param name="colMaps"></param> /// <param name="colDataFormats"></param> /// <returns></returns> public static IWorkbook FillSheet(this IWorkbook book, string sheetName, DataTable excelData, IDictionary<string, string> colMaps, IDictionary<string, string> colDataFormats = null) { if (excelData.Rows.Count <= 0) return book; var sheet = book.CreateSheet(sheetName); var headerCellStyle = GetCellStyle(book, true); Dictionary<int, ICellStyle> colStyles = new Dictionary<int, ICellStyle>(); IRow rowHeader = sheet.CreateRow(0); int nIndex = 0; var headerColNames = new List<string>(); foreach (var item in colMaps) { ICell headerCell = rowHeader.CreateCell(nIndex); headerCell.SetCellValue(item.Value); headerCell.CellStyle = headerCellStyle; if (colDataFormats != null && colDataFormats.ContainsKey(item.Value)) { colStyles[nIndex] = GetCellStyleWithDataFormat(book, colDataFormats[item.Value]); } else { colStyles[nIndex] = GetCellStyle(book); } headerColNames.Add(item.Key); nIndex++; } //生成excel內容 for (int i = 0; i < excelData.Rows.Count; i++) { IRow irow = sheet.CreateRow(i + 1); var row = excelData.Rows[i]; for (int j = 0; j < headerColNames.Count; j++) { ICell cell = irow.CreateCell(j); string colName = headerColNames[j]; string cellValue = row[colName].ToNotNullString(); SetCellValue(cell, cellValue, excelData.Columns[colName].DataType, colStyles); } } return book; } private static PropertyInfo GetPropertyInfo<T, TR>(Expression<Func<T, TR>> select) { var body = select.Body; if (body.NodeType == ExpressionType.Convert) { var o = (body as UnaryExpression).Operand; return (o as MemberExpression).Member as PropertyInfo; } else if (body.NodeType == ExpressionType.MemberAccess) { return (body as MemberExpression).Member as PropertyInfo; } return null; } private static Type GetColType(string colTypeSimpleName) { colTypeSimpleName = colTypeSimpleName.ToUpper(); switch (colTypeSimpleName) { case "DT": { return typeof(DateTime); } case "BL": { return typeof(Boolean); } case "NUM": { return typeof(Int64); } case "DEC": { return typeof(Decimal); } default: { return typeof(String); } } } private static void SetCellValue(ICell cell, string value, Type colType, IDictionary<int, ICellStyle> colStyles) { if (colType.IsNullableType()) { colType = colType.GetGenericArguments()[0]; } string dataFormatStr = null; switch (colType.ToString()) { case "System.String": //字符串類型 cell.SetCellType(CellType.String); cell.SetCellValue(value); break; case "System.DateTime": //日期類型 DateTime dateV = new DateTime(); if (DateTime.TryParse(value, out dateV)) { cell.SetCellValue(dateV); } else { cell.SetCellValue(value); } dataFormatStr = "yyyy/mm/dd hh:mm:ss"; break; case "System.Boolean": //布爾型 bool boolV = false; if (bool.TryParse(value, out boolV)) { cell.SetCellType(CellType.Boolean); cell.SetCellValue(boolV); } else { cell.SetCellValue(value); } break; case "System.Int16": //整型 case "System.Int32": case "System.Int64": case "System.Byte": int intV = 0; if (int.TryParse(value, out intV)) { cell.SetCellType(CellType.Numeric); cell.SetCellValue(intV); } else { cell.SetCellValue(value); } dataFormatStr = "0"; break; case "System.Decimal": //浮點型 case "System.Double": double doubV = 0; if (double.TryParse(value, out doubV)) { cell.SetCellType(CellType.Numeric); cell.SetCellValue(doubV); } else { cell.SetCellValue(value); } dataFormatStr = "0.00"; break; case "System.DBNull": //空值處理 cell.SetCellType(CellType.Blank); cell.SetCellValue(string.Empty); break; default: cell.SetCellType(CellType.Unknown); cell.SetCellValue(value); break; } if (!string.IsNullOrEmpty(dataFormatStr) && colStyles[cell.ColumnIndex].DataFormat <= 0) //沒有設置,則採用默認類型格式 { colStyles[cell.ColumnIndex] = GetCellStyleWithDataFormat(cell.Sheet.Workbook, dataFormatStr); } cell.CellStyle = colStyles[cell.ColumnIndex]; ReSizeColumnWidth(cell.Sheet, cell); } private static ICellStyle GetCellStyleWithDataFormat(IWorkbook workbook, string format) { ICellStyle style = GetCellStyle(workbook); var dataFormat = workbook.CreateDataFormat(); short formatId = -1; if (dataFormat is HSSFDataFormat) { formatId = HSSFDataFormat.GetBuiltinFormat(format); } if (formatId != -1) { style.DataFormat = formatId; } else { style.DataFormat = dataFormat.GetFormat(format); } return style; } private static ICellStyle GetCellStyle(IWorkbook workbook, bool isHeaderRow = false) { ICellStyle style = workbook.CreateCellStyle(); if (isHeaderRow) { style.FillPattern = FillPattern.SolidForeground; style.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index; IFont f = workbook.CreateFont(); f.FontHeightInPoints = 11D; f.Boldweight = (short)FontBoldWeight.Bold; style.SetFont(f); } style.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin; style.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin; style.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin; style.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin; return style; } private static void ReSizeColumnWidth(ISheet sheet, ICell cell) { int cellLength = (Encoding.Default.GetBytes(cell.ToString()).Length + 2) * 256; const int maxLength = 60 * 256; //255 * 256; if (cellLength > maxLength) //當單元格內容超過30箇中文字符(英語60個字符)寬度,則強制換行 { cellLength = maxLength; cell.CellStyle.WrapText = true; } int colWidth = sheet.GetColumnWidth(cell.ColumnIndex); if (colWidth < cellLength) { sheet.SetColumnWidth(cell.ColumnIndex, cellLength); } } private static ISheet GetSheet(IWorkbook workbook, string sheetIndexOrName) { int sheetIndex = 0; ISheet sheet = null; if (int.TryParse(sheetIndexOrName, out sheetIndex)) { sheet = workbook.GetSheetAt(sheetIndex); } else { sheet = workbook.GetSheet(sheetIndexOrName); } return sheet; } /// <summary> /// 從工做表中解析生成DataTable /// </summary> /// <param name="workbook"></param> /// <param name="sheetIndexOrName"></param> /// <param name="headerRowIndex"></param> /// <param name="startColIndex"></param> /// <param name="colCount"></param> /// <returns></returns> public static DataTable ResolveDataTable(this IWorkbook workbook, string sheetIndexOrName, int headerRowIndex, short startColIndex = 0, short colCount = 0) { DataTable table = new DataTable(); ISheet sheet = GetSheet(workbook, sheetIndexOrName); IRow headerRow = sheet.GetRow(headerRowIndex); int cellFirstNum = (startColIndex > headerRow.FirstCellNum ? startColIndex : headerRow.FirstCellNum); int cellCount = (colCount > 0 && colCount < headerRow.LastCellNum ? colCount : headerRow.LastCellNum); for (int i = cellFirstNum; i < cellCount; i++) { if (headerRow.GetCell(i) == null || headerRow.GetCell(i).StringCellValue.Trim() == "") { // 若是遇到第一個空列,則再也不繼續向後讀取 cellCount = i; break; } DataColumn column = new DataColumn(headerRow.GetCell(i).StringCellValue); table.Columns.Add(column); } for (int i = (headerRowIndex + 1); i <= sheet.LastRowNum; i++) { IRow row = sheet.GetRow(i); if (row != null) { List<string> cellValues = new List<string>(); for (int j = cellFirstNum; j < cellCount; j++) { if (row.GetCell(j) != null) { cellValues.Add(row.GetCell(j).ToNotNullString()); } else { cellValues.Add(string.Empty); } } table.Rows.Add(cellValues.ToArray()); } } return table; } /// <summary> /// 從工做表中解析生成指定的結果對象列表 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="workbook"></param> /// <param name="sheetIndexOrName"></param> /// <param name="headerRowIndex"></param> /// <param name="buildResultItemFunc"></param> /// <param name="startColIndex"></param> /// <param name="colCount"></param> /// <returns></returns> public static List<T> ResolveAs<T>(this IWorkbook workbook, string sheetIndexOrName, int headerRowIndex, Func<List<string>, T> buildResultItemFunc, short startColIndex = 0, short colCount = 0) { ISheet sheet = GetSheet(workbook, sheetIndexOrName); IRow headerRow = sheet.GetRow(headerRowIndex); int cellFirstNum = (startColIndex > headerRow.FirstCellNum ? startColIndex : headerRow.FirstCellNum); int cellCount = (colCount > 0 && colCount < headerRow.LastCellNum ? colCount : headerRow.LastCellNum); List<T> resultList = new List<T>(); for (int i = (headerRowIndex + 1); i <= sheet.LastRowNum; i++) { IRow row = sheet.GetRow(i); if (row != null) { List<string> cellValues = new List<string>(); for (int j = cellFirstNum; j < cellCount; j++) { if (row.GetCell(j) != null) { cellValues.Add(row.GetCell(j).ToNotNullString()); } else { cellValues.Add(string.Empty); } } resultList.Add(buildResultItemFunc(cellValues)); } } return resultList; } public static MemoryStream ToExcelStream(this IWorkbook book) { if (book.NumberOfSheets <= 0) { throw new Exception("無有效的sheet數據"); } MemoryStream stream = new MemoryStream(); stream.Seek(0, SeekOrigin.Begin); book.Write(stream); return stream; } public static byte[] ToExcelBytes(this IWorkbook book) { using (MemoryStream stream = ToExcelStream(book)) { return stream.ToArray(); } } public static JObject HttpUpload(this IWorkbook book, string uploadUrl, IDictionary<string, object> fieldData = null, string exportFileName = null) { using (HttpClient client = new HttpClient()) { MultipartFormDataContent formData = new MultipartFormDataContent(); ByteArrayContent fileContent = new ByteArrayContent(ToExcelBytes(book)); //StreamContent fileContent = new StreamContent(ToExcelStream(book)); 兩者均可以 fileContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data"); if (string.IsNullOrWhiteSpace(exportFileName)) { exportFileName = Guid.NewGuid().ToString("N") + ((book is XSSFWorkbook) ? ".xlsx" : ".xls"); } fileContent.Headers.ContentDisposition.FileName = exportFileName; fileContent.Headers.ContentDisposition.Name = "file"; formData.Add(fileContent); Func<string, StringContent> getStringContent = (str) => new StringContent(str, Encoding.UTF8); if (fieldData != null) { foreach (var header in fieldData) { formData.Add(getStringContent(header.Value.ToNotNullString()), header.Key); } } HttpResponseMessage res = client.PostAsync(uploadUrl, formData).Result; string resContent = res.Content.ReadAsStringAsync().Result; return JObject.Parse(resContent); } } public static string SaveToFile(this IWorkbook book, string filePath) { if (File.Exists(filePath)) { File.SetAttributes(filePath, FileAttributes.Normal); File.Delete(filePath); } using (FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { book.Write(fs); } return filePath; } } }
如上代碼都比較簡單沒有什麼複雜要,故再也不細述。還有一個Core類,這個只是一個入口幫助類,若是已有得到IWorkbook的自定義方法,該類能夠不用,代碼以下:性能
using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using System; using System.Collections.Generic; using System.Text; namespace ExcelEasyUtil { /// <summary> /// NPOI 相關核心入口方法幫助類 /// author:zuowenjun /// 2019-5-21 /// </summary> public static class Core { /// <summary> /// 建立一個基本XLSX格式的EXCEL工做薄對象 /// </summary> /// <returns></returns> public static IWorkbook CreateXlsxWorkBook() { return new XSSFWorkbook(); } /// <summary> /// 建立一個基本XLS格式的EXCEL工做薄對象 /// </summary> /// <returns></returns> public static IWorkbook CreateXlsWorkBook() { return new HSSFWorkbook(); } /// <summary> /// 打開指定文件的EXCEL工做薄對象 /// </summary> /// <param name="filePath">Excel文件路徑</param> /// <returns></returns> public static IWorkbook OpenWorkbook(string filePath) { bool isCompatible = filePath.EndsWith(".xls", StringComparison.OrdinalIgnoreCase); var fileStream = System.IO.File.OpenRead(filePath); if (isCompatible) { return new HSSFWorkbook(fileStream); } else { return new XSSFWorkbook(fileStream); } } } }
雖然代碼簡單,但方法命名稍有些講究,易閱讀與理解,CreateXlsxWorkBook就是表現建立一個新的基於xlsx格式的工做薄對象,而CreateXlsWorkBook就是表現建立一個新的基於xls格式的工做薄對象,我並沒合成一個方法,而後使用一個bool參數或enum參數來區分,我以爲在這個追求極簡、高效的開發理念中,方法名要易於理解與快速上手,不該產生歧義,也無需太多的參數。OpenWorkbook就是打開一個已有的EXCEL文件工做薄對象。網站
代碼雖簡單,但我經過合理的封裝入參,委託參數等,實現了簡單但又不失靈活的EXCEL操做方式,沒有一味追求極簡,把全部的複雜操做所有封裝,從而致使原本簡單的事情搞得複雜化,好比:將一個List<T>導出到EXCEL中,常見的實現方式確定就是經過反射得到屬性信息,再利用屬性信息得到值,這是作雖入參簡單,但性能很差,而本文的這個類庫將取值或賦值的方式經過Func委託交由給具體使用的地方,從而避免了反射帶來的性能損失,好了,以下展現幾個使用示例,幫助你們理解和使用。ui
第一種填充sheet方式:(重點在表格頭的映射設置,經過Lamba屬性表達式與要生成的EXCEL表頭進行關聯映射)
var book= ExcelEasyUtil.Core.CreateXlsxWorkBook() .FillSheet("人員列表1", peoples,//填充第一個表格 //new Dictionary<string, Expression<Func<People, dynamic>>> //設置表格頭,原始類型 new PropertyColumnMapping<People> //設置表格頭,專用簡化類型 { {"姓名",p=>p.Name },{"年齡",p=>p.Age },{"生日",p=>p.Birthday },{"住址",p=>p.Address },{"學歷",p=>p.Education }, { "有工做否",p=>p.hasWork },{"備註",p=>p.Remark } }, new Dictionary<string, string> //爲指定的列設置單元格格式 { { "年齡","0歲"},{"生日","yyyy年mm月dd日"} });
第二種填充sheet方式:(重點在表格頭類型設置【:XXX表示生成的EXCEL該列爲某種格式的單元格,如:生日:DT表示是生日這列導出是日期類型格式】,第二個參數返回List<object>這個是能夠很好的控制導出時須要的填充數據,能夠自由控制數據,好比示例代碼中額外增長了一列判斷的數據列內容,第三個參數是爲指定的列設置單元格的具體應用格式)
var book= ExcelEasyUtil.Core.CreateXlsxWorkBook() .FillSheet("人員列表2", peoples, //填充第二個表格 new List<string> { "姓名","年齡:NUM","生日:DT","住址","學歷","有工做否:BL","備註","額外填充列" }, (p) => { return new List<object> { p.Name,p.Age,p.Birthday,p.Address,p.Education,p.hasWork?"有":"無",p.Remark,(p.Age<=30 && p.hasWork)?"年輕有爲":"要麼老了要麼沒工做,生活堪憂" }; }, new Dictionary<string, string> { { "生日","yyyy-mm-dd"} });
第三種填充sheet方式:(重點仍然是在表頭映射,因爲這裏的數據源是DataTable,故只是設置DataTable的列與EXCEL要導出的列名映射便可,無需指定列類型,第二個參數是爲指定的列設置單元格的具體應用格式)
var book= ExcelEasyUtil.Core.CreateXlsxWorkBook() .FillSheet("人員列表3", peoplesTable, //填充第三個表格 new Dictionary<string, string> { {"Name","姓名" },{"Birthday","生日" },{"Address","住址" },{"Education","學歷" }, {"hasWork","有工做否" },{"Remark","備註" } } , new Dictionary<string, string> { { "生日","yyyy-mm-dd"} });
因爲實現了FillSheet方法後仍返回IWorkBook實例自己,便可採用鏈式的方式來快速完成多個sheet導出的,合併代碼以下:
string savedPath = ExcelEasyUtil.Core.CreateXlsxWorkBook() .FillSheet("人員列表1", peoples,//填充第一個表格 //new Dictionary<string, Expression<Func<People, dynamic>>> //設置表格頭,原始類型 new PropertyColumnMapping<People> //設置表格頭,專用簡化類型 { {"姓名",p=>p.Name },{"年齡",p=>p.Age },{"生日",p=>p.Birthday },{"住址",p=>p.Address },{"學歷",p=>p.Education }, { "有工做否",p=>p.hasWork },{"備註",p=>p.Remark } }, new Dictionary<string, string> //爲指定的列設置單元格格式 { { "年齡","0歲"},{"生日","yyyy年mm月dd日"} }) .FillSheet("人員列表2", peoples, //填充第二個表格 new List<string> { "姓名","年齡:NUM","生日:DT","住址","學歷","有工做否:BL","備註","額外填充列" }, (p) => { return new List<object> { p.Name,p.Age,p.Birthday,p.Address,p.Education,p.hasWork?"有":"無",p.Remark,(p.Age<=30 && p.hasWork)?"年輕有爲":"要麼老了要麼沒工做,生活堪憂" }; }, new Dictionary<string, string> { { "生日","yyyy-mm-dd"} }) .FillSheet("人員列表3", peoplesTable, //填充第三個表格 new Dictionary<string, string> { {"Name","姓名" },{"Birthday","生日" },{"Address","住址" },{"Education","學歷" }, {"hasWork","有工做否" },{"Remark","備註" } } , new Dictionary<string, string> { { "生日","yyyy-mm-dd"} }) .SaveToFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "testdata123.xlsx")); Console.WriteLine("導出EXCEL文件路徑:" + savedPath);
感受如何,EXCEL導出既能設置列頭,列格式,還能控制填充的數據值,認爲是否夠方便呢,我我的以爲仍是能夠知足平常大部份的使用EXCEL的需求。
說了導出EXCEL方法再來貼出導入EXCEL數據(這裏稱爲解析EXCEL數據)的示例用法:
var xlsTable = ExcelEasyUtil.Core.OpenWorkbook(savedPath).ResolveDataTable("人員列表1", 0); foreach (DataRow row in xlsTable.Rows) { string rowStr = string.Join("\t", row.ItemArray); Console.WriteLine(rowStr); } var xlsPeoples = ExcelEasyUtil.Core.OpenWorkbook(savedPath).ResolveAs<People>("人員列表2", 0, list => { return new People { Name = list[0], Birthday = ConvertToDate(list[2]),//日期處理相對較麻煩 Address = list[3] }; }, 0, 4); Console.WriteLine("-".PadRight(30,'-')); foreach (var p in xlsPeoples) { string rowStr = string.Join("\t", p.Name, p.Age, p.Birthday, p.Address); Console.WriteLine(rowStr); }
這裏僅實現瞭解析到DataTable或解析到所需的對象集合,通常也能知足常見的導入數據的要求。
固然還有:HttpUpload方法,這個主要是把生成的內存EXCEL文件直接上傳至指定的文件服務器的,若是是在ASP.NET,ASP.NET CORE服務端須要下載,那麼則能夠採用先使用:book.ToExcelBytes(),而後構造文件字節流Result便可,好比:MVC中的File,能夠參照我本文一開始列舉的第二中方法中的導出,在此就再也不貼示例了。
好了,以上就是本文的所有內容,可能大神們認爲這太簡單了,但我認爲簡單高效的實用類庫仍是須要的,由於ExcelEasyUtil自己就是爲簡單、輕量、實用而封裝的,故不會有太多複雜的東西,若是須要複雜的EXCEL操做就使用我上面說的第四種方案:ExcelUtility。
如有不足之處或好的建議,歡迎評論,謝謝!
本文ExcelEasyUtil源代碼地址:https://github.com/zuowj/ExcelEasyUtil (文中的全部示例代碼在github均有)
爲了方便開發者使用,還封裝成了NuGet包:
Packge Manager:Install-Package ExcelEasyUtil -Version 1.0.0
.NET CLI:dotnet add package ExcelEasyUtil --version 1.0.0 OR <PackageReference Include="ExcelEasyUtil" Version="1.0.0" />