分享我基於NPOI+ExcelReport實現的導入與導出EXCEL類庫:ExcelUtility (續篇)

来源:http://www.cnblogs.com/zuowj/archive/2016/01/15/5133935.html
-Advertisement-
Play Games

上周六我發表的文章《分享我基於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)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 因為框架使用了字體文件來顯示矢量的圖標,為了能在IIS上正常顯示圖標,可以通過增加iis的MIME-TYPE來支持圖標字體文件:增加以下兩種文件類型即可:.woff application/x-woff.svg image/svg+xml最後還可以查看樣式是否有發佈進去,如果沒有直接把樣式考進去覆蓋...
  • 結果顯示:marc顯示:卡片顯示:程式一個類: public class MARC { #region 界面上要顯示的元素 public string ztm = "";//正題名 public string ftm = "";//副題名 ...
  • 來源:http://zxlovenet.cnblogs.com 偽彩色處理是指將灰度圖像轉換成彩色圖象。因為人眼對於彩色的分辨能力遠高於對灰度圖像的分辨能力,所以將灰度圖像轉換成彩色可以提高人眼對圖像細節的辨別能力。偽彩色並不能真實的反映圖像像的彩色情況。 效果圖: 強度分層法和灰度級-彩色...
  • 1. 日期控制項的使用(如下圖所示,點擊空白處彈出日曆) (1)首先下載AjaxControlToolkit.dll(2)文件起始處添加下麵的語句(3)再添加下麵的語句2. 樣例
  • //可以上傳圖片,txt文檔。doc,wps,還有音頻文件,視屏文件等,功能強大啊!//前臺代碼片,設置上傳圖片的界面 //後臺代碼 ,實現圖片從客戶...
  • 原文鏈接:http://docs.autofac.org/en/latest/getting-started/index.html在程式中使用Autofac的基本模式是:用控制反轉(IoC)的思想組織程式。添加對 Autofac 的引用。程式啟動階段創建 ContainerBuilder。註冊組件。...
  • 以前寫過一個wp8的工程,說實話那會的代碼很麻煩,寫起來費勁,另外還沒多少人下載,不過到windows 10 開始微軟出了UWP架構以後一切都像以前的winform wpf一樣好轉起來,新建一個工程以後模板很簡潔。現在就開始介紹一下基本控制項的使用,為新手寫程式提供一個例子。7天酒店沒有官方客戶端.....
  • 貨位是ERP系統總的倉庫管理中必不可少的,倉庫是有貨架組成,貨架上的每個格子就是一個貨位,所有貨位上的商品的庫存總和就是倉庫商品的庫存。倉庫的貨位主要分為貨架和托盤,貨架就是倉庫的固定貨位,托盤就是移動貨位,或者稱為移動托盤。倉庫的貨位類型可以分為存貨位,揀貨貨位,移動貨位三種大的類型。按正殘品.....
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...