C#_Excel數據讀取與寫入_自定義解析封裝類_支持設置標題行位置&使用excel表達式收集數據&單元格映射&標題映射&模板文件的參數數據替換

来源:https://www.cnblogs.com/lxhbky/archive/2020/01/20/12219174.html

本篇博客園是被任務所逼,而已有的使用nopi技術的文檔技術經驗又不支持我需要的應對各種複雜需求的苛刻要求,只能自己造輪子封裝了,由於需要應對很多總類型的數據採集需求,因此有了本篇博客的代碼封裝,下麵一點點介紹吧: 收集excel你有沒有遇到過一下痛點: 1-需要收集指定行標題位置的數據,我的標題行不 ...


  本篇博客園是被任務所逼,而已有的使用nopi技術的文檔技術經驗又不支持我需要的應對各種複雜需求的苛刻要求,只能自己造輪子封裝了,由於需要應對很多總類型的數據採集需求,因此有了本篇博客的代碼封裝,下麵一點點介紹吧:

 

  收集excel你有沒有遇到過一下痛點:

  1-需要收集指定行標題位置的數據,我的標題行不一定在第一行。  這個和我的csv的文檔需求是一致的

  2-需要採集指定單元格位置的數據生成一個對象,而不是一個列表。   這裡我的方案是制定一個單元格映射類解決問題。  單元格映射類,支持表達式數據採集(我可能需要一個單元格的數據+另一個單元格的數據作為一個屬性等等)

  3-應對不規範標題無法轉出字元串進行映射時,能不能通過制定標題的列下標建立對應關係,進行列表數據採集呢?   本博客同時支持標題字元串數據採集和標題下標數據採集,這個就牛逼了。

  4-存儲含有表達式的數據,這個並不是難點,由於很重要,就在這裡列一下

  5-應對Excel模板文件的數據指定位置填入數據,該位置可能會變動的解決方案。本文為了應對該情況,藉助了單元格映射關係,添加了模板參數名的屬性處理,可以應對模板文件調整時的位置變動問題。

  6-一個能同時處理excel新老版本(.xls和.xlsx),一個指定excel位置保存數據,保存含有表達式的數據,一個可以將多個不同的數據組合存放到一個excel中的需求都可以滿足。   

 

  痛點大概就是上面這些了,下麵寫主要代碼吧,供大家參考,不過封裝的類方法有點多:

  

  本文藉助了NPOI程式包做了業務封裝:  

 

  1-主要封裝類-ExcelHelper:

  該類包含很多輔助功能:比如自動幫助尋找含有指定標題名所在的位置、表達式元素A1,B2對應單元格位置的解析等等:

using NLog;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;

namespace PPPayReportTools.Excel
{
    /// <summary>
    /// EXCEL幫助類
    /// </summary>
    /// <typeparam name="T">泛型類</typeparam>
    /// <typeparam name="TCollection">泛型類集合</typeparam>
    public class ExcelHelper
    {
        private static Logger _Logger = LogManager.GetCurrentClassLogger();

        #region 創建工作表

