本篇博客園是被任務(wù)所逼,,而已有的使用nopi技術(shù)的文檔技術(shù)經(jīng)驗(yàn)又不支持我需要的應(yīng)對(duì)各種復(fù)雜需求的苛刻要求,,只能自己造輪子封裝了,由于需要應(yīng)對(duì)很多總類型的數(shù)據(jù)采集需求,,因此有了本篇博客的代碼封裝,,下面一點(diǎn)點(diǎn)介紹吧: 項(xiàng)目框架:.net Core 3.1 Nuget包:DotNetCore.NPOI 1.2.2
收集excel你有沒有遇到過一下痛點(diǎn): 1-需要收集指定行標(biāo)題位置的數(shù)據(jù),我的標(biāo)題行不一定在第一行,。 這個(gè)和我的csv的文檔需求是一致的 2-需要采集指定單元格位置的數(shù)據(jù)生成一個(gè)對(duì)象,,而不是一個(gè)列表。 這里我的方案是制定一個(gè)單元格映射類解決問題,。 單元格映射類,,支持表達(dá)式數(shù)據(jù)采集(我可能需要一個(gè)單元格的數(shù)據(jù)+另一個(gè)單元格的數(shù)據(jù)作為一個(gè)屬性等等) 3-應(yīng)對(duì)不規(guī)范標(biāo)題無法轉(zhuǎn)出字符串進(jìn)行映射時(shí),能不能通過制定標(biāo)題的列下標(biāo)建立對(duì)應(yīng)關(guān)系,,進(jìn)行列表數(shù)據(jù)采集呢,? 本博客同時(shí)支持標(biāo)題字符串?dāng)?shù)據(jù)采集和標(biāo)題下標(biāo)數(shù)據(jù)采集,這個(gè)就牛逼了,。 4-存儲(chǔ)含有表達(dá)式的數(shù)據(jù),,這個(gè)并不是難點(diǎn),由于很重要,,就在這里列一下 5-應(yīng)對(duì)Excel模板文件的數(shù)據(jù)指定位置填入數(shù)據(jù),,該位置可能會(huì)變動(dòng)的解決方案。本文為了應(yīng)對(duì)該情況,,借助了單元格映射關(guān)系,,添加了模板參數(shù)名的屬性處理,可以應(yīng)對(duì)模板文件調(diào)整時(shí)的位置變動(dòng)問題,。 6-一個(gè)能同時(shí)處理excel新老版本(.xls和.xlsx),,一個(gè)指定excel位置保存數(shù)據(jù),保存含有表達(dá)式的數(shù)據(jù),,一個(gè)可以將多個(gè)不同的數(shù)據(jù)組合存放到一個(gè)excel中的需求都可以滿足,。
痛點(diǎn)大概就是上面這些了,下面寫主要代碼吧,,供大家參考,,不過封裝的類方法有點(diǎn)多:
本文借助了NPOI程序包做了業(yè)務(wù)封裝:
1-主要封裝類-ExcelHelper: 該類包含很多輔助功能:比如自動(dòng)幫助尋找含有指定標(biāo)題名所在的位置,、表達(dá)式元素A1,B2對(duì)應(yīng)單元格位置的解析等等:
![]() /// <summary> /// EXCEL幫助類 /// </summary> /// <typeparam name="T">泛型類</typeparam> /// <typeparam name="TCollection">泛型類集合</typeparam> public class ExcelHelper { public ILogger Logger { get; set; } public ExcelHelper(ILogger<ExcelHelper> logger) { this.Logger = logger; } #region 創(chuàng)建工作表 /// <summary> /// 將列表數(shù)據(jù)生成工作表 /// </summary> /// <param name="tList">要導(dǎo)出的數(shù)據(jù)集</param> /// <param name="fieldNameAndShowNameDic">鍵值對(duì)集合(鍵:字段名,值:顯示名稱)</param> /// <param name="workbook">更新時(shí)添加:要更新的工作表</param> /// <param name="sheetName">指定要?jiǎng)?chuàng)建的sheet名稱時(shí)添加</param> /// <param name="excelFileDescription">讀取或插入定制需求時(shí)添加</param> /// <returns></returns> public 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 = this.CreateOrUpdateWorkbook<T>(tList, titleMapperList, workbook, sheetName, excelFileDescription); return workbook; } /// <summary> /// 將列表數(shù)據(jù)生成工作表(T的屬性需要添加:屬性名列名映射關(guān)系) /// </summary> /// <param name="tList">要導(dǎo)出的數(shù)據(jù)集</param> /// <param name="workbook">更新時(shí)添加:要更新的工作表</param> /// <param name="sheetName">指定要?jiǎng)?chuàng)建的sheet名稱時(shí)添加</param> /// <param name="excelFileDescription">讀取或插入定制需求時(shí)添加</param> /// <returns></returns> public 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 = this.CreateOrUpdateWorkbook<T>(tList, titleMapperList, workbook, sheetName, excelFileDescription); return workbook; } private IWorkbook CreateOrUpdateWorkbook<T>(List<T> tList, List<ExcelTitleFieldMapper> titleMapperList, IWorkbook workbook, string sheetName, ExcelFileDescription excelFileDescription = null) { //xls文件格式屬于老版本文件,,一個(gè)sheet最多保存65536行,;而xlsx屬于新版文件類型; //Excel 07 - 2003一個(gè)工作表最多可有65536行,,行用數(shù)字1—65536表示; 最多可有256列,,列用英文字母A—Z,AA—AZ,,BA—BZ,,……,IA—IV表示,;一個(gè)工作簿中最多含有255個(gè)工作表,,默認(rèn)情況下是三個(gè)工作表; //Excel 2007及以后版本,,一個(gè)工作表最多可有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) { //到達(dá)標(biāo)題行 if (currentRowIndex == defaultBeginTitleIndex) { int cellIndex = 0; foreach (var titleMapper in titleMapperList) { cell = row1.GetCell(cellIndex); if (cell == null) { cell = row1.CreateCell(cellIndex); } this.SetCellValue(cell, titleMapper.ExcelTitle, outputFormat: null); cellIndex++; } } //到達(dá)內(nèi)容行 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); } this.SetCellValue<T>(cell, t, titleMapper); cellIndex++; } //重要:設(shè)置行寬度自適應(yīng)(大批量添加數(shù)據(jù)時(shí),,該行代碼需要注釋,,否則會(huì)極大減緩Excel添加行的速度!) //worksheet.AutoSizeColumn(i, true); } } } currentRowIndex++; } while (dataIndex < tCount - 1); //設(shè)置表達(dá)式重算(如果不添加該代碼,,表達(dá)式更新不出結(jié)果值) worksheet.ForceFormulaRecalculation = true; return workbook; } /// <summary> /// 將單元格數(shù)據(jù)列表生成工作表 /// </summary> /// <param name="commonCellList">所有的單元格數(shù)據(jù)列表</param> /// <param name="workbook">更新時(shí)添加:要更新的工作表</param> /// <param name="sheetName">指定要?jiǎng)?chuàng)建的sheet名稱時(shí)添加</param> /// <returns></returns> public IWorkbook CreateOrUpdateWorkbook(CommonCellModelColl commonCellList, IWorkbook workbook = null, string sheetName = "sheet1") { //xls文件格式屬于老版本文件,,一個(gè)sheet最多保存65536行;而xlsx屬于新版文件類型,; //Excel 07 - 2003一個(gè)工作表最多可有65536行,,行用數(shù)字1—65536表示; 最多可有256列,列用英文字母A—Z,,AA—AZ,,BA—BZ,……,,IA—IV表示,;一個(gè)工作簿中最多含有255個(gè)工作表,,默認(rèn)情況下是三個(gè)工作表,; //Excel 2007及以后版本,一個(gè)工作表最多可有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); } //設(shè)置首列顯示 IRow row1 = null; int rowIndex = 0; int maxRowIndex = commonCellList.Max(m => m.ColumnIndex); 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; this.SetCellValue(cell, cellValue, outputFormat: null, rowColumnIndexCellDIC[columnIndex].IsCellFormula); } columnIndex++; } while (columnIndex <= maxColumnIndex); } rowIndex++; } while (rowIndex <= maxRowIndex); //設(shè)置表達(dá)式重算(如果不添加該代碼,表達(dá)式更新不出結(jié)果值) worksheet.ForceFormulaRecalculation = true; return workbook; } /// <summary> /// 更新模板文件數(shù)據(jù):將使用單元格映射的數(shù)據(jù)T存入模板文件中 /// </summary> /// <param name="filePath">所有的單元格數(shù)據(jù)列表</param> /// <param name="t">添加了單元格參數(shù)映射的數(shù)據(jù)對(duì)象</param> /// <returns></returns> public IWorkbook CreateOrUpdateWorkbook<T>(string filePath, T t) { //該方法默認(rèn)替換模板數(shù)據(jù)在首個(gè)sheet里 IWorkbook workbook = null; CommonCellModelColl commonCellColl = this._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]; this.SetCellValue<T>(cell, t, cellMapper); } } } if (tParamMapperDic.Count > 0) { //循環(huán)所有單元格數(shù)據(jù)替換指定變量數(shù)據(jù) foreach (var cellItem in commonCellColl) { cellValue = cellItem.CellValue.ToString(); if (tParamMapperDic.ContainsKey(cellValue)) { cellItem.CellValue = tParamMapperDic[cellValue].PropertyInfo.GetValue(t); } } } //設(shè)置表達(dá)式重算(如果不添加該代碼,,表達(dá)式更新不出結(jié)果值) worksheet.ForceFormulaRecalculation = true; return workbook; } #endregion #region 保存工作表到文件 /// <summary> /// 保存Workbook數(shù)據(jù)為文件 /// </summary> /// <param name="workbook"></param> /// <param name="fileDirectoryPath"></param> /// <param name="fileName"></param> public void SaveWorkbookToFile(IWorkbook workbook, string filePath) { //xls文件格式屬于老版本文件,,一個(gè)sheet最多保存65536行,;而xlsx屬于新版文件類型; //Excel 07 - 2003一個(gè)工作表最多可有65536行,,行用數(shù)字1—65536表示; 最多可有256列,,列用英文字母A—Z,AA—AZ,,BA—BZ,,……,IA—IV表示,;一個(gè)工作簿中最多含有255個(gè)工作表,,默認(rèn)情況下是三個(gè)工作表; //Excel 2007及以后版本,,一個(gè)工作表最多可有1048576行,,16384列; MemoryStream ms = new MemoryStream(); //這句代碼非常重要,,如果不加,,會(huì)報(bào):打開的EXCEL格式與擴(kuò)展名指定的格式不一致 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到字節(jié)流中(提供給API接口使用) /// </summary> /// <param name="workbook"></param> /// <returns></returns> public 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數(shù)據(jù) /// <summary> /// 讀取Excel數(shù)據(jù)1_手動(dòng)提供屬性信息和標(biāo)題對(duì)應(yīng)關(guān)系 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="filePath"></param> /// <param name="fieldNameAndShowNameDic"></param> /// <param name="excelFileDescription"></param> /// <returns></returns> public List<T> ReadTitleDataList<T>(string filePath, Dictionary<string, string> fieldNameAndShowNameDic, ExcelFileDescription excelFileDescription) where T : new() { //標(biāo)題屬性字典列表 List<ExcelTitleFieldMapper> titleMapperList = ExcelTitleFieldMapper.GetModelFieldMapper<T>(fieldNameAndShowNameDic); List<T> tList = this._GetTList<T>(filePath, titleMapperList, excelFileDescription); return tList ?? new List<T>(0); } /// <summary> /// 讀取Excel數(shù)據(jù)2_使用Excel標(biāo)記特性和文件描述自動(dòng)創(chuàng)建關(guān)系 /// </summary> /// <param name="filePath"></param> /// <param name="excelFileDescription"></param> /// <returns></returns> public List<T> ReadTitleDataList<T>(string filePath, ExcelFileDescription excelFileDescription) where T : new() { //標(biāo)題屬性字典列表 List<ExcelTitleFieldMapper> titleMapperList = ExcelTitleFieldMapper.GetModelFieldMapper<T>(); List<T> tList = this._GetTList<T>(filePath, titleMapperList, excelFileDescription); return tList ?? new List<T>(0); } private 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); //標(biāo)題下標(biāo)屬性字典 Dictionary<int, ExcelTitleFieldMapper> sheetTitleIndexPropertyDic = new Dictionary<int, ExcelTitleFieldMapper>(0); //如果沒有設(shè)置標(biāo)題行,則通過自動(dòng)查找方法獲取 if (excelFileDescription.TitleRowIndex < 0) { string[] titleArray = titleMapperList.Select(m => m.ExcelTitle).ToArray(); currentSheetRowTitleIndex = this.GetSheetTitleIndex(sheet, titleArray); } else { currentSheetRowTitleIndex = excelFileDescription.TitleRowIndex; } var rows = sheet.GetRowEnumerator(); bool isHaveTitleIndex = false; //含有Excel行下標(biāo) 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; //到達(dá)標(biāo)題行 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]); } } } //到達(dá)內(nèi)容行 if (currentRowIndex > currentSheetRowTitleIndex) { t = new T(); ExcelTitleFieldMapper excelTitleFieldMapper = null; foreach (var titleIndexItem in sheetTitleIndexPropertyDic) { ICell cell = row.GetCell(titleIndexItem.Key); excelTitleFieldMapper = titleIndexItem.Value; //沒有數(shù)據(jù)的單元格默認(rèn)為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) { //讀取含有表達(dá)式的單元格值 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) { this.Logger.LogError($"文件_{filePath}讀取{currentRowIndex + 1}行內(nèi)容失??!"); t = default(T); break; } } if (t != null) { tList.Add(t); } } } currentSheetIndex++; } while (currentSheetIndex + 1 <= sheetCount); } return tList ?? new List<T>(0); } /// <summary> /// 讀取文件的所有單元格數(shù)據(jù) /// </summary> /// <param name="filePath">文件路徑</param> /// <returns></returns> public CommonCellModelColl ReadCellList(string filePath) { IWorkbook workbook = null; CommonCellModelColl commonCellColl = this._ReadCellList(filePath, out workbook); return commonCellColl; } /// <summary> /// 讀取文件的所有單元格數(shù)據(jù) /// </summary> /// <param name="filePath">文件路徑</param> /// <returns></returns> public CommonCellModelColl ReadCellList(string filePath, out IWorkbook workbook) { CommonCellModelColl commonCellColl = this._ReadCellList(filePath, out workbook); return commonCellColl; } private 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行數(shù)據(jù)開始獲取 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> /// 獲取文件單元格數(shù)據(jù)對(duì)象 /// </summary> /// <typeparam name="T">T的屬性必須標(biāo)記了ExcelCellAttribute</typeparam> /// <param name="filePath">文建路徑</param> /// <returns></returns> public T ReadCellData<T>(string filePath) where T : new() { T t = new T(); this.Logger.LogInformation($"開始讀取{filePath}的數(shù)據(jù)..."); CommonCellModelColl commonCellColl = this.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 = this.GetVByExpress(cellExpress, propertyInfo, commonCellColl).ToString(); if (!string.IsNullOrEmpty(pValue)) { propertyInfo.SetValue(t, Convert.ChangeType(pValue, propertyInfo.PropertyType)); } } return t; } /// <summary> /// 獲取文件首個(gè)sheet的標(biāo)題位置 /// </summary> /// <typeparam name="T">T必須做了標(biāo)題映射</typeparam> /// <param name="filePath"></param> /// <returns></returns> public 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 = this.GetSheetTitleIndex(sheet, titleArray); } } return titleIndex; } /// <summary> /// 獲取文件首個(gè)sheet的標(biāo)題位置 /// </summary> /// <param name="filePath"></param> /// <param name="titleNames"></param> /// <returns></returns> public int FileFirstSheetTitleIndex(string filePath, params string[] titleNames) { 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); } ISheet sheet = workbook.GetSheetAt(0); titleIndex = this.GetSheetTitleIndex(sheet, titleNames); } } return titleIndex; } #endregion #region 輔助方法 /// <summary> /// 返回單元格坐標(biāo)橫坐標(biāo) /// </summary> /// <param name="cellPoint">單元格坐標(biāo)(A1,B15...)</param> /// <param name="columnIndex">帶回:縱坐標(biāo)</param> /// <returns></returns> private int GetValueByZM(string cellPoint, out int columnIndex) { int rowIndex = 0; columnIndex = 0; Regex columnIndexRegex = new Regex("[a-zA-Z]+", RegexOptions.IgnoreCase); string columnZM = columnIndexRegex.Match(cellPoint).Value; rowIndex = Convert.ToInt32(cellPoint.Replace(columnZM, "")) - 1; int zmLen = 0; if (!string.IsNullOrEmpty(columnZM)) { zmLen = columnZM.Length; } for (int i = zmLen - 1; i > -1; i--) { columnIndex += (int)Math.Pow((int)columnZM[i] - 64, (zmLen - i)); } columnIndex = columnIndex - 1; return rowIndex; } /// <summary> /// 根據(jù)單元格表達(dá)式和單元格數(shù)據(jù)集獲取數(shù)據(jù) /// </summary> /// <param name="cellExpress">單元格表達(dá)式</param> /// <param name="commonCellColl">單元格數(shù)據(jù)集</param> /// <returns></returns> private object GetVByExpress(string cellExpress, PropertyInfo propertyInfo, CommonCellModelColl commonCellColl) { object value = null; //含有單元格表達(dá)式的取表達(dá)式值,沒有表達(dá)式的取單元格字符串 if (!string.IsNullOrEmpty(cellExpress)) { MatchCollection matchCollection = Regex.Matches(cellExpress, "\\w+"); string point = null; int rowIndex = 0; int columnIndex = 0; string cellValue = null; System.Data.DataTable dt = new System.Data.DataTable(); foreach (var item in matchCollection) { point = item.ToString(); rowIndex = this.GetValueByZM(point, out columnIndex); cellValue = commonCellColl[rowIndex, columnIndex]?.CellValue?.ToString() ?? ""; if (propertyInfo.PropertyType == typeof(decimal) || propertyInfo.PropertyType == typeof(double) || propertyInfo.PropertyType == typeof(int)) { if (!string.IsNullOrEmpty(cellValue)) { cellValue = cellValue.Replace(",", ""); } else { cellValue = "0"; } } else { cellValue = $"'{cellValue}'"; } cellExpress = cellExpress.Replace(item.ToString(), cellValue); } //執(zhí)行字符和數(shù)字的表達(dá)式計(jì)算(字符需要使用單引號(hào)包裹,,數(shù)字需要移除逗號(hào)) value = dt.Compute(cellExpress, ""); } return value ?? ""; } /// <summary> /// 將數(shù)據(jù)放入單元格中 /// </summary> /// <typeparam name="T">泛型類</typeparam> /// <param name="cell">單元格對(duì)象</param> /// <param name="t">泛型類數(shù)據(jù)</param> /// <param name="cellFieldMapper">單元格映射信息</param> private void SetCellValue<T>(ICell cell, T t, ExcelCellFieldMapper cellFieldMapper) { object cellValue = cellFieldMapper.PropertyInfo.GetValue(t); this.SetCellValue(cell, cellValue, cellFieldMapper?.OutputFormat); } /// <summary> /// 將數(shù)據(jù)放入單元格中 /// </summary> /// <typeparam name="T">泛型類</typeparam> /// <param name="cell">單元格對(duì)象</param> /// <param name="t">泛型類數(shù)據(jù)</param> /// <param name="cellFieldMapper">單元格映射信息</param> private void SetCellValue<T>(ICell cell, T t, ExcelTitleFieldMapper cellFieldMapper) { object cellValue = cellFieldMapper.PropertyInfo.GetValue(t); this.SetCellValue(cell, cellValue, cellFieldMapper?.OutputFormat, cellFieldMapper?.IsCoordinateExpress ?? false); } /// <summary> /// 將數(shù)據(jù)放入單元格中 /// </summary> /// <param name="cell">單元格對(duì)象</param> /// <param name="cellValue">數(shù)據(jù)</param> /// <param name="outputFormat">格式化字符串</param> /// <param name="isCoordinateExpress">是否是表達(dá)式數(shù)據(jù)</param> private void SetCellValue(ICell cell, object cellValue, string outputFormat, bool isCoordinateExpress = false) { if (cell != null) { if (isCoordinateExpress) { cell.SetCellFormula(cellValue.ToString()); } else { if (!string.IsNullOrEmpty(outputFormat)) { string formatValue = null; IFormatProvider formatProvider = null; if (cellValue is DateTime) { formatProvider = new DateTimeFormatInfo(); ((DateTimeFormatInfo)formatProvider).ShortDatePattern = outputFormat; } formatValue = ((IFormattable)cellValue).ToString(outputFormat, formatProvider); cell.SetCellValue(formatValue); } else { if (cellValue is decimal || cellValue is double || cellValue is int) { cell.SetCellValue(Convert.ToDouble(cellValue)); } else if (cellValue is DateTime) { cell.SetCellValue((DateTime)cellValue); } else if (cellValue is bool) { cell.SetCellValue((bool)cellValue); } else { cell.SetCellValue(cellValue.ToString()); } } } } } /// <summary> /// 根據(jù)標(biāo)題名稱獲取標(biāo)題行下標(biāo)位置 /// </summary> /// <param name="sheet">要查找的sheet</param> /// <param name="titleNames">標(biāo)題名稱</param> /// <returns></returns> private int GetSheetTitleIndex(ISheet sheet, params string[] titleNames) { int titleIndex = -1; if (sheet != null && titleNames != null && titleNames.Length > 0) { var rows = sheet.GetRowEnumerator(); List<ICell> cellList = null; List<string> rowValueList = null; //從第1行數(shù)據(jù)開始獲取 while (rows.MoveNext()) { IRow row = (IRow)rows.Current; cellList = row.Cells; rowValueList = new List<string>(cellList.Count); foreach (var cell in cellList) { rowValueList.Add(cell.ToString()); } bool isTitle = true; foreach (var title in titleNames) { if (!rowValueList.Contains(title)) { isTitle = false; break; } } if (isTitle) { titleIndex = row.RowNum; break; } } } return titleIndex; } #endregion }
2-自定義單元格類:
![]() public class CommonCellModel { public CommonCellModel() { } public CommonCellModel(int rowIndex, int columnIndex, object cellValue, bool isCellFormula = false) { this.RowIndex = rowIndex; this.ColumnIndex = columnIndex; this.CellValue = cellValue; this.IsCellFormula = isCellFormula; } public int RowIndex { get; set; } public int ColumnIndex { get; set; } public object CellValue { get; set; } /// <summary> /// 是否是單元格公式 /// </summary> public bool IsCellFormula { get; set; } } public class CommonCellModelColl : List<CommonCellModel>, IList<CommonCellModel> { public CommonCellModelColl() { } public CommonCellModelColl(int capacity) : base(capacity) { } /// <summary> /// 根據(jù)行下標(biāo),,列下標(biāo)獲取單元格數(shù)據(jù) /// </summary> /// <param name="rowIndex"></param> /// <param name="columnIndex"></param> /// <returns></returns> public CommonCellModel this[int rowIndex, int columnIndex] { get { CommonCellModel cell = this.FirstOrDefault(m => m.RowIndex == rowIndex && m.ColumnIndex == columnIndex); return cell; } set { CommonCellModel cell = this.FirstOrDefault(m => m.RowIndex == rowIndex && m.ColumnIndex == columnIndex); if (cell != null) { cell.CellValue = value.CellValue; } } } /// <summary> /// 所有一行所有的單元格數(shù)據(jù) /// </summary> /// <param name="rowIndex">行下標(biāo)</param> /// <returns></returns> public List<CommonCellModel> GetRawCellList(int rowIndex) { List<CommonCellModel> cellList = null; cellList = this.FindAll(m => m.RowIndex == rowIndex); return cellList ?? new List<CommonCellModel>(0); } /// <summary> /// 所有一列所有的單元格數(shù)據(jù) /// </summary> /// <param name="columnIndex">列下標(biāo)</param> /// <returns></returns> public List<CommonCellModel> GetColumnCellList(int columnIndex) { List<CommonCellModel> cellList = null; cellList = this.FindAll(m => m.ColumnIndex == columnIndex); return cellList ?? new List<CommonCellModel>(0); } }
3-單元格特性類:
![]() /// <summary> /// Excel單元格標(biāo)記特性 /// </summary> [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = false)] public class ExcelCellAttribute : System.Attribute { /// <summary> /// 該參數(shù)用于收集數(shù)據(jù)存于固定位置的單元格數(shù)據(jù)(單元格坐標(biāo)表達(dá)式(如:A1,B2,C1+C2...橫坐標(biāo)使用26進(jìn)制字母,縱坐標(biāo)使用十進(jìn)制數(shù)字)) /// </summary> public string CellCoordinateExpress { get; set; } /// <summary> /// 該參數(shù)用于替換模板文件的預(yù)定義變量使用({A} {B}) /// </summary> public string CellParamName { get; set; } /// <summary> /// 字符輸出格式(數(shù)字和日期類型需要) /// </summary> public string OutputFormat { get; set; } public ExcelCellAttribute(string cellCoordinateExpress = null, string cellParamName = null) { CellCoordinateExpress = cellCoordinateExpress; CellParamName = cellParamName; } public ExcelCellAttribute(string cellCoordinateExpress, string cellParamName, string outputFormat) : this(cellCoordinateExpress, cellParamName) { OutputFormat = outputFormat; } }
4-單元格屬性映射幫助類:
![]() /// <summary> /// 單元格字段映射類 /// </summary> internal class ExcelCellFieldMapper { /// <summary> /// 屬性信息 /// </summary> public PropertyInfo PropertyInfo { get; set; } /// <summary> /// 該參數(shù)用于收集數(shù)據(jù)存于固定位置的單元格數(shù)據(jù)(單元格坐標(biāo)表達(dá)式(如:A1,B2,C1+C2...橫坐標(biāo)使用26進(jìn)制字母,,縱坐標(biāo)使用十進(jìn)制數(shù)字)) /// </summary> public string CellCoordinateExpress { get; set; } /// <summary> /// 該參數(shù)用于替換模板文件的預(yù)定義變量使用({A} {B}) /// </summary> public string CellParamName { get; set; } /// <summary> /// 字符輸出格式(數(shù)字和日期類型需要) /// </summary> public string OutputFormat { get; set; } /// <summary> /// 獲取對(duì)應(yīng)關(guān)系_T屬性添加了單元格映射關(guān)系 /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public static List<ExcelCellFieldMapper> GetModelFieldMapper<T>() { List<ExcelCellFieldMapper> fieldMapperList = new List<ExcelCellFieldMapper>(100); List<PropertyInfo> tPropertyInfoList = typeof(T).GetProperties().ToList(); ExcelCellAttribute cellExpress = null; foreach (var item in tPropertyInfoList) { cellExpress = item.GetCustomAttribute<ExcelCellAttribute>(); if (cellExpress != null) { fieldMapperList.Add(new ExcelCellFieldMapper { CellCoordinateExpress = cellExpress.CellCoordinateExpress, CellParamName = cellExpress.CellParamName, OutputFormat = cellExpress.OutputFormat, PropertyInfo = item }); } } return fieldMapperList; } }
5-Excel文件描述類:
![]() public class ExcelFileDescription { /// <summary> /// 默認(rèn)從第1行數(shù)據(jù)開始讀取標(biāo)題數(shù)據(jù) /// </summary> public ExcelFileDescription() : this(0) { } public ExcelFileDescription(int titleRowIndex) { this.TitleRowIndex = titleRowIndex; } /// <summary> /// 標(biāo)題所在行位置(默認(rèn)為0,,沒有標(biāo)題填-1) /// </summary> public int TitleRowIndex { get; set; } }
6-Excel標(biāo)題特性類:
![]() /// <summary> /// Excel標(biāo)題標(biāo)記特性 /// </summary> [System.AttributeUsage(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple = false)] public class ExcelTitleAttribute : System.Attribute { /// <summary> /// Excel行標(biāo)題(標(biāo)題和下標(biāo)選擇一個(gè)即可) /// </summary> public string RowTitle { get; set; } /// <summary> /// Excel行下標(biāo)(標(biāo)題和下標(biāo)選擇一個(gè)即可,默認(rèn)值-1) /// </summary> public int RowTitleIndex { get; set; } /// <summary> /// 單元格是否要檢查空數(shù)據(jù)(true為檢查,為空的行數(shù)據(jù)不添加) /// </summary> public bool IsCheckContentEmpty { get; set; } /// <summary> /// 字符輸出格式(數(shù)字和日期類型需要) /// </summary> public string OutputFormat { get; set; } /// <summary> /// 是否是公式列 /// </summary> public bool IsCoordinateExpress { get; set; } /// <summary> /// 標(biāo)題特性構(gòu)造方法 /// </summary> /// <param name="title">標(biāo)題</param> /// <param name="isCheckEmpty">單元格是否要檢查空數(shù)據(jù)</param> /// <param name="isCoordinateExpress">是否是公式列</param> /// <param name="outputFormat">是否有格式化輸出要求</param> public ExcelTitleAttribute(string title, bool isCheckEmpty = false, bool isCoordinateExpress = false, string outputFormat = "") { RowTitle = title; IsCheckContentEmpty = isCheckEmpty; IsCoordinateExpress = isCoordinateExpress; OutputFormat = outputFormat; RowTitleIndex = -1; } public ExcelTitleAttribute(int titleIndex, bool isCheckEmpty = false, bool isCoordinateExpress = false, string outputFormat = "") { RowTitleIndex = titleIndex; IsCheckContentEmpty = isCheckEmpty; IsCoordinateExpress = isCoordinateExpress; OutputFormat = outputFormat; } }
7-Ecel標(biāo)題屬性映射幫助類:
![]() /// <summary> /// 標(biāo)題字段映射類 /// </summary> internal class ExcelTitleFieldMapper { /// <summary> /// 屬性信息 /// </summary> public PropertyInfo PropertyInfo { get; set; } /// <summary> /// 行標(biāo)題 /// </summary> public string ExcelTitle { get; set; } /// <summary> /// 行標(biāo)題下標(biāo)位置 /// </summary> public int ExcelTitleIndex { get; set; } /// <summary> /// 是否要做行內(nèi)容空檢查 /// </summary> public bool IsCheckContentEmpty { get; set; } /// <summary> /// 字符輸出格式(數(shù)字和日期類型需要) /// </summary> public string OutputFormat { get; set; } /// <summary> /// 是否是公式列 /// </summary> public bool IsCoordinateExpress { get; set; } /// <summary> /// 獲取對(duì)應(yīng)關(guān)系_T屬性添加了標(biāo)題映射關(guān)系 /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public static List<ExcelTitleFieldMapper> GetModelFieldMapper<T>() { List<ExcelTitleFieldMapper> fieldMapperList = new List<ExcelTitleFieldMapper>(100); List<PropertyInfo> tPropertyInfoList = typeof(T).GetProperties().ToList(); ExcelTitleAttribute excelTitleAttribute = null; foreach (var tPropertyInfo in tPropertyInfoList) { excelTitleAttribute = (ExcelTitleAttribute)tPropertyInfo.GetCustomAttribute(typeof(ExcelTitleAttribute)); if (excelTitleAttribute != null) { fieldMapperList.Add(new ExcelTitleFieldMapper { PropertyInfo = tPropertyInfo, ExcelTitle = excelTitleAttribute.RowTitle, ExcelTitleIndex = excelTitleAttribute.RowTitleIndex, IsCheckContentEmpty = excelTitleAttribute.IsCheckContentEmpty, OutputFormat = excelTitleAttribute.OutputFormat, IsCoordinateExpress = excelTitleAttribute.IsCoordinateExpress }); } } return fieldMapperList; } /// <summary> /// 獲取對(duì)應(yīng)關(guān)系_手動(dòng)提供映射關(guān)系 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="fieldNameAndShowNameDic"></param> /// <returns></returns> public static List<ExcelTitleFieldMapper> GetModelFieldMapper<T>(Dictionary<string, string> fieldNameAndShowNameDic) { List<ExcelTitleFieldMapper> fieldMapperList = new List<ExcelTitleFieldMapper>(100); List<PropertyInfo> tPropertyInfoList = typeof(T).GetProperties().ToList(); PropertyInfo propertyInfo = null; foreach (var item in fieldNameAndShowNameDic) { propertyInfo = tPropertyInfoList.Find(m => m.Name.Equals(item.Key, StringComparison.OrdinalIgnoreCase)); fieldMapperList.Add(new ExcelTitleFieldMapper { PropertyInfo = propertyInfo, ExcelTitle = item.Value, ExcelTitleIndex = -1, OutputFormat = null, IsCheckContentEmpty = false, IsCoordinateExpress = false }); } return fieldMapperList; } /// <summary> /// 獲取對(duì)應(yīng)關(guān)系_未提供(默認(rèn)屬性名和標(biāo)題名一致) /// </summary> /// <returns></returns> public static List<ExcelTitleFieldMapper> GetModelDefaultFieldMapper<T>() { List<ExcelTitleFieldMapper> fieldMapperList = new List<ExcelTitleFieldMapper>(100); List<PropertyInfo> tPropertyInfoList = typeof(T).GetProperties().ToList(); foreach (var item in tPropertyInfoList) { fieldMapperList.Add(new ExcelTitleFieldMapper { PropertyInfo = item, ExcelTitle = item.Name, ExcelTitleIndex = -1, OutputFormat = null, IsCheckContentEmpty = false, IsCoordinateExpress = false }); } return fieldMapperList; } }
示例代碼1-單元格映射類:
![]() /// <summary> /// 賬戶_多幣種交易報(bào)表_數(shù)據(jù)源 /// </summary> public class AccountMultiCurrencyTransactionSource { /// <summary> /// 期初 /// </summary> [ExcelCellAttribute("B9")] public decimal BeginingBalance { get; set; } /// <summary> /// 收款 /// </summary> [ExcelCellAttribute("B19+C19")] public decimal TotalTransactionPrice { get; set; } /// <summary> /// 收到非EBay款項(xiàng)_主要指從其他賬戶轉(zhuǎn)給當(dāng)前賬戶的錢 /// </summary> [ExcelCellAttribute("B21+C21")] public decimal TransferAccountInPrice { get; set; } /// <summary> /// 退款(客戶不提交爭議直接退款) /// </summary> [ExcelCellAttribute("B23+C23")] public decimal TotalRefundPrice { get; set; } /// <summary> /// 手續(xù)費(fèi) /// </summary> [ExcelCellAttribute("B25+C25")] public decimal TotalFeePrice { get; set; } /// <summary> /// 爭議退款 /// </summary> [ExcelCellAttribute("B37+C37")] public decimal TotalChargebackRefundPrice { get; set; } /// <summary> /// 轉(zhuǎn)賬與提現(xiàn)(幣種轉(zhuǎn)換) /// </summary> [ExcelCellAttribute("B45+C45")] public decimal CurrencyChangePrice { get; set; } /// <summary> /// 轉(zhuǎn)賬與提現(xiàn)(轉(zhuǎn)賬到paypal賬戶)_提現(xiàn)失敗退回金額 /// </summary> [ExcelCellAttribute("B47+C47")] public decimal CashWithdrawalInPrice { get; set; } /// <summary> /// 轉(zhuǎn)賬與提現(xiàn)(從paypal賬戶轉(zhuǎn)賬)_提現(xiàn)金額 /// </summary> [ExcelCellAttribute("B49+C49")] public decimal CashWithdrawalOutPrice { get; set; } /// <summary> /// 購物_主要指從當(dāng)前賬戶轉(zhuǎn)給其他賬戶的錢 /// </summary> [ExcelCellAttribute("B51+C51")] public decimal TransferAccountOutPrice { get; set; } /// <summary> /// 其他活動(dòng) /// </summary> [ExcelCellAttribute("B85+C85")] public decimal OtherPrice { get; set; } /// <summary> /// 期末 /// </summary> [ExcelCellAttribute("C9")] public decimal EndingBalance { get; set; } }
示例代碼2-標(biāo)題映射類(標(biāo)題映射分類字符串映射和下標(biāo)位置映射,,這里使用下標(biāo)位置映射):
![]() /// <summary> /// 美元幣種轉(zhuǎn)換_數(shù)據(jù)源 /// </summary> public class CurrencyChangeUSDSource { /// <summary> /// 日期[y/M/d] /// </summary> [ExcelTitleAttribute(0, true)] public DateTime Date { get; set; } /// <summary> /// 類型 /// </summary> [ExcelTitleAttribute(1, true)] public string Type { get; set; } /// <summary> /// 交易號(hào) /// </summary> [ExcelTitleAttribute(2)] public string TX { get; set; } /// <summary> /// 商家/接收人姓名地址第1行地址第2行/區(qū)發(fā)款賬戶名稱_發(fā)款賬戶簡稱 /// </summary> [ExcelTitleAttribute(3)] public string SendedOrReceivedName { get; set; } /// <summary> /// 電子郵件編號(hào)_發(fā)款賬戶全稱 /// </summary> [ExcelTitleAttribute(4)] public string SendedOrReceivedAccountName { get; set; } /// <summary> /// 幣種 /// </summary> [ExcelTitleAttribute(5)] public string CurrencyCode { get; set; } /// <summary> /// 總額 /// </summary> [ExcelTitleAttribute(6)] public decimal TotalPrice { get; set; } /// <summary> /// 凈額 /// </summary> [ExcelTitleAttribute(7)] public decimal NetPrice { get; set; } /// <summary> /// 費(fèi)用 /// </summary> [ExcelTitleAttribute(8)] public decimal FeePrice { get; set; } }
示例代碼3-模板文件數(shù)據(jù)替換-單元格映射類:
![]() /// <summary> /// 多賬戶美元匯總金額_最終模板使用展示類 /// </summary> public class AccountUSDSummaryTransaction { /// <summary> /// 期初 /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_BeginingBalance}")] public decimal DLZ_BeginingBalance { get; set; } /// <summary> /// 收款 /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_TotalTransactionPrice}")] public decimal DLZ_TotalTransactionPrice { get; set; } /// <summary> /// 收到非EBay款項(xiàng)_主要指從其他賬戶轉(zhuǎn)給當(dāng)前賬戶的錢 /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_TransferAccountInPrice}")] public decimal DLZ_TransferAccountInPrice { get; set; } /// <summary> /// 退款(客戶不提交爭議直接退款) /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_TotalRefundPrice}")] public decimal DLZ_TotalRefundPrice { get; set; } /// <summary> /// 手續(xù)費(fèi) /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_TotalFeePrice}")] public decimal DLZ_TotalFeePrice { get; set; } /// <summary> /// 爭議退款 /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_TotalChargebackRefundPrice}")] public decimal DLZ_TotalChargebackRefundPrice { get; set; } /// <summary> /// 轉(zhuǎn)賬與提現(xiàn)(幣種轉(zhuǎn)換) /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_CurrencyChangePrice}")] public decimal DLZ_CurrencyChangePrice { get; set; } /// <summary> /// 轉(zhuǎn)賬與提現(xiàn)(轉(zhuǎn)賬到paypal賬戶)_提現(xiàn)失敗退回金額 /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_CashWithdrawalInPrice}")] public decimal DLZ_CashWithdrawalInPrice { get; set; } /// <summary> /// 轉(zhuǎn)賬與提現(xiàn)(從paypal賬戶轉(zhuǎn)賬)_提現(xiàn)金額 /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_CashWithdrawalOutPrice}")] public decimal DLZ_CashWithdrawalOutPrice { get; set; } /// <summary> /// 購物_主要指從當(dāng)前賬戶轉(zhuǎn)給其他賬戶的錢 /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_TransferAccountOutPrice}")] public decimal DLZ_TransferAccountOutPrice { get; set; } /// <summary> /// 其他活動(dòng) /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_OtherPrice}")] public decimal DLZ_OtherPrice { get; set; } /// <summary> /// 期末 /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_EndingBalance}")] public decimal DLZ_EndingBalance { get { decimal result = this.DLZ_BeginingBalance + this.DLZ_TotalTransactionPrice + this.DLZ_TransferAccountInPrice + this.DLZ_TotalRefundPrice + this.DLZ_TotalFeePrice + this.DLZ_TotalChargebackRefundPrice + this.DLZ_CurrencyChangePrice + this.DLZ_CashWithdrawalInPrice + this.DLZ_CashWithdrawalOutPrice + this.DLZ_TransferAccountOutPrice + this.DLZ_OtherPrice; return result; } } /// <summary> /// 期末匯率差 /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_EndingBalanceDifferenceValue}")] public decimal DLZ_EndingBalanceDifferenceValue { get { return this.DLZ_RealRateEndingBalance - this.DLZ_EndingBalance; } } /// <summary> /// 真實(shí)匯率計(jì)算的期末余額 /// </summary> [ExcelCellAttribute(cellParamName: "{DLZ_RealRateEndingBalance}")] public decimal DLZ_RealRateEndingBalance { get; set; } }
示例代碼4-存儲(chǔ)多個(gè)數(shù)據(jù)源到一個(gè)Excel中(這里我是保存到了不同的sheet頁里,,當(dāng)然也可以保持到同一個(gè)sheet的不同位置):
IWorkbook workbook = null; workbook = ExcelHelper.CreateOrUpdateWorkbook(dlzShopList, workbook, "獨(dú)立站"); workbook = ExcelHelper.CreateOrUpdateWorkbook(ebayShopList, workbook, "EBay"); ExcelHelper.SaveWorkbookToFile(workbook, ConfigSetting.SaveReceivedNonEBayReportFile);
示例代碼5-讀取一個(gè)標(biāo)題位置在第8行的標(biāo)題行數(shù)據(jù):
ExcelHelper.ReadTitleDataList<T>("文件路徑", new ExcelFileDescription(7))
示例代碼6-使用.net core API控制器方法返回文件流數(shù)據(jù): [Route("api/[controller]")] [ApiController] public class TestController : ControllerBase { public ExcelHelper ExcelHelper { get; set; } public TestController(ExcelHelper excelHelper) { this.ExcelHelper = excelHelper; } [HttpGet] [Route("")] public async Task<ActionResult> Test() { IWorkbook workbook = null; CommonCellModelColl accountCellColl = new CommonCellModelColl(10 * 10000); for (var i = 0; i < 10; i++) { accountCellColl.Add(new CommonCellModel(0, i, "第" + i + "列")); //標(biāo)題行數(shù)據(jù) } // 最后循環(huán)數(shù)據(jù)列: vList 循環(huán)加到結(jié)合中去。 int beginRowIndex = 2; List<dynamic> vList = new List<dynamic>(5); vList.Add(new { a = 2, b = 1 }); vList.Add(new { a = 2, b = 2 }); vList.Add(new { a = 2, b = 3 }); vList.Add(new { a = 3, b = 1 }); vList.Add(new { a = 3, b = 2 }); vList.Add(new { a = 3, b = 3 }); int objPropertyCount = 2; //這里需要用反射獲取 for (var i = 0; i < vList.Count; i++) { for (int j = 0; j < objPropertyCount; j++) { //值這里實(shí)際應(yīng)根據(jù)屬性反射獲取屬性值 int testValue = 0; if (j == 0) { testValue = ((dynamic)vList[i]).a; } else { testValue = ((dynamic)vList[i]).b; } accountCellColl.Add(new CommonCellModel(beginRowIndex, j, "測試數(shù)據(jù)" + testValue)); //內(nèi)容行數(shù)據(jù) } beginRowIndex++; } workbook = this.ExcelHelper.CreateOrUpdateWorkbook(accountCellColl, workbook, "sheet1"); //生成字節(jié)流 byte[] myFileByteArray = this.ExcelHelper.SaveWorkbookToByte(workbook); //設(shè)置導(dǎo)出文件名 this.Response.Headers.Add("content-disposition", $"attachment;filename=test.xls"); await this.Response.Body.WriteAsync(myFileByteArray, 0, myFileByteArray.Length); return Ok("success"); } }
|
|