C#_Excel數據讀取與寫入_自定義解析封裝類_支持設置標題行位置&使用excel表達式收集數據&單元格映射&標題映射&模板文件的參數數據替換(第二版-增加深度讀取和更新功能)

来源:https://www.cnblogs.com/lxhbky/archive/2020/04/13/12692407.html
-Advertisement-
Play Games

前言:新的的封裝類,增加了單元格映射深度更新和讀取的功能,預留了標題映射的深度更新介面待擴展。。。(以後有時間和精力再完善吧) 【深度更新】:我這裡定義的深度更新策略,指的是:假如我們需要讀取一組單元格的映射數據為一個對象,但是有不止一組這樣的單元格數據對象,且這些對象的單元格位置排列是有規律的! ...


  前言:新的的封裝類,增加了單元格映射深度更新和讀取的功能,預留了標題映射的深度更新介面待擴展。。。(以後有時間和精力再完善吧)

  【深度更新】:我這裡定義的深度更新策略,指的是:假如我們需要讀取一組單元格的映射數據為一個對象,但是有不止一組這樣的單元格數據對象,且這些對象的單元格位置排列是有規律的!

如:我要收集一個對象,在A1,A2,B1,B2的位置組成的一個數據對象,下一個對象位置在:  A5,C6,B5,B6的位置,同理。。。

  前面的文章介紹了使用單元格映射關係,我可以順利收集到其中一個對象,但是我不可能把所有的單元格都建立對象關聯起來,且數據又不符合標題行數據映射;那麼就提出了一個新的策略,我這裡叫:深度更新表達式讀取策略。

 

  下麵放置完整代碼,這版本做了深度更新的介面的抽象和封裝,類有點多:

 

  1-ExcelHelper  幫助類:

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


        public static IWorkbook GetExcelWorkbook(string filePath)
        {
            IWorkbook workbook = null;

            try
            {
                using (FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    try
                    {
                        workbook = new XSSFWorkbook(fileStream);
                    }
                    catch (Exception)
                    {
                        workbook = new HSSFWorkbook(fileStream);
                    }
                }
            }
            catch (Exception e)
            {
                throw new Exception($"文件:{filePath}被占用!", e);
            }
            return workbook;
        }

        public static ISheet GetExcelWorkbookSheet(IWorkbook workbook, int sheetIndex = 0)
        {
            ISheet sheet = null;

            if (workbook != null)
            {
                if (sheetIndex >= 0)
                {
                    sheet = workbook.GetSheetAt(sheetIndex);
                }
            }
            return sheet;
        }

        public static ISheet GetExcelWorkbookSheet(IWorkbook workbook, string sheetName = "sheet1")
        {
            ISheet sheet = null;

            if (workbook != null && !string.IsNullOrEmpty(sheetName))
            {
                sheet = workbook.GetSheet(sheetName);
                if (sheet == null)
                {
                    sheet = workbook.CreateSheet(sheetName);
                }
            }
            return sheet;
        }

        public static IRow GetOrCreateRow(ISheet sheet, int rowIndex)
        {
            IRow row = null;
            if (sheet != null)
            {
                row = sheet.GetRow(rowIndex);
                if (row == null)
                {
                    row = sheet.CreateRow(rowIndex);
                }
            }
            return row;
        }

        public static ICell GetOrCreateCell(ISheet sheet, int rowIndex, int columnIndex)
        {
            ICell cell = null;

            IRow row = ExcelHelper.GetOrCreateRow(sheet, rowIndex);
            if (row != null)
            {
                cell = row.GetCell(columnIndex);
                if (cell == null)
                {
                    cell = row.CreateCell(columnIndex);
                }
            }

            return cell;
        }

        /// <summary>
        /// 根據單元格表達式和單元格數據集獲取數據
        /// </summary>
        /// <param name="cellExpress">單元格表達式</param>
        /// <param name="workbook">excel工作文件</param>
        /// <param name="currentSheet">當前sheet</param>
        /// <returns></returns>
        public static object GetVByExpress(string cellExpress, IWorkbook workbook, ISheet currentSheet)
        {
            object value = null;

            //含有單元格表達式的取表達式值,沒有表達式的取單元格字元串
            if (!string.IsNullOrEmpty(cellExpress) && workbook != null && currentSheet != null)
            {
                IFormulaEvaluator formulaEvaluator = null;
                if (workbook is HSSFWorkbook)
                {
                    formulaEvaluator = new HSSFFormulaEvaluator(workbook);
                }
                else
                {
                    formulaEvaluator = new XSSFFormulaEvaluator(workbook);
                }

                //創建臨時行,單元格,執行表達式運算;
                IRow newRow = currentSheet.CreateRow(currentSheet.LastRowNum + 1);
                ICell cell = newRow.CreateCell(0);
                cell.SetCellFormula(cellExpress);
                cell = formulaEvaluator.EvaluateInCell(cell);
                value = cell.ToString();

                currentSheet.RemoveRow(newRow);
            }

            return value ?? "";

        }

        #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)
        {
            CellModelColl cellModelColl = new CellModelColl(0);

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

            //補全標題行映射數據的標題和下標位置映射關係
            ISheet sheet = ExcelHelper.GetExcelWorkbookSheet(workbook, sheetName: sheetName);
            IRow titleRow = null;
            if (sheet != null)
            {
                titleRow = sheet.GetRow(defaultBeginTitleIndex);
            }

            if (titleRow != null)
            {
                List<ICell> titleCellList = titleRow.Cells;
                foreach (var titleMapper in titleMapperList)
                {
                    if (titleMapper.ExcelTitleIndex < 0)
                    {
                        foreach (var cellItem in titleCellList)
                        {
                            if (cellItem.ToString().Equals(titleMapper.ExcelTitle, StringComparison.OrdinalIgnoreCase))
                            {
                                titleMapper.ExcelTitleIndex = cellItem.ColumnIndex;
                                break;
                            }
                        }
                    }
                    else if (string.IsNullOrEmpty(titleMapper.ExcelTitle))
                    {
                        ICell cell = titleRow.GetCell(titleMapper.ExcelTitleIndex);
                        if (cell != null)
                        {
                            titleMapper.ExcelTitle = cell.ToString();
                        }
                    }
                }
            }
            else
            {
                //如果是新建Sheet頁,則手動初始化下標關係
                for (int i = 0; i < titleMapperList.Count; i++)
                {
                    titleMapperList[i].ExcelTitleIndex = i;
                }
            }

            int currentRowIndex = defaultBeginTitleIndex;
            //添加標題單元格數據
            foreach (var titleMapper in titleMapperList)
            {
                cellModelColl.Add(new CellModel
                {
                    RowIndex = defaultBeginTitleIndex,
                    ColumnIndex = titleMapper.ExcelTitleIndex,
                    CellValue = titleMapper.ExcelTitle,
                    IsCellFormula = false
                });
            }
            currentRowIndex++;

            //將標題行數據轉出單元格數據
            foreach (var item in tList)
            {
                foreach (var titleMapper in titleMapperList)
                {
                    cellModelColl.Add(new CellModel
                    {
                        RowIndex = currentRowIndex,
                        ColumnIndex = titleMapper.ExcelTitleIndex,
                        CellValue = titleMapper.PropertyInfo.GetValue(item),
                        IsCellFormula = titleMapper.IsCoordinateExpress
                    });
                }
                currentRowIndex++;
            }

            workbook = ExcelHelper.CreateOrUpdateWorkbook(cellModelColl, workbook, sheetName);

            return workbook;
        }

        /// <summary>
        /// 將單元格數據列表生成工作表
        /// </summary>
        /// <param name="commonCellList">所有的單元格數據列表</param>
        /// <param name="workbook">更新時添加:要更新的工作表</param>
        /// <param name="sheetName">指定要創建的sheet名稱時添加</param>
        /// <returns></returns>
        public static IWorkbook CreateOrUpdateWorkbook(CellModelColl 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 = ExcelHelper.GetExcelWorkbookSheet(workbook, sheetName);

            if (worksheet != null && commonCellList != null && commonCellList.Count > 0)
            {
                //設置首列顯示
                IRow row1 = null;
                int rowIndex = 0;
                int maxRowIndex = commonCellList.Max(m => m.RowIndex);
                Dictionary<int, CellModel> rowColumnIndexCellDIC = null;
                ICell cell = null;
                object cellValue = null;

                do
                {
                    rowColumnIndexCellDIC = commonCellList.GetRawCellList(rowIndex).ToDictionary(m => m.ColumnIndex);
                    int 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);
                        }
                        int columnIndex = 0;
                        do
                        {
                            cell = row1.GetCell(columnIndex);
                            if (cell == null)
                            {
                                cell = row1.CreateCell(columnIndex);
                            }

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

                                CellFactory.SetCellValue(cell, cellValue, outputFormat: null, rowColumnIndexCellDIC[columnIndex].IsCellFormula);
                            }
                            columnIndex++;
                        } while (columnIndex <= maxColumnIndex);
                    }
                    rowIndex++;
                } while (rowIndex <= maxRowIndex);

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

            return workbook;
        }

        /// <summary>
        /// 更新模板文件數據:將使用單元格映射的數據T存入模板文件中
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="workbook"></param>
        /// <param name="sheet"></param>
        /// <param name="t"></param>
        /// <param name="excelFileDescription"></param>
        /// <returns></returns>
        public static IWorkbook UpdateTemplateWorkbook<T>(IWorkbook workbook, ISheet sheet, T t, ExcelFileDescription excelFileDescription = null)
        {
            //該方法預設替換模板數據在首個sheet里

            CellModelColl commonCellColl = ExcelHelper.ReadCellList(workbook, sheet, false);

            List<IExcelCellPointDeepUpdate> excelCellPointDeepList = new List<IExcelCellPointDeepUpdate>(0);
            if (excelFileDescription != null)
            {
                excelCellPointDeepList.Add((IExcelCellPointDeepUpdate)excelFileDescription.ExcelDeepUpdateList);
            }

            //獲取t的單元格映射列表
            List<ExcelCellFieldMapper> cellMapperList = ExcelCellFieldMapper.GetModelFieldMapper<T>();
            foreach (var cellMapper in cellMapperList)
            {
                if (cellMapper.CellParamWriteList.Count > 0)
                {
                    foreach (var cellParamWriteAttribute in cellMapper.CellParamWriteList)
                    {
                        CellModel cellModel = commonCellColl.GetCell(cellParamWriteAttribute.CellParamName);
                        if (cellModel != null)
                        {
                            cellModel.CellValue = cellMapper.PropertyInfo.GetValue(t);
                        }
                    }
                }
                if (cellMapper.CellPointWriteList.Count > 0)
                {
                    object cellValue = cellMapper.PropertyInfo.GetValue(t);
                    ICellModel firstCellPosition = null;
                    foreach (var cellPointWriteAttribute in cellMapper.CellPointWriteList)
                    {
                        firstCellPosition = CellFactory.GetCellByExcelPosition(cellPointWriteAttribute.CellPosition);
                        CellFactory.SetDeepUpdateCellValue(sheet, firstCellPosition.RowIndex, firstCellPosition.ColumnIndex, cellValue, cellPointWriteAttribute.OutputFormat, false, excelCellPointDeepList);
                    }
                }
            }

            workbook = ExcelHelper.CreateOrUpdateWorkbook(commonCellColl, workbook, sheet.SheetName);

            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);
        }

        /// <summary>
        /// 保存workbook到位元組流中(提供給API介面使用)
        /// </summary>
        /// <param name="workbook"></param>
        /// <returns></returns>
        public static byte[] SaveWorkbookToByte(IWorkbook workbook)
        {
            MemoryStream stream = new MemoryStream();
            stream.Seek(0, SeekOrigin.Begin);
            workbook.Write(stream);

            byte[] byteArray = stream.GetBuffer();
            return byteArray;
        }

        #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);

            try
            {
                IWorkbook workbook = ExcelHelper.GetExcelWorkbook(filePath);
                IFormulaEvaluator formulaEvaluator = null;

                if (workbook is XSSFWorkbook)
                {
                    formulaEvaluator = new XSSFFormulaEvaluator(workbook);
                }
                else if (workbook is HSSFWorkbook)
                {
                    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;

                    if (currentSheetRowTitleIndex >= 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);
            }
            catch (Exception e)
            {
                throw new Exception($"文件:{filePath}被占用!", e);
            }
            return tList ?? new List<T>(0);
        }

        public static CellModelColl ReadCellList(IWorkbook workbook, ISheet sheet, bool isRunFormula = false)
        {
            CellModelColl commonCells = new CellModelColl(10000);

            IFormulaEvaluator formulaEvaluator = null;
            if (workbook != null)
            {
                if (workbook is HSSFWorkbook)
                {
                    formulaEvaluator = new HSSFFormulaEvaluator(workbook);
                }
                else
                {
                    formulaEvaluator = new XSSFFormulaEvaluator(workbook);
                }
            }
            if (sheet != null)
            {
                CellModel cellModel = null;

                var rows = sheet.GetRowEnumerator();

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

                    List<ICell> cellList = row.Cells;

                    ICell cell = null;
                    foreach (var cellItem in cellList)
                    {
                        cell = cellItem;
                        if (isRunFormula && cell.CellType == CellType.Formula)
                        {
                            cell = formulaEvaluator.EvaluateInCell(cell);
                        }

                        cellModel = new CellModel
                        {
                            RowIndex = cell.RowIndex,
                            ColumnIndex = cell.ColumnIndex,
                            CellValue = cell.ToString(),
                            IsCellFormula = cell.CellType == CellType.Formula
                        };

                        commonCells.Add(cellModel);
                    }
                }
            }
            return commonCells;
        }

        /// <summary>
        /// 獲取文件單元格數據對象
        /// </summary>
        /// <typeparam name="T">T的屬性必須標記了ExcelCellAttribute</typeparam>
        /// <p

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