        /// <summary>
        /// 將列表數據生成工作表
        /// </summary>
        /// <param name="tList">要導出的數據集</param>
        /// <param name="fieldNameAndShowNameDic">鍵值對集合(鍵:欄位名,值:顯示名稱)</param>
        /// <param name="workbook">更新時添加:要更新的工作表</param>
        /// <param name="sheetName">指定要創建的sheet名稱時添加</param>
        /// <param name="excelFileDescription">讀取或插入定製需求時添加</param>
        /// <returns></returns>
        public static IWorkbook CreateOrUpdateWorkbook<T>(List<T> tList, Dictionary<string, string> fieldNameAndShowNameDic, IWorkbook workbook = null, string sheetName = "sheet1", ExcelFileDescription excelFileDescription = null) where T : new()
        {
            List<ExcelTitleFieldMapper> titleMapperList = ExcelTitleFieldMapper.GetModelFieldMapper<T>(fieldNameAndShowNameDic);

            workbook = ExcelHelper.CreateOrUpdateWorkbook<T>(tList, titleMapperList, workbook, sheetName, excelFileDescription);
            return workbook;
        }
        /// <summary>
        /// 將列表數據生成工作表(T的屬性需要添加:屬性名列名映射關係)
        /// </summary>
        /// <param name="tList">要導出的數據集</param>
        /// <param name="workbook">更新時添加:要更新的工作表</param>
        /// <param name="sheetName">指定要創建的sheet名稱時添加</param>
        /// <param name="excelFileDescription">讀取或插入定製需求時添加</param>
        /// <returns></returns>
        public static IWorkbook CreateOrUpdateWorkbook<T>(List<T> tList, IWorkbook workbook = null, string sheetName = "sheet1", ExcelFileDescription excelFileDescription = null) where T : new()
        {
            List<ExcelTitleFieldMapper> titleMapperList = ExcelTitleFieldMapper.GetModelFieldMapper<T>();

            workbook = ExcelHelper.CreateOrUpdateWorkbook<T>(tList, titleMapperList, workbook, sheetName, excelFileDescription);
            return workbook;
        }

        private static IWorkbook CreateOrUpdateWorkbook<T>(List<T> tList, List<ExcelTitleFieldMapper> titleMapperList, IWorkbook workbook, string sheetName, ExcelFileDescription excelFileDescription = null)
        {
            //xls文件格式屬於老版本文件,一個sheet最多保存65536行;而xlsx屬於新版文件類型;
            //Excel 07 - 2003一個工作表最多可有65536行,行用數字1—65536表示; 最多可有256列,列用英文字母A—Z,AA—AZ,BA—BZ,……,IA—IV表示;一個工作簿中最多含有255個工作表,預設情況下是三個工作表;
            //Excel 2007及以後版本,一個工作表最多可有1048576行,16384列;
            if (workbook == null)
            {
                workbook = new XSSFWorkbook();
                //workbook = new HSSFWorkbook();
            }
            ISheet worksheet = null;
            if (workbook.GetSheetIndex(sheetName) >= 0)
            {
                worksheet = workbook.GetSheet(sheetName);
            }
            else
            {
                worksheet = workbook.CreateSheet(sheetName);
            }

            IRow row1 = null;
            ICell cell = null;

            int defaultBeginTitleIndex = 0;
            if (excelFileDescription != null)
            {
                defaultBeginTitleIndex = excelFileDescription.TitleRowIndex;
            }

            PropertyInfo propertyInfo = null;
            T t = default(T);

            int tCount = tList.Count;
            int currentRowIndex = 0;
            int dataIndex = 0;
            do
            {
                row1 = worksheet.GetRow(currentRowIndex);
                if (row1 == null)
                {
                    row1 = worksheet.CreateRow(currentRowIndex);
                }

                if (currentRowIndex >= defaultBeginTitleIndex)
                {
                    //到達標題行
                    if (currentRowIndex == defaultBeginTitleIndex)
                    {
                        int cellIndex = 0;
                        foreach (var titleMapper in titleMapperList)
                        {
                            cell = row1.GetCell(cellIndex);

                            if (cell == null)
                            {
                                cell = row1.CreateCell(cellIndex);
                            }
                            ExcelHelper.SetCellValue(cell, titleMapper.ExcelTitle, outputFormat: null);
                            cellIndex++;
                        }
                    }
                    //到達內容行
                    else
                    {
                        dataIndex = currentRowIndex - defaultBeginTitleIndex - 1;
                        if (dataIndex <= tCount - 1)
                        {
                            t = tList[dataIndex];

                            int cellIndex = 0;
                            foreach (var titleMapper in titleMapperList)
                            {
                                propertyInfo = titleMapper.PropertyInfo;

                                cell = row1.GetCell(cellIndex);
                                if (cell == null)
                                {
                                    cell = row1.CreateCell(cellIndex);
                                }

                                ExcelHelper.SetCellValue<T>(cell, t, titleMapper);

                                cellIndex++;
                            }

                            //重要:設置行寬度自適應(大批量添加數據時,該行代碼需要註釋,否則會極大減緩Excel添加行的速度!)
                            //worksheet.AutoSizeColumn(i, true);
                        }
                    }
                }

                currentRowIndex++;

            } while (dataIndex < tCount - 1);

            //設置表達式重算(如果不添加該代碼,表達式更新不出結果值)
            worksheet.ForceFormulaRecalculation = true;

            return workbook;
        }

