上周六我發表的文章《分享我基於NPOI+ExcelReport實現的導入與導出EXCEL類庫:ExcelUtility》受到了大家的熱烈支持與推薦,再此表示感謝,該ExcelUtility類庫自上次發文起,又經過了多次的改進,增加了許多的功能與方法,可以全面滿足大家的需求,下麵先來看一下新方法的測試...
上周六我發表的文章《分享我基於NPOI+ExcelReport實現的導入與導出EXCEL類庫:ExcelUtility》受到了大家的熱烈支持與推薦,再此表示感謝,該ExcelUtility類庫自上次發文起,又經過了多次的改進,增加了許多的功能與方法,可以全面滿足大家的需求,下麵先來看一下新方法的測試結果:
第一個新增功能,列寬自適應,當超過30個字元則將單元格內容設為換行
任意一個無模板的導出方法均支持該功能,示例代碼如下:
/// <summary> /// 測試方法:測試將DataTable導出到EXCEL,無模板 /// </summary> [TestMethod] public void TestExportToExcelByDataTable() { DataTable dt = GetDataTable(); string excelPath = ExcelUtility.Export.ToExcel(dt, "導出結果"); Assert.IsTrue(File.Exists(excelPath)); }
結果如下圖示:
第二個新增功能,依據數據源(DataTable、DataGridView)的列類型自動將與之對應的EXCEL列的單元格式設為相同的格式內容顯示,如:整數類型顯示在單元格內無小數的數字格式,有小數位的類顯示在單元格內2位小數數字格式,日期類型顯示在單元格內日期+時間的日期格式,布爾類型顯示在單元格內布爾格式,任意一個無模板的導出方法均支持該功能,示例代碼如下:
/// <summary> /// 測試方法:測試將DataTable導出到EXCEL,無模板,且指定導出的列名,以及導出列名的重命名 /// </summary> [TestMethod] public void TestExportToExcelByDataTable3() { DataTable dt = GetDataTable(); string[] expColNames = { "Col1", "Col2", "Col3", "Col4", "Col5", "Col7" }; Dictionary<string, string> expColAsNames = new Dictionary<string, string>() { {"Col1","列一"}, {"Col2","列二"}, {"Col3","列三"}, {"Col4","數字列"}, {"Col5","列五"}, {"Col7","日期列"} }; string excelPath = ExcelUtility.Export.ToExcel(dt, "導出結果", null, expColNames, expColAsNames); Assert.IsTrue(File.Exists(excelPath)); }
結果如下圖示:
第三個新增功能,在第二個新增功能的基礎上,增加可以自定義設置列的單元格顯示格式(支持日期類型、數字類型),任意一個無模板的導出方法均支持該功能,示例代碼如下:
/// <summary> /// 測試方法:測試將DataTable導出到EXCEL,無模板,且指定某些列的顯示格式 /// </summary> [TestMethod] public void TestExportToExcelByDataTable6() { DataTable dt = GetDataTable(); var colDataFormatDic = new Dictionary<string, string> { {"Col4","0.000"}, //將Col4列DOUBLE類型的EXCEL對應列格式設置為顯示成3位小數(預設為2位小數) {"Col7","yyyy-mm-dd"}//將Col7列DateTime類型的EXCEL對應列格式設置為年月日(預設為yyyy/mm/dd hh:mm:ss) }; //更多設置格式可在EXCEL的設置單元格格式中的數字選項卡中的自定義格式列表(若無,可自定義,建議先在EXCEL中測試好格式字元串後再用於程式中) string excelPath = ExcelUtility.Export.ToExcel(dt, "導出結果", colDataFormats: colDataFormatDic); Assert.IsTrue(File.Exists(excelPath)); }
結果如下圖示:
換種格式定義測試:
/// <summary> /// 測試方法:測試將DataTable導出到EXCEL,無模板,且指定某些列的顯示格式 /// </summary> [TestMethod] public void TestExportToExcelByDataTable7() { DataTable dt = GetDataTable(); var colDataFormatDic = new Dictionary<string, string> { {"Col4","¥#,##0.00_);(¥#,##0.00)"}, //將Col4列DOUBLE類型的EXCEL對應列格式設置為顯示成包含貨幣格式,如:¥5.00(預設為2位小數) {"Col7","yyyy\"年\"m\"月\"d\"日\";@"}//將Col7列DateTime類型的EXCEL對應列格式設置為中文年月日,如:2015年12月5日(預設為yyyy/mm/dd hh:mm:ss) }; //更多設置格式可在EXCEL的設置單元格格式中的數字選項卡中的自定義格式列表(若無,可自定義,建議先在EXCEL中測試好格式字元串後再用於程式中) string excelPath = ExcelUtility.Export.ToExcel(dt, "導出結果", colDataFormats: colDataFormatDic); Assert.IsTrue(File.Exists(excelPath)); }
結果如下圖示:
註意事項說明:想要實現導出的EXCEL單元格依據數據類型自動設置或手動指定格式,需首先確保數據源的列與自動或手動設置的格式相符,即列類型必需是數字類型、日期類型、布爾類型,不能是以字元串的形式存在的這些所謂的“數字類型、日期類型、布爾類型”
第四個新增的功能,可指定DataGridView是否可以導出隱藏列(不顯示的列)、及指定依據DataGridView標題列名導出相應列數據,示例代碼如下:
/// <summary> /// 測試方法:測試將DataGridView數據導出到EXCEL文件,無模板,且不導出隱藏列 /// </summary> [TestMethod] public void TestToExcelByDataGridView() { var grid = GetDataGridViewWithData(); string excelPath = ExcelUtility.Export.ToExcel(grid, "導出結果", null, false); Assert.IsTrue(File.Exists(excelPath)); }
結果如下圖示:
第五個新增功能,DataGridView若改變列的顯示位置,導出的數據也能與界面顯示的數據同步調整,示例代碼如下:
/// <summary> /// 測試方法:測試將DataGridView數據導出到EXCEL文件,無模板,改變列的顯示位置,導出隱藏列 /// </summary> [TestMethod] public void TestToExcelByDataGridView2() { var grid = GetDataGridViewWithData(); //模擬改變列的顯示位置 grid.Columns[0].DisplayIndex = 1; grid.Columns[1].DisplayIndex = 0; string excelPath = ExcelUtility.Export.ToExcel(grid, "導出結果", null, true); Assert.IsTrue(File.Exists(excelPath)); }
結果如下圖示:
以下是GetDataGridViewWithData模擬數據方法:
private DataGridView GetDataGridViewWithData() { var grid = new DataGridView(); var dt = GetDataTable(); foreach (DataColumn col in dt.Columns) { bool v = col.Ordinal > 4 ? false : true; grid.Columns.Add(new DataGridViewTextBoxColumn() { DataPropertyName = col.ColumnName, HeaderText ="列名" + col.ColumnName , Visible = v,ValueType=col.DataType }); } foreach (DataRow row in dt.Rows) { ArrayList values = new ArrayList(); foreach (DataColumn col in dt.Columns) { values.Add(row[col]); } grid.Rows.Add(values.ToArray()); } return grid; }
我相信這些功能加上上次的功能,應該能滿足大家日常工作中所遇到的各種導出EXCEL場景吧,下麵重新公佈一下兩個核心的與導出相關類源代碼,以供大家參考,若有不足之處,敬請指出,謝謝!
ExcelUtility.Export:
using ExcelReport; using ExcelUtility.Base; using NPOI.SS.UserModel; using System; using System.Collections.Generic; using System.Data; using System.IO; using System.Linq; using System.Text; using System.Windows.Forms; namespace ExcelUtility { /// <summary> /// EXCEL導出功能集合類 /// 作者:Zuowenjun /// 日期:2016/1/15 /// </summary> public sealed class Export { /// <summary> /// 由DataSet導出Excel /// </summary> /// <param name="sourceTable">要導出數據的DataTable</param> /// <param name="filePath">導出路徑,可選</param> /// <returns></returns> public static string ToExcel(DataSet sourceDs, string filePath = null) { if (string.IsNullOrEmpty(filePath)) { filePath = Common.GetSaveFilePath(); } if (string.IsNullOrEmpty(filePath)) return null; bool isCompatible = Common.GetIsCompatible(filePath); IWorkbook workbook = Common.CreateWorkbook(isCompatible); ICellStyle headerCellStyle = Common.GetCellStyle(workbook, true); //ICellStyle cellStyle = Common.GetCellStyle(workbook); for (int i = 0; i < sourceDs.Tables.Count; i++) { DataTable table = sourceDs.Tables[i]; string sheetName = string.IsNullOrEmpty(table.TableName) ? "result" + i.ToString() : table.TableName; ISheet sheet = workbook.CreateSheet(sheetName); IRow headerRow = sheet.CreateRow(0); Dictionary<int, ICellStyle> colStyles = new Dictionary<int, ICellStyle>(); // handling header. foreach (DataColumn column in table.Columns) { ICell headerCell = headerRow.CreateCell(column.Ordinal); headerCell.SetCellValue(column.ColumnName); headerCell.CellStyle = headerCellStyle; sheet.AutoSizeColumn(headerCell.ColumnIndex); colStyles[headerCell.ColumnIndex] = Common.GetCellStyle(workbook); } // handling value. int rowIndex = 1; foreach (DataRow row in table.Rows) { IRow dataRow = sheet.CreateRow(rowIndex); foreach (DataColumn column in table.Columns) { ICell cell = dataRow.CreateCell(column.Ordinal); //cell.SetCellValue((row[column] ?? "").ToString()); //cell.CellStyle = cellStyle; Common.SetCellValue(cell, (row[column] ?? "").ToString(), column.DataType,colStyles); Common.ReSizeColumnWidth(sheet, cell); } rowIndex++; } sheet.ForceFormulaRecalculation = true; } FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); workbook.Write(fs); fs.Dispose(); workbook = null; return filePath; } /// <summary> /// 由DataTable導出Excel /// </summary> /// <param name="sourceTable">要導出數據的DataTable</param> /// <param name="colAliasNames">導出的列名重命名數組</param> /// <param name="sheetName">工作薄名稱,可選</param> /// <param name="filePath">導出路徑,可選</param> /// <param name="colDataFormats">列格式化集合,可選</param> /// <returns></returns> public static string ToExcel(DataTable sourceTable, string[] colAliasNames, string sheetName = "result", string filePath = null, IDictionary<string, string> colDataFormats = null) { if (sourceTable.Rows.Count <= 0) return null; if (string.IsNullOrEmpty(filePath)) { filePath = Common.GetSaveFilePath(); } if (string.IsNullOrEmpty(filePath)) return null; if (colAliasNames == null || sourceTable.Columns.Count != colAliasNames.Length) { throw new ArgumentException("列名重命名數組與DataTable列集合不匹配。", "colAliasNames"); } bool isCompatible = Common.GetIsCompatible(filePath); IWorkbook workbook = Common.CreateWorkbook(isCompatible); ICellStyle headerCellStyle = Common.GetCellStyle(workbook, true); //ICellStyle cellStyle = Common.GetCellStyle(workbook); Dictionary<int, ICellStyle> colStyles = new Dictionary<int, ICellStyle>(); ISheet sheet = workbook.CreateSheet(sheetName); IRow headerRow = sheet.CreateRow(0); // handling header. foreach (DataColumn column in sourceTable.Columns) { ICell headerCell = headerRow.CreateCell(column.Ordinal); headerCell.SetCellValue(colAliasNames[column.Ordinal]); headerCell.CellStyle = headerCellStyle; sheet.AutoSizeColumn(headerCell.ColumnIndex); if (colDataFormats != null && colDataFormats.ContainsKey(column.ColumnName)) { colStyles[headerCell.ColumnIndex] = Common.GetCellStyleWithDataFormat(workbook, colDataFormats[column.ColumnName]); } else { colStyles[headerCell.ColumnIndex] = Common.GetCellStyle(workbook); } } // handling value. int rowIndex = 1; foreach (DataRow row in sourceTable.Rows) { IRow dataRow = sheet.CreateRow(rowIndex); foreach (DataColumn column in sourceTable.Columns) { ICell cell = dataRow.CreateCell(column.Ordinal); //cell.SetCellValue((row[column] ?? "").ToString()); //cell.CellStyle = cellStyle; Common.SetCellValue(cell, (row[column] ?? "").ToString(), column.DataType, colStyles); Common.ReSizeColumnWidth(sheet, cell); } rowIndex++; } sheet.ForceFormulaRecalculation = true; FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); workbook.Write(fs); fs.Dispose(); sheet = null; headerRow = null; workbook = null; return filePath; } /// <summary> /// 由DataGridView導出 /// </summary> /// <param name="grid">要導出的DataGridView對象</param> /// <param name="sheetName">工作薄名稱,可選</param> /// <param name="filePath">導出路徑,可選</param> /// <param name="includeHiddenCol">導出時是否包含隱藏列,可選</param> /// <param name="colHeaderTexts">指定導出DataGridView的列標題名數組,可選</param> /// <param name="colDataFormats">列格式化集合,可選</param> /// <returns></returns> public static string ToExcel(DataGridView grid, string sheetName = "result", string filePath = null, bool includeHiddenCol = false, string[] colHeaderTexts = null, IDictionary<string, string> colDataFormats = null) { if (grid.Rows.Count <= 0) return null; if (string.IsNullOrEmpty(filePath)) { filePath = Common.GetSaveFilePath(); } if (string.IsNullOrEmpty(filePath)) return null; bool isCompatible = Common.GetIsCompatible(filePath); DataGridViewColumn[] expCols = null; expCols = grid.Columns.Cast<DataGridViewColumn>().OrderBy(c => c.DisplayIndex).ToArray(); if (!includeHiddenCol) { expCols = expCols.Where(c => c.Visible).ToArray(); } if (colHeaderTexts != null && colHeaderTexts.Length > 0) { expCols = expCols.Where(c => colHeaderTexts.Contains(c.HeaderText)).ToArray(); } IWorkbook workbook = Common.CreateWorkbook(isCompatible); ICellStyle headerCellStyle = Common.GetCellStyle(workbook, true); //ICellStyle cellStyle = Common.GetCellStyle(workbook); ISheet sheet = workbook.CreateSheet(sheetName); IRow headerRow = sheet.CreateRow(0); Dictionary<int, ICellStyle> colStyles = new Dictionary<int, ICellStyle>(); for (int i = 0; i < expCols.Length; i++) { ICell headerCell = headerRow.CreateCell(i); headerCell.SetCellValue(expCols[i].HeaderText); headerCell.CellStyle = headerCellStyle; sheet.AutoSizeColumn(headerCell.ColumnIndex); if (colDataFormats != null && colDataFormats.ContainsKey(expCols[i].HeaderText)) { colStyles[headerCell.ColumnIndex] = Common.GetCellStyleWithDataFormat(workbook, colDataFormats[expCols[i].HeaderText]); } else { colStyles[headerCell.ColumnIndex] = Common.GetCellStyle(workbook); } } int rowIndex = 1; foreach (DataGridViewRow row in grid.Rows) { IRow dataRow = sheet.CreateRow(rowIndex); for (int n = 0; n < expCols.Length; n++) { ICell cell = dataRow.CreateCell(n); //cell.SetCellValue((row.Cells[expCols[n].Index].Value ?? "").ToString()); //cell.CellStyle = cellStyle; Common.SetCellValue(cell, (row.Cells[expCols[n].Index].Value ?? "").ToString(), expCols[n].ValueType, colStyles); Common.ReSizeColumnWidth(sheet, cell); } rowIndex++; } sheet.ForceFormulaRecalculation = true; FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); workbook.Write(fs); fs.Dispose(); sheet = null; headerRow = null; workbook = null; return filePath; } /// <summary> /// 由DataTable導出Excel /// </summary> /// <param name="sourceTable">要導出數據的DataTable</param> /// <param name="sheetName">工作薄名稱,可選</param> /// <param name="filePath">導出路徑,可選</param> /// <param name="colNames">需要導出的列名,可選</param> /// <param name="colAliasNames">導出的列名重命名,可選</param> /// <param name="colDataFormats">列格式化集合,可選</param> /// <returns></returns> public static string ToExcel(DataTable sourceTable, string sheetName = "result", string filePath = null, string[] colNames = null, IDictionary<string, string> colAliasNames = null, IDictionary<string, string> colDataFormats = null) { if (sourceTable.Rows.Count <= 0) return null; if (string.IsNullOrEmpty(filePath)) { filePath = Common.GetSaveFilePath(); } if (string.IsNullOrEmpty(filePath)) return null; bool isCompatible = Common.GetIsCompatible(filePath); IWorkbook workbook = Common.CreateWorkbook(isCompatible); ICellStyle headerCellStyle = Common.GetCellStyle(workbook, true); //ICellStyle cellStyle = Common.GetCellStyle(workbook); Dictionary<int, ICellStyle> colStyles = new Dictionary<int, ICellStyle>(); ISheet sheet = workbook.CreateSheet(sheetName); IRow headerRow = sheet.CreateRow(0); if (colNames == null || colNames.Length <= 0) { colNames = sourceTable.Columns.Cast<DataColumn>().OrderBy(c => c.Ordinal).Select(c => c.ColumnName).ToArray(); } // handling header. for (int i = 0; i < colNames.Length; i++) { ICell headerCell = headerRow.CreateCell(i); if (colAliasNames != null && colAliasNames.ContainsKey(colNames[i])) { headerCell.SetCellValue(colAliasNames[colNames[i]]); } else { headerCell.SetCellValue(colNames[i]); } headerCell.CellStyle = headerCellStyle; sheet.AutoSizeColumn(headerCell.ColumnIndex); if (colDataFormats != null && colDataFormats.ContainsKey(colNames[i])) { colStyles[headerCell.ColumnIndex] = Common.GetCellStyleWithDataFormat(workbook, colDataFormats[colNames[i]]); } else { colStyles[headerCell.ColumnIndex] = Common.GetCellStyle(workbook); } } // handling value. int rowIndex = 1; foreach (DataRow row in sourceTable.Rows) { IRow dataRow = sheet.CreateRow(rowIndex); for (int i = 0; i < colNames.Length; i++) { ICell cell = dataRow.CreateCell(i); //cell.SetCellValue((row[colNames[i]] ?? "").ToString()); //cell.CellStyle = cellStyle; Common.SetCellValue(cell, (row[colNames[i]] ?? "").ToString(), sourceTable.Columns[colNames[i]].DataType,colStyles); Common.ReSizeColumnWidth(sheet, cell); } rowIndex++; } sheet.ForceFormulaRecalculation = true; FileStream fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite); workbook.Write(fs); fs.Dispose(); sheet = null; headerRow = null; workbook = null; return filePath; } /// <summary> ///由SheetFormatterContainer導出基於EXCEL模板的文件 /// </summary> /// <param name="templatePath">模板路徑</param> /// <param name="sheetName">模板中使用的工作薄名稱</param> /// <param name="formatterContainer">模板數據格式化容器</param> /// <param name="filePath">導出路徑,可選</param> /// <returns></returns> public static string ToExcelWithTemplate<T>(string templatePath, string sheetName, SheetFormatterContainer<T> formatterContainer, string filePath = null) { if (!File.Exists(templatePath)) { throw new FileNotFoundException(templatePath + "文件不存在!"); } if (string.IsNullOrEmpty(filePath)) { filePath = Common.GetSaveFilePath(); } if (string.IsNullOrEmpty(filePath)) return null; string templateConfigFilePath = Common.GetTemplateConfigFilePath(templatePath, false); var workbookParameterContainer = new WorkbookParameterContainer(); workbookParameterContainer.Load(templateConfigFilePath); SheetParameterContainer sheetParameterContainer = workbookParameterContainer[sheetName]; ExportHelper.ExportToLocal(templatePath, filePath, new SheetFormatter(sheetName, formatterContainer.GetFormatters(sheetParameterContainer))); return filePath; } /// <summary> /// 由SheetFormatterContainer集合導出基於EXCEL模板(多工作薄)的文件 /// </summary> /// <param name="templatePath"></param> /// <param name="formatterContainers"></param> /// <param name="filePath"></param> /// <returns></returns> public static string ToExcelWithTemplate(string templatePath,IDictionary<string,SheetFormatterContainer<dynamic>> formatterContainers, string filePath = null) { if (!File.Exists(templatePath)) { throw new FileNotFoundException(templatePath + "文件不存在!"); } if (string.IsNullOrEmpty(filePath)) { filePath = Common.GetSaveFilePath(); } if (string.IsNullOrEmpty(filePath)) return null; string templateConfigFilePath = Common.GetTemplateConfigFilePath(templatePath, false); var workbookParameterContainer = new WorkbookParameterContainer(); workbookParameterContainer.Load(templateConfigFilePath); List<SheetFormatter> sheetFormatterList = new List<SheetFormatter>(); foreach (var item in formatterContainers) { SheetParameterContainer sheetParameterContainer = workbookParameterContainer[item.Key]; sheetFormatterList.Add(new SheetFormatter(item.Key, item.Value.GetFormatters(sheetParameterContainer))); } ExportHelper.ExportToLocal(templatePath, filePath,sheetFormatterList.ToArray()); return filePath; } } }
ExcelUtility.Base.Common:
using ExcelReport; 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; using System.Text; using System.Text.RegularExpressions; using System.Windows.Forms; namespace ExcelUtility.Base { /// <summary> /// ExcelUtility類庫內部通用功能類 /// 作者:Zuowenjun /// 日期:2016/1/15 /// </summary> internal static class Common { public static string DesktopDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); /// <summary> /// 獲取要保存的文件名稱(含完整路徑) /// </summary> /// <returns></returns> public static string GetSaveFilePath() { SaveFileDialog saveFileDig = new SaveFileDialog(); saveFileDig.Filter = "Excel Office97-2003(*.xls)|*.xls|Excel Office2007及以上(*.xlsx)|*.xlsx"; saveFileDig.FilterIndex = 0; saveFileDig.Title = "導出到"; saveFileDig.OverwritePrompt = true; saveFileDig.InitialDirectory = DesktopDirectory; string filePath = null; if (saveFileDig.ShowDialog() == DialogResult.OK) { filePath = saveFileDig.FileName; } return filePath; } /// <summary> /// 獲取要打開要導入的文件名稱(含完整路徑) /// </summary> /// <returns></returns> public static string GetOpenFilePath() { OpenFileDialog openFileDig = new OpenFileDialog(); openFileDig.Filter = "Excel Office97-2003(*.xls)|*.xls|Excel Office2007及以上(*.xlsx)|*.xlsx"; openFileDig.FilterIndex = 0; openFileDig.Title = "打開"; openFileDig.CheckFileExists = true; openFileDig.CheckPathExists = true; openFileDig.InitialDirectory = Common.DesktopDirectory; string filePath = null; if (openFileDig.ShowDialog() == DialogResult.OK) { filePath = openFileDig.FileName; } return filePath; } /// <summary> /// 判斷是否為相容模式 /// </summary> /// <param name="filePath"></param> /// <returns></returns> public static bool GetIsCompatible(string filePath) { return filePath.EndsWith(".xls", StringComparison.OrdinalIgnoreCase); } /// <summary> /// 創建工作薄 /// </summary> /// <param name="isCompatible"></param> /// <returns></returns> public static IWorkbook CreateWorkbook(bool isCompatible) { if (isCompatible) { return new HSSFWorkbook(); } else { return new XSSFWorkbook(); } } /// <summary> /// 創建工作薄(依據文件流) /// </summary> /// <param name="isCompatible"></param> /// <param name="stream"></param> /// <returns></returns> public static IWorkbook CreateWorkbook(bool isCompatible, dynamic stream) { if (isCompatible) { return new HSSFWorkbook(stream); } else { return new XSSFWorkbook(stream); } } /// <summary> /// 創建單元格樣式 /// </summary> /// <param name="sheet"></param> /// <returns></returns> public 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.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; } /// <summary> /// 根據單元格內容重新設置列寬 /// </summary> /// <param name="sheet"></param> /// <param name="cell"></param> public 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); } } /// <summary> /// 創建單元格樣式並設置數據格式化規則 /// </summary> /// <param name="cell"></param> /// <param name="format"></param> public static ICellStyle GetCellStyleWithDataFormat(IWorkbook workbook, string format) { var 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; } /// <summary> /// 依據值類型為單元格設置值 /// </summary> /// <param name="cell"></param> /// <param name="value"></param> /// <param name="colType"></param> public static void SetCellValue(ICell cell, string value, Type colType, IDictionary<int, ICellStyle> colStyles) { string dataFormatStr = null; switch (colType.ToString()) { case "System.String": //字元串類型 cell.SetCellType(CellType.String); cell.SetCellValue(value); break; case "System.DateTime": //日期類型 DateTime dateV = new DateTime(); DateTime.TryParse(value, out dateV); cell.SetCellValue(dateV); dataFormatStr = "yyyy/mm/dd hh:mm:ss"; break; case "System.Boolean": //布爾型 bool boolV = false; bool.TryParse(value, out boolV); cell.SetCellType(CellType.Boolean); cell.SetCellValue(boolV); break; case "System.Int16": //整型 case "System.Int32": case "System.Int64": case "System.Byte": int intV = 0; int.TryParse(value, out intV); cell.SetCellType(CellType.Numeric); cell.SetCellValue(intV); dataFormatStr = "0"; break; case "System.Decimal": //浮點型 case "System.Double": double doubV = 0; double.TryParse(value, out doubV); cell.SetCellType(CellType.Numeric); cell.SetCellValue(doubV); dataFormatStr = "0.00"; break; case "System.DBNull": //空值處理 cell.SetCellType(CellType.Blank); cell.SetCellValue(""); 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]; } /// <summary> /// 從工作表中生成DataTable /// </summary> /// <param name="sheet"></param> /// <param name="headerRowIndex"></param> /// <returns></returns> public static DataTable GetDataTableFromSheet(ISheet sheet, int headerRowIndex) { DataTable table = new DataTable(); IRow headerRow = sheet.GetRow(headerRowIndex); int cellCount = headerRow.LastCellNum; for (int i = headerRow.FirstCellNum; 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 && !string.IsNullOrEmpty(row.GetCell(0).ToString())) { DataRow dataRow = table.NewRow(); for (int j = row.FirstCellNum; j < cellCount; j++) { dataRow[j] = row.GetCell(j).ToString(); } table.Rows.Add(dataRow); } } return table; } /// <summary> /// 獲取模板文件對應的模板格式配置XML文件路徑(當不存在或較舊時,將會重新生成) /// </summary> /// <param name="templatePath"></param> /// <param name="newGenerate"></param> /// <returns></returns> public static string GetTemplateConfigFilePath(string templatePath, bool newGenerate = false) { string templateConfigFilePath = Path.ChangeExtension(templatePath, ".xml"); if (newGenerate || !File.Exists(templateConfigFilePath) || File.GetLastWriteTime(templatePath) > File.GetLastWriteTime(templateConfigFilePath)) { WorkbookParameterContainer workbookParameter = ParseTemplate.Parse(templatePath); workbookParameter.Save(templateConfigFilePath); } return templateConfigFilePath; } } }
第六個新增功能,支持模板中包含多個工作薄導出(目前這個方法還沒有模擬測試,所以無法保證其一定有效,大家可以試試),該方法定義如下:
/// <summary> /// 由SheetFormatterContainer集合導出基於EXCEL模板(多工作薄)的文件 /// </summary> /// <param name="templatePath"></param> /// <param name="formatterContainers"></param> /// <param name="filePath"></param> /// <returns></returns> public static string ToExcelWithTemplate(string templatePath,IDictionary<string,SheetFormatterContainer<dynamic>> formatterContainers, string filePath = null) { if (!File.Exists(templatePath)) { throw new FileNotFoundException(templatePath + "文件不存在!"); } if (string.IsNullOrEmpty(filePath)) { filePath = Common.GetSaveFilePath(); } if (string.IsNullOrEmpty(filePath)) return null; string templateConfigFilePath = Common.GetTemplateConfigFilePath(templatePath, false); var workbookParameterContainer = new WorkbookParameterContainer(); workbookParameterContainer.Load(templateConfigFilePath); List<SheetFormatter> sheetFormatterList = new List<SheetFormatter>(); foreach (var item in formatterContainers) { SheetParameterContainer sheetParameterContainer = workbookParameterContainer[item.Key]; sheetFormatterList.Add(new SheetFormatter(item.Key, item.Value.GetFormatters(sheetParameterContainer))); } ExportHelper.ExportToLocal(templatePath, filePath,sheetFormatterList.ToArray()); return filePath; }
該類庫源碼已分享到該路徑中:http://git.oschina.net/zuowj/ExcelUtility GIT Repository路徑:[email protected]:zuowj/ExcelUtility.git (會持續更新及修正BUG)