【2010-12-16】基于NPOI的打开/导出Excel文件操作类

 

在很久之前我应该是写过一次关于Excel的导入导出的文章的,那时候是直接使用OFFICE的组件,后来遇到进程的问题,改为使用第三方Aspose.Cells,但这是一个收费的组件,最近在开源中国中看到开源项目NPOI,所以今天把Aspose.Cells替换掉,改成NPOI。

NPOI目前应该说没有Aspose.Cells强大的,比如说现在日渐盛行的OFFICE 2007,NPOI还不支持,有些操作也不如Aspose.Cells来的方便。但是我曾经把两者比较过,打开Excel文件的话,Aspose.Cells会快大概1-3秒左右,导出的话NPOI反而比Aspose.Cells快上05-2秒左右(导出的过程逻辑是一样的,我只是把用到Aspose.Cells的地方都换成NPOI的操作),当然这里的比较仅仅是提供参考。

Aspose.Cells,我感觉其实就是封装了好些常用的操作,比如说打开文件并导入一个DataTable里,在Aspose.Cells是已经封装好的方法,而在NPOI是需要自己做的。两者应该是各有各的优势的,但是毕竟Aspose.Cells是收费的,估计愿意出钱的不多,而且要用全部功能的也不多,而NPOI免费而且开源,况且我仅仅是做一些简单的导入导出而已。

因为是类库,没什么图片上,上代码:

 

///

/// 打开指定EXCEL文件并导入到指定的DataTable中。DataTable必须先建立相应数据列。 /// /// 文件路径 /// 工作表名称 /// 第一行 /// 第一列 /// 指定的DataTable public static Boolean OpenExcelFile(String FilePath, String SheetName, Int32 FirstRow, Int32 FirstCol , ref DataTable InDataTable) { Boolean iExistsSheet = false; Int32 iSheetIndex=0; errMeg = ""; if (File.Exists(FilePath) == false) { errMeg = "指定的文件不存在!"; return false; } HSSFWorkbook iMyWorkbook = null; using (Stream iExcelFile = File.Open(FilePath, FileMode.Open, FileAccess.Read)) { if (CheckIsExcel03File(iExcelFile) == false) { errMeg = "指定的文件并非Excle2003或其以下版本!"; return false; } iMyWorkbook = new HSSFWorkbook(iExcelFile); } if (iMyWorkbook == null) { errMeg = "打开指定的文件出错!"; return false; } for (int i = 0; i < iMyWorkbook.NumberOfSheets; i++) { if (iMyWorkbook.GetSheetName(i) == SheetName) { iExistsSheet = true; iSheetIndex=i; break; } } if (iExistsSheet == false) { errMeg = "指定的工作表不存在!"; if (iMyWorkbook != null) { iMyWorkbook.Dispose(); } return false; } HSSFSheet iSheet = (HSSFSheet)iMyWorkbook.GetSheetAt(iSheetIndex); IEnumerator iRows = iSheet.GetRowEnumerator(); for (Int32 ii = FirstRow; ii <= iSheet.LastRowNum; ii++) { HSSFRow iRow = (HSSFRow)iSheet.GetRow(ii); if (iRow == null) { continue; } Int32 iDataColIndes = 0; DataRow iDataRow = InDataTable.NewRow(); for (Int32 iii = FirstCol; iii < iRow.LastCellNum; iii++) { HSSFCell iCell = (HSSFCell)iRow.GetCell(iii); if (iCell == null) { iDataRow = null; break; } if (InDataTable.Columns[iDataColIndes] == null) { iDataRow = null; break; } if (iCell.CellType == CellType.BLANK || iCell.CellType == CellType.Unknown) { if (!InDataTable.Columns[iDataColIndes].AllowDBNull) { iDataRow = null; break; } } switch (Type.GetTypeCode(InDataTable.Columns[iDataColIndes].DataType)) { case TypeCode.Boolean: { if (iCell.CellType != CellType.BOOLEAN) { iDataRow = null; break; } iDataRow[iDataColIndes] = iCell.BooleanCellValue; break; } case TypeCode.Char: { if (iCell.CellType != CellType.STRING) { iDataRow = null; break; } iDataRow[iDataColIndes] = iCell.StringCellValue[0]; break; } case TypeCode.DateTime: { if (iCell.CellType != CellType.NUMERIC) { iDataRow = null; break; } iDataRow[iDataColIndes] = iCell.DateCellValue; break; } case TypeCode.Decimal: { if (iCell.CellType != CellType.NUMERIC) { iDataRow = null; break; } Decimal iCellValue = (Decimal)iCell.NumericCellValue; if (iCellValue > Decimal.MaxValue || iCellValue < Decimal.MinValue) { iDataRow = null; break; } iDataRow[iDataColIndes] = iCellValue; break; } case TypeCode.Double: { if (iCell.CellType != CellType.NUMERIC) { iDataRow = null; break; } if (iCell.NumericCellValue > Double.MaxValue || iCell.NumericCellValue < Double.MinValue) { iDataRow = null; break; } iDataRow[iDataColIndes] = iCell.NumericCellValue; break; } case TypeCode.Int16: { if (iCell.CellType != CellType.NUMERIC) { iDataRow = null; break; } Int16 iCellValue = (Int16)iCell.NumericCellValue; if (iCellValue > Int16.MaxValue || iCellValue < Int16.MinValue) { iDataRow = null; break; } iDataRow[iDataColIndes] = iCellValue; break; } case TypeCode.Int32: { if (iCell.CellType != CellType.NUMERIC) { iDataRow = null; break; } Int32 iCellValue = (Int32)iCell.NumericCellValue; if (iCellValue > Int32.MaxValue || iCellValue < Int32.MinValue) { iDataRow = null; break; } iDataRow[iDataColIndes] = iCellValue; break; } case TypeCode.Int64: { if (iCell.CellType != CellType.NUMERIC) { iDataRow = null; break; } Int64 iCellValue = (Int64)iCell.NumericCellValue; if (iCellValue > Int64.MaxValue || iCellValue < Int64.MinValue) { iDataRow = null; break; } iDataRow[iDataColIndes] = iCellValue; break; } case TypeCode.String: { iDataRow[iDataColIndes] = iCell.StringCellValue; break; } } if (iDataRow == null) { break; } iDataColIndes++; } if (iDataRow != null) { InDataTable.Rows.Add(iDataRow); } } if (iSheet != null) { iSheet.Dispose(); } if (iMyWorkbook != null) { iMyWorkbook.Dispose(); } return true; } 

 