        /// <summary>
        /// 將單元格數據列表生成工作表
        /// </summary>
        /// <param name="commonCellList">所有的單元格數據列表</param>
        /// <param name="workbook">更新時添加:要更新的工作表</param>
        /// <param name="sheetName">指定要創建的sheet名稱時添加</param>
        /// <returns></returns>
        public static IWorkbook CreateOrUpdateWorkbook(CommonCellModelColl commonCellList, IWorkbook workbook = null, string sheetName = "sheet1")
        {
            //xls文件格式屬於老版本文件,一個sheet最多保存65536行;而xlsx屬於新版文件類型;
            //Excel 07 - 2003一個工作表最多可有65536行,行用數字1—65536表示; 最多可有256列,列用英文字母A—Z,AA—AZ,BA—BZ,……,IA—IV表示;一個工作簿中最多含有255個工作表,預設情況下是三個工作表;
            //Excel 2007及以後版本,一個工作表最多可有1048576行,16384列;
            if (workbook == null)
            {
                workbook = new XSSFWorkbook();
                //workbook = new HSSFWorkbook();
            }
            ISheet worksheet = null;
            if (workbook.GetSheetIndex(sheetName) >= 0)
            {
                worksheet = workbook.GetSheet(sheetName);
            }
            else
            {
                worksheet = workbook.CreateSheet(sheetName);
            }

            //設置首列顯示
            IRow row1 = null;
            int rowIndex = 0;
            int columnIndex = 0;
            int maxColumnIndex = 0;
            Dictionary<int, CommonCellModel> rowColumnIndexCellDIC = null;
            ICell cell = null;
            object cellValue = null;

            do
            {
                rowColumnIndexCellDIC = commonCellList.GetRawCellList(rowIndex).ToDictionary(m => m.ColumnIndex);
                maxColumnIndex = rowColumnIndexCellDIC.Count > 0 ? rowColumnIndexCellDIC.Keys.Max() : 0;

                if (rowColumnIndexCellDIC != null && rowColumnIndexCellDIC.Count > 0)
                {
                    row1 = worksheet.GetRow(rowIndex);
                    if (row1 == null)
                    {
                        row1 = worksheet.CreateRow(rowIndex);
                    }
                    columnIndex = 0;
                    do
                    {
                        cell = row1.GetCell(columnIndex);
                        if (cell == null)
                        {
                            cell = row1.CreateCell(columnIndex);
                        }

                        if (rowColumnIndexCellDIC.ContainsKey(columnIndex))
                        {
                            cellValue = rowColumnIndexCellDIC[columnIndex].CellValue;

                            ExcelHelper.SetCellValue(cell, cellValue, outputFormat: null, rowColumnIndexCellDIC[columnIndex].IsCellFormula);
                        }
                        columnIndex++;
                    } while (columnIndex <= maxColumnIndex);
                }
                rowIndex++;
            } while (rowColumnIndexCellDIC != null && rowColumnIndexCellDIC.Count > 0);

            //設置表達式重算(如果不添加該代碼,表達式更新不出結果值)
            worksheet.ForceFormulaRecalculation = true;

            return workbook;
        }

