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 ...
一周排行
  • 前幾天發佈了 "抄抄《CSS 故障藝術》的動畫" 這篇文章,在這篇文章里介紹瞭如何使用Win2D繪製文字然後配合BlendEffect製作故障藝術的動畫。本來打算就這樣收手不玩這個動畫了,但後來又發現性能不符合理想。明明只是做做Resize動畫和用BlendEffect混合,為什麼性能會這麼差呢? ...
  • 控制條控制項: progressBar 不能按照你程式的進程自動變化,需認為計算,調整變化量 private void progressBar1_Click(object sender, EventArgs e) { this.progressBar1.Maximum = 100;//設置進度條最大長 ...
  • 首先創建一個asp.net core web應用程式 第二步 目前官方預置了7種模板項目供我們選擇。從中我們可以看出,既有我們熟悉的MVC、WebAPI,又新添加了Razor Page,以及結合比較流行的Angular、React前端框架的模板項目。 空項目模板 Program.cs using S ...
  • 對閉包的理解 1.對於成員變數和局部變數:成員變數就是方法外部,類的內部定義的變數;局部變數就是方法或語句塊內部定義的變數。局部變數必須初始化。 形式參數是局部變數,局部變數的數據存在於棧記憶體中。棧記憶體中的局部變數隨著方法的消失而消失。成員變數存儲在堆中的對象裡面,由垃圾回收器負責回收。 成員變數它 ...
  • Xamarin.Forms讀取並展示Android和iOS通訊錄 TerminalMACS客戶端 本文同步更新地址: https://dotnet9.com/11520.html https://terminalmacs.com/861.html 閱讀導航: 一、功能說明 二、代碼實現 三、源碼獲取 ...
  • 做下對文件複製操作相關的筆記: /// <summary> /// 文件幫助類 /// </summary> public class FileHelper { /// <summary> /// 複製一個目錄下所有文件到一個新目錄下 /// </summary> /// <param name=" ...
  • 前言 有一個東西叫做鴨子類型,所謂鴨子類型就是,只要一個東西表現得像鴨子那麼就能推出這玩意就是鴨子。 C 裡面其實也暗藏了很多類似鴨子類型的東西,但是很多開發者並不知道,因此也就沒法好好利用這些東西,那麼今天我細數一下這些藏在編譯器中的細節。 不是只有 和 才能 在 C 中編寫非同步代碼的時候,我們經 ...
  • [toc] 1.應用背景 底端設備有大量網路報文(位元組數組):心跳報文,數據採集報文,告警報文上報。需要有對應的報文結構去解析這些位元組流數據。 2.結構體解析 由此,我第一點就想到了用結構體去解析。原因有以下兩點: 2.1.結構體存在棧中 類屬於引用類型,存在堆中;結構體屬於值類型,存在棧中,在一個 ...
  • 《深入淺出 C#》 (第3版) [作者] (美) Andrew Stellman (美) Jennifer Greene[譯者] (中) 徐陽 丁小峰 等譯[出版] 中國電力出版社[版次] 2016年08月 第1版[印次] 2018年04月 第4次 印刷[定價] 148.00元 【引子】 要學習編程 ...
  • 記錄使用對象初始值設定項初始化對象。 using System; using System.Collections.Generic; namespace ConsoleApp2 { class Program { static void Main(string[] args) { // 使用構造函數 ...
x