以上是打开一个Excel文件。

 

 

///

/// 导出到EXCEL文件 /// /// 需要导出的相关 /// 导出的全路径 /// 成功则返回true,出错,即使是一条数据出错都返回false public static Boolean ExportExcelFile(C_ExpInfo MyExpData, String FilePath) { errMeg = ""; Boolean iRetbool = true; List iMySheetNameList = new List();//记录已经存在的工作表,防止重复。 Dictionary iSeleColName = new Dictionary(); Int32 iMyUserRow = 0; if ((!(MyExpData.ExpData.Tables.Contains("AllInfo"))) || (!(MyExpData.ExpData.Tables.Contains("ExpSheets")))) { errMeg = "导出的表集内缺少必需表(AllInfo、ExpSheets)"; return false; } DataTable iExpSheetsDataTable = MyExpData.ExpData.Tables["ExpSheets"]; DataTable iAllInfoDataTable = MyExpData.ExpData.Tables["AllInfo"]; if (iExpSheetsDataTable.Rows.Count <= 0) { errMeg = "没有需要导出的数据信息"; return false; } int iExpDataRowCount = iExpSheetsDataTable.Rows.Count; HSSFWorkbook iMyWorkB = new HSSFWorkbook(); Frm_Schedule iMyFrm_Schedule = new Frm_Schedule(); for (int i = 0; i < iExpDataRowCount; i++) { HSSFSheet iMySheet = null; DataRow[] iMyExpInfo = null; String iMyDataName = ""; String iMySheetName = ""; DataTable iCurrentDataTable = null; #region 准备数据 try { iMySheetName = iExpSheetsDataTable.Rows[i]["ExpSheetName"].ToString();//导出EXCEL表的表名 iMyDataName = iExpSheetsDataTable.Rows[i]["ExpDataName"].ToString();//导出的数据表名 Int32 iExpID = (Int32)iExpSheetsDataTable.Rows[i]["ExpID"];//导出的ID(用对应AllInfo的ID) Boolean iIfUserSele = (Boolean)iExpSheetsDataTable.Rows[i]["IfUserSele"]; if ((!MyExpData.ExpData.Tables.Contains(iMyDataName))) { errMeg = "不存在需要导出的数据表!(" + iMyDataName + ")"; iRetbool = false; continue; } iCurrentDataTable = MyExpData.ExpData.Tables[iMyDataName]; if (iCurrentDataTable.Rows.Count == 0) { continue; } if (iMySheetNameList.Contains(iMySheetName)) { continue; } else { iMySheetNameList.Add(iMySheetName); } int iExpDataCount = iCurrentDataTable.Rows.Count; if (iIfUserSele) { Frm_SeleCol iMyFrm_SeleCol = new Frm_SeleCol(MyExpData.ClumnName); if (iMyFrm_SeleCol.ShowDialog() == System.Windows.Forms.DialogResult.OK) { iSeleColName = iMyFrm_SeleCol.MySeleCol; } iMyFrm_SeleCol.Close(); } if (iSeleColName.Count == 0) { continue; } iMyFrm_Schedule.Init(iExpDataCount); iMyFrm_Schedule.Visible = true; iMySheet = (HSSFSheet)iMyWorkB.CreateSheet(iMySheetName); iMyExpInfo = iAllInfoDataTable.Select("ID=" + iExpID.ToString()); } catch (Exception iErr_ZhB) { errMeg += "准备第 " + i.ToString() + " 个表数据时出错!" + iErr_ZhB.Message; iRetbool = false; continue; } #endregion #region 表附加设计 try { foreach (DataRow iMyInfoRow in iMyExpInfo) { Boolean iIfRag = (Boolean)iMyInfoRow["IfRag"]; Boolean iIfAutoCol = (Boolean)iMyInfoRow["IfAutoCol"];//标识该合并单元格是否使用自动取列数 Int32 iCellRowIndex = (Int32)iMyInfoRow["RowNum_B"]; Int32 iCellColIndex = (Int32)iMyInfoRow["ColNum_B"]; HSSFRow iCellRow = (HSSFRow)iMySheet.GetRow(iCellRowIndex); if (iCellRow == null) { iCellRow = (HSSFRow)iMySheet.CreateRow(iCellRowIndex); } HSSFCell iCell = (HSSFCell)iCellRow.GetCell(iCellColIndex); if (iCell == null) { iCell = (HSSFCell)iCellRow.CreateCell(iCellColIndex, CellType.STRING); } iCell.SetCellValue(iMyInfoRow["Text"].ToString()); HSSFCellStyle iCellStyle = (HSSFCellStyle)iMyWorkB.CreateCellStyle(); iCellStyle.Alignment = HorizontalAlignment.CENTER; HSSFFont iCellFont = (HSSFFont)iMyWorkB.CreateFont(); short iFontSize=(short)iMyInfoRow["Fonts"]; iCellFont.FontHeight = (short)(iFontSize * iFontSize); iCellStyle.SetFont(iCellFont); iCell.CellStyle = iCellStyle; if (iIfRag) { Int32 iRegionColCount = 0; Int32 iRegionRowCount = (Int32)iMyInfoRow["RowSum"]; if (iIfAutoCol) { iRegionColCount = iSeleColName.Count; } else { iRegionColCount = (Int32)iMyInfoRow["ColSum"]; } iMySheet.AddMergedRegion(new CellRangeAddress(iCellRowIndex, (iCellRowIndex + iRegionRowCount - 1) , iCellColIndex, (iCellColIndex + iRegionColCount - 1))); if (iMyUserRow < iCellRowIndex + iRegionRowCount) { iMyUserRow = iCellRowIndex + iRegionRowCount; } } else { if (iMyUserRow < iCellRowIndex) { iMyUserRow = iCellRowIndex; } } } } catch (Exception iErr_Bfj) { errMeg += "导出第 " + i.ToString() + " 个表表头时出错!" + iErr_Bfj.Message; iRetbool = false; continue; } #endregion #region 导出数据 try { Int32 iCurrColNum = 0; for (Int32 a = 0; a < iCurrentDataTable.Columns.Count; a++) { String iMyColName = iCurrentDataTable.Columns[a].ColumnName; if (iSeleColName.ContainsKey(iMyColName)) { HSSFRow iRowHand = (HSSFRow)iMySheet.GetRow(iMyUserRow); if (iRowHand == null) { iRowHand = (HSSFRow)iMySheet.CreateRow(iMyUserRow); } HSSFCell iCellHand = (HSSFCell)iRowHand.GetCell(iCurrColNum); if (iCellHand == null) { iCellHand = (HSSFCell)iRowHand.CreateCell(iCurrColNum, CellType.STRING); } iCellHand.SetCellValue(iSeleColName[iMyColName]); iCurrColNum++; } } iMyUserRow++; for (int b = 0; b < iCurrentDataTable.Rows.Count; b++) { iCurrColNum = 0; for (int c = 0; c < iCurrentDataTable.Columns.Count; c++) { if (iSeleColName.ContainsKey(iCurrentDataTable.Columns[c].ColumnName)) { HSSFRow iRowValue = (HSSFRow)iMySheet.GetRow(iMyUserRow); if (iRowValue == null) { iRowValue = (HSSFRow)iMySheet.CreateRow(iMyUserRow); } HSSFCell iCellValue = (HSSFCell)iRowValue.GetCell(iCurrColNum); if (iCellValue == null) { iCellValue = (HSSFCell)iRowValue.CreateCell(iCurrColNum, CellType.STRING); } iCellValue.SetCellValue(iCurrentDataTable.Rows[b][c].ToString()); iCurrColNum++; } } if (iMyUserRow > MyExpData.MaxRow) break; iMyUserRow++; iMyFrm_Schedule.ChValue(); } } catch (Exception iErr_DCh) { errMeg += "导出第 " + i.ToString() + " 个表数据时出错!" + iErr_DCh.Message; iRetbool = false; continue; } #endregion } iMyFrm_Schedule.Close(); try { using (FileStream iFile = new FileStream(FilePath, FileMode.Create, FileAccess.Write)) { iMyWorkB.Write(iFile); } } catch (Exception Err) { errMeg = "保存文件出错!" + Err.Message; return false; } iMyWorkB.Dispose(); return iRetbool; } 

 

以上是导出到Excel,里面用了自己定义的一个类,用来放一些导出的一些设置和数据。里面用DataSet来放相关设置和数据,主要考虑到一次多出多个文件。

 

 

因为NPOI目前还不支持office2007,所以有必要做一下文件的判断,其实NPOI的源码里也有这个判断的,但是自己先判断一下,不符合的直接不打开。

///

/// 检查指定文件是否03或以下版本 /// /// 文件路径 /// public static Boolean CheckIsExcel03File(Stream File) { if (File == null) { return false; } BinaryReader iFileReader = new BinaryReader(File); ulong iTempNum = iFileReader.ReadUInt64(); Int32 iTempNum2 = (Int32)(iTempNum & ((ulong)0xffffL)); File.Seek(-8L, SeekOrigin.Current); if (iTempNum == 16220472316735377360L) { iFileReader.Close(); return true; } iFileReader.Close(); return false; } 

 

项目源码:http://download.csdn.net/source/2912158

 

你可能感兴趣的:(C#相关)