        /// <summary>
        /// 更新模板文件數據:將使用單元格映射的數據T存入模板文件中
        /// </summary>
        /// <param name="filePath">所有的單元格數據列表</param>
        /// <param name="t">添加了單元格參數映射的數據對象</param>
        /// <returns></returns>
        public static IWorkbook CreateOrUpdateWorkbook<T>(string filePath, T t)
        {
            //該方法預設替換模板數據在首個sheet里

            IWorkbook workbook = null;
            CommonCellModelColl commonCellColl = ExcelHelper._ReadCellList(filePath, out workbook);

            ISheet worksheet = workbook.GetSheetAt(0);

            //獲取t的單元格映射列表
            Dictionary<string, ExcelCellFieldMapper> tParamMapperDic = ExcelCellFieldMapper.GetModelFieldMapper<T>().ToDictionary(m => m.CellParamName);

            var rows = worksheet.GetRowEnumerator();
            IRow row;
            ICell cell;
            string cellValue;
            ExcelCellFieldMapper cellMapper;
            while (rows.MoveNext())
            {
                row = (XSSFRow)rows.Current;
                int cellCount = row.Cells.Count;

                for (int i = 0; i < cellCount; i++)
                {
                    cell = row.Cells[i];
                    cellValue = cell.ToString();
                    if (tParamMapperDic.ContainsKey(cellValue))
                    {
                        cellMapper = tParamMapperDic[cellValue];
                        ExcelHelper.SetCellValue<T>(cell, t, cellMapper);
                    }
                }

            }

            if (tParamMapperDic.Count > 0)
            {
                //迴圈所有單元格數據替換指定變數數據
                foreach (var cellItem in commonCellColl)
                {
                    cellValue = cellItem.CellValue.ToString();

                    if (tParamMapperDic.ContainsKey(cellValue))
                    {
                        cellItem.CellValue = tParamMapperDic[cellValue].PropertyInfo.GetValue(t);
                    }
                }
            }

            //設置表達式重算(如果不添加該代碼,表達式更新不出結果值)
            worksheet.ForceFormulaRecalculation = true;

            return workbook;
        }

        #endregion

        #region 保存工作表到文件

        /// <summary>
        /// 保存Workbook數據為文件
        /// </summary>
        /// <param name="workbook"></param>
        /// <param name="fileDirectoryPath"></param>
        /// <param name="fileName"></param>
        public static void SaveWorkbookToFile(IWorkbook workbook, string filePath)
        {
            //xls文件格式屬於老版本文件,一個sheet最多保存65536行;而xlsx屬於新版文件類型;
            //Excel 07 - 2003一個工作表最多可有65536行,行用數字1—65536表示; 最多可有256列,列用英文字母A—Z,AA—AZ,BA—BZ,……,IA—IV表示;一個工作簿中最多含有255個工作表,預設情況下是三個工作表;
            //Excel 2007及以後版本,一個工作表最多可有1048576行,16384列;

            MemoryStream ms = new MemoryStream();
            //這句代碼非常重要,如果不加,會報:打開的EXCEL格式與擴展名指定的格式不一致
            ms.Seek(0, SeekOrigin.Begin);
            workbook.Write(ms);
            byte[] myByteArray = ms.GetBuffer();

            string fileDirectoryPath = filePath.Split('\\')[0];
            if (!Directory.Exists(fileDirectoryPath))
            {
                Directory.CreateDirectory(fileDirectoryPath);
            }
            string fileName = filePath.Replace(fileDirectoryPath, "");

            if (File.Exists(filePath))
            {
                File.Delete(filePath);
            }
            File.WriteAllBytes(filePath, myByteArray);
        }

        #endregion

        #region 讀取Excel數據

        /// <summary>
        /// 讀取Excel數據1_手動提供屬性信息和標題對應關係
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="filePath"></param>
        /// <param name="fieldNameAndShowNameDic"></param>
        /// <param name="excelFileDescription"></param>
        /// <returns></returns>
        public static List<T> ReadTitleDataList<T>(string filePath, Dictionary<string, string> fieldNameAndShowNameDic, ExcelFileDescription excelFileDescription) where T : new()
        {
            //標題屬性字典列表
            List<ExcelTitleFieldMapper> titleMapperList = ExcelTitleFieldMapper.GetModelFieldMapper<T>(fieldNameAndShowNameDic);

            List<T> tList = ExcelHelper._GetTList<T>(filePath, titleMapperList, excelFileDescription);
            return tList ?? new List<T>(0);
        }