-Advertisement-
Play Games
更多相關文章
  • WPF的UI多語言切換核心代碼: CultureInfo.CurrentUICulture = CultureInfo.CreateSpecificCulture("語種"); 關於上面的語種如何傳進去,什麼時候調用上面的方法是跟你具體業務有關的。 我的做法: 1. 什麼時候調用 因為用戶的語種基本 ...
  • 關於多語言,其實有很多經驗可以分享。本篇文章先說說最基礎的。 下圖:利用自帶的resx文件格式記錄各種通用辭彙的多語言(簡體中文、繁體中文、英文) 下圖是英文的示例(註意:Access Modifier必須是`Public`,否則無法在xaml文件中引用) 使用方法: 1. 聲明命名空間 xmlns ...
  • 前言 代碼胡亂寫,維護火葬場! 在平時工作中遇到前同事寫介面這樣返回值 當介面返回1時,不去看他的代碼就永遠猜不到這個1代表的是返回成功還是返回值 稍微好點的 維護和改bug簡直讓人瘋狂,導致大部分時間浪費在“體會”別人返回值的邏輯中 天天加班與救bug於水火之中 合理分配前後端返回值很重要! 一般 ...
  • 3.1中提到我定義了一些公共配置項,現在我來說一說配置項的用法: 1. 提供軟體標識符 1 public static class CfgIndentifiers 2 { 3 public static readonly string Identifier = 4 #if DEBUG 5 "DEBU ...
  • 在上一篇文章abp(net core)+easyui+efcore實現倉儲管理系統——入庫管理之七(四十三)中我們實現了測試了入庫單新增功能,不過還存在一些BUG。今天我們來繼續完善入庫單信息新增功能。同時講講如何通過瀏覽器的調試功能來調整CSS樣式。 ...
  • 1.什麼是Swagger/OpenAPI? Swagger是一個與語言無關的規範,用於描述REST API。因為Swagger項目已捐贈給OpenAPI計劃,所以也叫OpenAPI。它允許電腦和人員瞭解服務的功能,可以直接線上訪問測試API功能。而Swagger UI提供了基於Web的UI,它使用 ...
  • 視頻, 圖文向新手解釋, 如何快速獲得開發Blazor的環境. ...
  • c 8引入了新特性:“可為空引用”( "詳情" ),這個功能個人覺得挺好的,能夠非常明確的表現程式設計者的意圖,編譯器能夠進行檢查,盡最大可能減小NullReferenceException錯誤。 如果是新項目,那麼上手很簡單,一點點搭建起來,遇山開山,遇河渡河。但是對於我這種手頭上的項目大多都是以 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...