        /// <summary>
        /// 讀取Excel數據2_使用Excel標記特性和文件描述自動創建關係
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="excelFileDescription"></param>
        /// <returns></returns>
        public static List<T> ReadTitleDataList<T>(string filePath, ExcelFileDescription excelFileDescription) where T : new()
        {
            //標題屬性字典列表
            List<ExcelTitleFieldMapper> titleMapperList = ExcelTitleFieldMapper.GetModelFieldMapper<T>();

            List<T> tList = ExcelHelper._GetTList<T>(filePath, titleMapperList, excelFileDescription);
            return tList ?? new List<T>(0);
        }

        private static List<T> _GetTList<T>(string filePath, List<ExcelTitleFieldMapper> titleMapperList, ExcelFileDescription excelFileDescription) where T : new()
        {
            List<T> tList = new List<T>(500 * 10000);
            T t = default(T);

            using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                IWorkbook workbook = null;
                IFormulaEvaluator formulaEvaluator = null;

                try
                {
                    workbook = new XSSFWorkbook(fileStream);
                    formulaEvaluator = new XSSFFormulaEvaluator(workbook);
                }
                catch (Exception)
                {
                    workbook = new HSSFWorkbook(fileStream);
                    formulaEvaluator = new HSSFFormulaEvaluator(workbook);
                }

                int sheetCount = workbook.NumberOfSheets;

                int currentSheetIndex = 0;
                int currentSheetRowTitleIndex = -1;
                do
                {
                    var sheet = workbook.GetSheetAt(currentSheetIndex);

                    //標題下標屬性字典
                    Dictionary<int, ExcelTitleFieldMapper> sheetTitleIndexPropertyDic = new Dictionary<int, ExcelTitleFieldMapper>(0);

                    //如果沒有設置標題行,則通過自動查找方法獲取
                    if (excelFileDescription.TitleRowIndex < 0)
                    {
                        string[] titleArray = titleMapperList.Select(m => m.ExcelTitle).ToArray();
                        currentSheetRowTitleIndex = ExcelHelper.GetSheetTitleIndex(sheet, titleArray);
                    }
                    else
                    {
                        currentSheetRowTitleIndex = excelFileDescription.TitleRowIndex;
                    }

                    var rows = sheet.GetRowEnumerator();

                    bool isHaveTitleIndex = false;
                    //含有Excel行下標
                    if (titleMapperList.Count > 0 && titleMapperList[0].ExcelTitleIndex >= 0)
                    {
                        isHaveTitleIndex = true;

                        foreach (var titleMapper in titleMapperList)
                        {
                            sheetTitleIndexPropertyDic.Add(titleMapper.ExcelTitleIndex, titleMapper);
                        }
                    }

                    PropertyInfo propertyInfo = null;
                    int currentRowIndex = 0;

                    while (rows.MoveNext())
                    {
                        IRow row = (IRow)rows.Current;
                        currentRowIndex = row.RowNum;

                        //到達標題行
                        if (isHaveTitleIndex == false && currentRowIndex == currentSheetRowTitleIndex)
                        {
                            ICell cell = null;
                            string cellValue = null;
                            Dictionary<string, ExcelTitleFieldMapper> titleMapperDic = titleMapperList.ToDictionary(m => m.ExcelTitle);
                            for (int i = 0; i < row.Cells.Count; i++)
                            {
                                cell = row.Cells[i];
                                cellValue = cell.StringCellValue;
                                if (titleMapperDic.ContainsKey(cellValue))
                                {
                                    sheetTitleIndexPropertyDic.Add(i, titleMapperDic[cellValue]);
                                }
                            }
                        }

                        //到達內容行
                        if (currentRowIndex > currentSheetRowTitleIndex)
                        {
                            t = new T();
                            ExcelTitleFieldMapper excelTitleFieldMapper = null;
                            foreach (var titleIndexItem in sheetTitleIndexPropertyDic)
                            {
                                ICell cell = row.GetCell(titleIndexItem.Key);

                                excelTitleFieldMapper = titleIndexItem.Value;

                                //沒有數據的單元格預設為null
                                string cellValue = cell?.ToString() ?? "";
                                propertyInfo = excelTitleFieldMapper.PropertyInfo;
                                try
                                {
                                    if (excelTitleFieldMapper.IsCheckContentEmpty)
                                    {
                                        if (string.IsNullOrEmpty(cellValue))
                                        {
                                            t = default(T);
                                            break;
                                        }
                                    }

                                    if (excelTitleFieldMapper.IsCoordinateExpress || cell.CellType == CellType.Formula)
                                    {
                                        //讀取含有表達式的單元格值
                                        cellValue = formulaEvaluator.Evaluate(cell).StringValue;
                                        propertyInfo.SetValue(t, Convert.ChangeType(cellValue, propertyInfo.PropertyType));
                                    }
                                    else if (propertyInfo.PropertyType.IsEnum)
                                    {
                                        object enumObj = propertyInfo.PropertyType.InvokeMember(cellValue, BindingFlags.GetField, null, null, null);
                                        propertyInfo.SetValue(t, Convert.ChangeType(enumObj, propertyInfo.PropertyType));
                                    }
                                    else
                                    {
                                        propertyInfo.SetValue(t, Convert.ChangeType(cellValue, propertyInfo.PropertyType));
                                    }
                                }
                                catch (Exception e)
                                {
                                    ExcelHelper._Logger.Debug($"文件_{filePath}讀取{currentRowIndex + 1}行內容失敗!");
                                    t = default(T);
                                    break;
                                }
                            }
                            if (t != null)
                            {
                                tList.Add(t);
                            }
                        }
                    }

                    currentSheetIndex++;

                } while (currentSheetIndex + 1 <= sheetCount);
            }
            return tList ?? new List<T>(0);
        }

        /// <summary>
        /// 讀取文件的所有單元格數據
        /// </summary>
        /// <param name="filePath">文件路徑</param>
        /// <returns></returns>
        public static CommonCellModelColl ReadCellList(string filePath)
        {
            IWorkbook workbook = null;

            CommonCellModelColl commonCellColl = ExcelHelper._ReadCellList(filePath, out workbook);
            return commonCellColl;
        }

        /// <summary>
        /// 讀取文件的所有單元格數據
        /// </summary>
        /// <param name="filePath">文件路徑</param>
        /// <returns></returns>
        public static CommonCellModelColl ReadCellList(string filePath, out IWorkbook workbook)
        {
            CommonCellModelColl commonCellColl = ExcelHelper._ReadCellList(filePath, out workbook);
            return commonCellColl;
        }

        private static CommonCellModelColl _ReadCellList(string filePath, out IWorkbook workbook)
        {
            CommonCellModelColl commonCellColl = new CommonCellModelColl(10000);
            CommonCellModel cellModel = null;
            workbook = null;

            using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                try
                {
                    workbook = new XSSFWorkbook(fileStream);
                }
                catch (Exception)
                {
                    workbook = new HSSFWorkbook(fileStream);
                }
                var sheet = workbook.GetSheetAt(0);

                var rows = sheet.GetRowEnumerator();
                List<ICell> cellList = null;
                ICell cell = null;

                //從第1行數據開始獲取
                while (rows.MoveNext())
                {
                    IRow row = (IRow)rows.Current;

                    cellList = row.Cells;
                    int cellCount = cellList.Count;

                    for (int i = 0; i < cellCount; i++)
                    {
                        cell = cellList[i];
                        cellModel = new CommonCellModel
                        {
                            RowIndex = row.RowNum,
                            ColumnIndex = i,
                            CellValue = cell.ToString(),
                            IsCellFormula = cell.CellType == CellType.Formula ? true : false
                        };
                        commonCellColl.Add(cellModel);
                    }
                }
            }
            return commonCellColl;
        }

        /// <summary>
        /// 獲取文件單元格數據對象
        /// </summary>
        /// <typeparam name="T">T的屬性必須標記了ExcelCellAttribute</typeparam>
        /// <param name="filePath">文建路徑</param>
        /// <returns></returns>
        public static T ReadCellData<T>(string filePath) where T : new()
        {
            T t = new T();

            ExcelHelper._Logger.Info($"開始讀取{filePath}的數據...");

            CommonCellModelColl commonCellColl = ExcelHelper.ReadCellList(filePath);

            Dictionary<PropertyInfo, ExcelCellFieldMapper> propertyMapperDic = ExcelCellFieldMapper.GetModelFieldMapper<T>().ToDictionary(m => m.PropertyInfo);
            string cellExpress = null;
            string pValue = null;
            PropertyInfo propertyInfo = null;
            foreach (var item in propertyMapperDic)
            {
                cellExpress = item.Value.CellCoordinateExpress;
                propertyInfo = item.Key;
                pValue = ExcelHelper.GetVByExpress(cellExpress, propertyInfo, commonCellColl).ToString();
                if (!string.IsNullOrEmpty(pValue))
                {
                    propertyInfo.SetValue(t, Convert.ChangeType(pValue, propertyInfo.PropertyType));
                }
            }
            return t;
        }

        /// <summary>
        /// 獲取文件首個sheet的標題位置
        /// </summary>
        /// <typeparam name="T">T必須做了標題映射</typeparam>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public static int FileFirstSheetTitleIndex<T>(string filePath)
        {
            int titleIndex = 0;

            if (File.Exists(filePath))
            {
                using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    IWorkbook workbook = null;
                    try
                    {
                        workbook = new XSSFWorkbook(fileStream);
                    }
                    catch (Exception)
                    {
                        workbook = new HSSFWorkbook(fileStream);
                    }

                    string[] titleArray = ExcelTitleFieldMapper.GetModelFieldMapper<T>().Select(m => m.ExcelTitle).ToArray();

                    ISheet sheet = workbook.GetSheetAt(0);
                    titleIndex = ExcelHelper.GetSheetTitleIndex(sheet, titleArray);
                }
            }

            return titleIndex;
        }

        /// <

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

更多相關文章
  • 發現一個驗證字元串是否包含中文滴時候,一個比正則更好使滴方法,而且是golang 自帶滴驗證。 不需要自己寫正則驗證,代碼如下: package main import ( "fmt" "regexp" "unicode" ) func main() { s1 := "我是中國人hello word ...
  • 基本構架 所有的C程式都有一個 main 函數.其後包含在大括弧中的是 main 函數的內容. main函數是程式的入口,程式運行後,先進入 main 函數,然後一次執行 main 函數體中的語句. 這是一個例子: 簡單來說,寫在 main 中的內容會在程式啟動時執行.main 函數中的內容是程式的 ...
  • 功能描述:做的是物聯網的項目,Excel導入實現的功能是將Excel中的數據批量的導入AEP系統,再導入我們系統中。目前已經完成該功能,前端還會添加進度條優化。Excel模板: 前端向後端傳遞的參數: 前端代碼: <Upload name="wlwDeviceFile" ref="upload" : ...
  • 導入下列依賴包,搞定 sudo apt-get install python3 python-dev python3-dev build-essential libssl-dev libffi-dev libxml2-dev libxslt1-dev zlib1g-dev python-pip 上訴 ...
  • 引言 昨日接了一個阿裡外包的電話面試,問了一些技術問題感覺到自己是真的菜,接觸Java開發已經也有一段時間,技術方面說來慚愧,一直以來只是局限於框架工具的用法,也沒有進行瞭解其實現的原理,更重要的是一直沒有歸納和總結,這次把這些問題記錄下來,相關的知識點也找了一些資料學習下。 問題 1. Count ...
  • 錯誤信息 錯誤原因 so文件損壞 或者ida換成32 解決辦法 重新獲得so文件,或者調整ida的位數 ...
  • 在JAVA中集合是一種比較基礎重要的數據結構,對集合的常用操作,不同集合直接的比較是非常重要的,這裡ConcurrentHashMap是一個線程安全並且效率非常高的集合,主要講解這裡如何去使用這個集合,和集合的效率比較 ...
  • 首先需要pip3 install wakeonlan 然後在電腦需要你的網卡支持網路喚醒電腦。 然後在主板BIOS開啟支持喚醒。 在系統網卡屬性里選上“允許電腦關閉此設備以節約電源”,“允許此設備喚醒電腦” 然後以下就是python代碼,非常簡單。from wakeonlan import s ...
一周排行
  • 1. 雲停車 (開篇)2. 雲停車 (硬體篇)3. 雲停車 (業務篇)4. 雲停車 (平臺篇)5. 雲停車 (源碼篇) 網址:http://42.194.142.223:8091/Home 賬戶:admin 密碼:[email protected] 在場記錄 出入記錄 月租車繳費記錄 臨時車繳費記錄 車場 ...
  • 1.RabbitMQ簡介 因為RabbitMQ是基於開源的AMQP協議來實現的,所以在瞭解MQ時候,首先我們來瞭解下AMQP協議。AMQP,即Advanced Message Queuing Protocol,一個提供統一消息服務的應用層標準高級消息隊列協議,是應用層協議的一個開放標準,為面向消息的 ...
  • 1.AMQP Messaging中的基本概念 Broker:接收和分發消息的應用,RabbitMQ Server就是Message Broker。Virtual Host:出於多租戶和安全因素設計的,把AMQP的基本組件劃分到一個虛擬的分組中,類似於網路中的Namespace概念。當多個不同的用戶使 ...
  • 在顯示或者隱藏視窗的時候,可以利用Windows API中的AnimateWindow函數實現一些特殊的效果。主要的動畫類型有四種:滾動、幻燈片、摺疊或展開和alpha混合漸變。 ##視窗動畫效果 首先定義動畫工具類,引入AnimateWindow函數。 public class WindowsEf ...
  • 泥水佬大佬的地址已經不能下載,所以分享下。 用法很簡單,輸入地址即可。 鏈接:https://pan.baidu.com/s/1OUeybjqY9uGWmxe_ywgwgQ 提取碼:nls9 ...
  • //前提需要 //需要一個 serialPort 工具 可在vs自帶的工具欄中獲得 //源代碼加串口工具地址: //鏈接:https://pan.baidu.com/s/1YbfvdXEmfsJX87D-Jxljyg 提取碼:d32x //記錄用戶打開的串口號 可改為泛型模式 string seri ...
  • 從業務視角還原問題、業務視角抽象問題、二次抽象發現技術問題,作為思考問題的三個還原點。 提煉單點問題解決能力、思考單點問題解決能力,複製、層層遞進思考問題,從深度和廣度出發, 深度以數據作指標,廣度以領域做方向。 腳踏實地的代碼量成長沒有捷徑。 ...
  • Java電子書分類 Java、Spring、SpringBoot、SpringCloud、mybatis、Tomcat、多線程、Git相關、Redis、設計模式、Nginx、Linux、演算法、資料庫、大數據、架構 電子書大概有30G左右 部分電子書截圖 領取方式 加我的微信(s2001sssss)免 ...
  • 一.node啟動js公鑰加密 //需要導入模塊npm install node-forge var arguments = process.argv.splice(2); // console.log('所傳遞的參數是:', arguments); var e = arguments[1]; var ...
  • LeetCode–最長公共首碼 博客說明 文章所涉及的資料來自互聯網整理和個人總結,意在於個人學習和經驗彙總,如有什麼地方侵權,請聯繫本人刪除,謝謝! 說明 leetcode題,14題 最長公共首碼 題目 編寫一個函數來查找字元串數組中的最長公共首碼。 如果不存在公共首碼,返回空字元串 ""。 示例 ...