前言: NPOI 技術在別人看來可能有點老生長談了,但是對於我現在處於的這個創業型公司,還是挺前沿的,不知道是前輩們不知道這個技術,還是懶得去對現有的軟體進行修改,因為在現有的軟體中,幾乎所有的數據導入導出都是依賴於: Excel.Application(設置excel組件,系統許可權,然後還得考慮版
前言:
NPOI 技術在別人看來可能有點老生長談了,但是對於我現在處於的這個創業型公司,還是挺前沿的,不知道是前輩們不知道這個技術,還是懶得去對現有的軟體進行修改,因為在現有的軟體中,幾乎所有的數據導入導出都是依賴於:
Excel.Application(設置excel組件,系統許可權,然後還得考慮版本一系列的問題)都是坑
基於現有的方法,之前的技術團隊在軟體沒有推廣之前可能自我感覺良好,沒有進行一些系統性的測試,在加上一些別的因素吧,導致在工程文件中對 Excel.Application 的操作方法,操作類層出不窮,算了,不揭短了。
有的時候向領導提出想對項目框架優化,或者對代碼的優化有所動作的時候,總會有層出不窮的原因導致這個動作漸漸的滯後。這隻是一個點,可想而知在沒有一個真正的技術經理參與的項目中,沒有對框架優化,方法重構的發起人,本來不是很複雜的項目,代碼的臃腫,堪憂。
算了,不吐槽了,可能是好久沒有寫博的原因。
數據輸出方法:
/// <summary> /// 攜帶數據導出 /// </summary> /// <param name="dtSource"></param> /// <param name="_excelName"></param> /// <param name="str_fieldtext"></param> public void export(DataTable dtSource, string _excelName, string str_fieldtext) { HttpContext curContext = HttpContext.Current; // 設置編碼和附件格式 curContext.Response.ContentType = "application/ms-excel"; curContext.Response.ContentEncoding = Encoding.UTF8; curContext.Response.Charset = ""; string fileName = _excelName + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls"; //Excel文件名稱 curContext.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName, Encoding.UTF8)); //調用導出具體方法Export() curContext.Response.BinaryWrite(Export(dtSource, _excelName, str_fieldtext).GetBuffer()); curContext.Response.End(); }
導出方法:
#region DataTable導出到Excel /// <summary> /// DataTable導出到Excel的MemoryStream Export() /// </summary> /// <param name="dtSource">DataTable數據源</param> /// <param name="strHeaderText">Excel表頭文本</param> /// <param name="str_fieldtext"></param> public static MemoryStream Export(DataTable dtSource, string strHeaderText, string str_fieldtext) { HSSFWorkbook workbook = new HSSFWorkbook(); ISheet sheet = workbook.CreateSheet("Data"); ISheet sheet2 = workbook.CreateSheet("ShtDictionary"); //sheet.DisplayGridlines = false;//隱藏網格線 #region 右擊文件 屬性信息 { DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); dsi.Company = "NPOI"; workbook.DocumentSummaryInformation = dsi; SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); si.Author = "文件作者信息"; //填加xls文件作者信息 si.ApplicationName = "創建程式信息"; //填加xls文件創建程式信息 si.LastAuthor = "最後保存者信息"; //填加xls文件最後保存者信息 si.Comments = "作者信息"; //填加xls文件作者信息 si.Title = "標題信息"; //填加xls文件標題信息 si.Subject = "主題信息";//填加文件主題信息 si.CreateDateTime = System.DateTime.Now; workbook.SummaryInformation = si; } #endregion ICellStyle dateStyle = workbook.CreateCellStyle(); IDataFormat format = workbook.CreateDataFormat(); dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd"); //取得列寬 int[] arrColWidth = new int[dtSource.Columns.Count]; foreach (DataColumn item in dtSource.Columns) { arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length; } for (int i = 0; i < dtSource.Rows.Count; i++) { for (int j = 0; j < dtSource.Columns.Count; j++) { int intTemp = Encoding.GetEncoding(936).GetBytes(dtSource.Rows[i][j].ToString()).Length; if (intTemp > arrColWidth[j]) { arrColWidth[j] = intTemp; } } } int rowIndex = 0; foreach (DataRow row in dtSource.Rows) { #region 新建表,填充表頭,填充列頭,樣式 if (rowIndex == 65535 || rowIndex == 0) { if (rowIndex != 0) { sheet = workbook.CreateSheet(); } #region 表頭及樣式 { //IRow headerRow = sheet.CreateRow(0); //headerRow.HeightInPoints = 25; //headerRow.CreateCell(0).SetCellValue(strHeaderText); //ICellStyle headStyle = workbook.CreateCellStyle(); //headStyle.Alignment = HorizontalAlignment.Center; //IFont font = workbook.CreateFont(); //font.FontHeightInPoints = 20; //font.Boldweight = 700; //headStyle.SetFont(font); //headerRow.GetCell(0).CellStyle = headStyle; //sheet.AddMergedRegion(new NPOI.SS.Util.CellRangeAddress(0, 0, 0, dtSource.Columns.Count - 1)); } #endregion #region 列頭及樣式 { IRow headerRow = sheet.CreateRow(0); ICellStyle headStyle = workbook.CreateCellStyle(); headStyle.Alignment = HorizontalAlignment.Center; IFont font = workbook.CreateFont(); font.FontHeightInPoints = 10; font.Boldweight = 700; headStyle.SetFont(font); headStyle.FillPattern = FillPattern.SolidForeground; headStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index2;//單元格背景色 HSSFPatriarch patr = sheet.CreateDrawingPatriarch() as HSSFPatriarch; HSSFClientAnchor a = new HSSFClientAnchor(); a.Dx1 = 0; a.Dy1 = 0; a.Dx2 = 0; a.Dy2 = 0; int colindex = 27; string[] str_text = { }; if (str_fieldtext.Length > 0) { str_text = str_fieldtext.Split(','); } foreach (DataColumn column in dtSource.Columns) { a.Col1 = column.Ordinal + 1;//批註起始位置的縱坐標(當前單元格位置+2) a.Col2 = column.Ordinal + 3;//批註結束位置的縱坐標 a.Row1 = column.Ordinal + 0;//批註起始位置的橫坐標 a.Row2 = column.Ordinal + 4;//批註結束位置的橫坐標 HSSFComment co = patr.CreateComment(a);//實例化批註模型 co.String = new HSSFRichTextString(Convert.ToString(column.ColumnName));//批註內容 co.Author = "大通軟體";//批註者 if (str_text.Length > 0) headerRow.CreateCell(column.Ordinal).SetCellValue(str_text[column.Ordinal]);//添加單元格內容 else headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName);//添加單元格內容 headerRow.GetCell(column.Ordinal).CellComment = co;//在該單元格是那個添加批註 headerRow.GetCell(column.Ordinal).CellStyle = headStyle;//給該單元格添加樣式 sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256);//設置列寬 #region 凍結 ///下麵對CreateFreezePane的參數作一下說明: ///第一個參數表示要凍結的列數; ///第二個參數表示要凍結的行數,這裡只凍結列所以為0; ///第三個參數表示右邊區域可見的首列序號,從1開始計算; ///第四個參數表示下邊區域可見的首行序號,也是從1開始計算,這裡是凍結列,所以為0; //sheet.CreateFreezePane(1, 0, 1, 0);//凍結首列 sheet.CreateFreezePane(0, 1, 0, 1);//凍結首行 #endregion #region 下拉 //if (column.Ordinal == 0) //{ // sheet2.CreateRow(0).CreateCell(0).SetCellValue("itemA"); // sheet2.CreateRow(1).CreateCell(0).SetCellValue("itemB"); // sheet2.CreateRow(2).CreateCell(0).SetCellValue("itemC"); //} //else //{ // sheet2.GetRow(0).CreateCell(column.Ordinal).SetCellValue("itemA" + column.Ordinal + ""); // sheet2.GetRow(1).CreateCell(column.Ordinal).SetCellValue("itemB" + column.Ordinal + ""); // sheet2.GetRow(2).CreateCell(column.Ordinal).SetCellValue("itemC" + column.Ordinal + ""); //} //string colname = string.Empty; //int remainder = 0; //remainder = colindex % 26; //if (remainder == 0) remainder = 26; //colname = Convert.ToString((char)(remainder + 64)); //IName range = workbook.CreateName(); //range.RefersToFormula = string.Format("{0}!$" + colname + "$1:$" + colname + "${1}", "ShtDictionary", 3); //range.NameName = "dicRange" + column.Ordinal + ""; //ISheet sheet1 = workbook.GetSheet("Data"); ////碰對了,第四個參數確定每次的下拉放到哪個column.Ordinal列,因缺思停 //CellRangeAddressList regions = new CellRangeAddressList(0, 65535, 0, column.Ordinal); //DVConstraint constraint = DVConstraint.CreateFormulaListConstraint("dicRange" + column.Ordinal + ""); //HSSFDataValidation dataValidate = new HSSFDataValidation(regions, constraint); //sheet1.AddValidationData(dataValidate); //colindex++; #endregion } } #endregion rowIndex = 1; } #endregion #region 填充內容 IRow dataRow = sheet.CreateRow(rowIndex); foreach (DataColumn column in dtSource.Columns) { ICell newCell = dataRow.CreateCell(column.Ordinal); string drValue = row[column].ToString(); switch (column.DataType.ToString()) { case "System.String"://字元串類型 newCell.SetCellValue(drValue); break; case "System.DateTime"://日期類型 System.DateTime dateV; System.DateTime.TryParse(drValue, out dateV); newCell.SetCellValue(dateV); newCell.CellStyle = dateStyle;//格式化顯示 break; case "System.Boolean"://布爾型 bool boolV = false; bool.TryParse(drValue, out boolV); newCell.SetCellValue(boolV); break; case "System.Int16"://整型 case "System.Int32": case "System.Int64": case "System.Byte": int intV = 0; int.TryParse(drValue, out intV); newCell.SetCellValue(intV); break; case "System.Decimal"://浮點型 case "System.Double": double doubV = 0; double.TryParse(drValue, out doubV); newCell.SetCellValue(doubV); break; case "System.DBNull"://空值處理 newCell.SetCellValue(""); break; default: newCell.SetCellValue(""); break; } } #endregion rowIndex++; } using (MemoryStream ms = new MemoryStream()) { workbook.Write(ms); ms.Flush(); ms.Position = 0; return ms; } } #endregion
讀取excel 數據:
/// <summary> /// 讀取excel ,預設第一行為標頭(獲取DataTable) /// </summary> /// <param name="strFileName">excel文檔路徑</param> /// <returns></returns> public DataTable Import(string strFileName) { DataTable dt = new DataTable(); HSSFWorkbook hssfworkbook; using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) { hssfworkbook = new HSSFWorkbook(file); } ISheet sheet = hssfworkbook.GetSheetAt(0); System.Collections.IEnumerator rows = sheet.GetRowEnumerator(); IRow headerRow = sheet.GetRow(0); int cellCount = headerRow.LastCellNum; for (int j = 0; j < cellCount; j++) { ICell cell = headerRow.GetCell(j); dt.Columns.Add(cell.ToString()); } for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++) { IRow row = sheet.GetRow(i); DataRow dataRow = dt.NewRow(); for (int j = row.FirstCellNum; j < cellCount; j++) { if (row.GetCell(j) != null) { if (row.GetCell(j).ToString().Contains('/')) { string[] a = row.GetCell(j).ToString().Split('/'); dataRow[j] = "20" + a[2] + "-" + a[0] + "-" + a[1]; } else { dataRow[j] = row.GetCell(j).ToString(); } } else { dataRow[j] = null; } } dt.Rows.Add(dataRow); } return dt; }
換一種方式:
/// <summary> /// 導出excel 模板 /// </summary> /// <param name="str_fieldid"></param> /// <param name="str_fieldtext"></param> /// <returns></returns> public void export(string _excelName, string str_fieldid, string str_fieldtext) { HSSFWorkbook workbook = new HSSFWorkbook(); ISheet sheet = workbook.CreateSheet("Data"); #region 右擊文件 屬性信息 { DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); dsi.Company = "NPOI"; workbook.DocumentSummaryInformation = dsi; SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); si.Author = "文件作者信息"; //填加xls文件作者信息 si.ApplicationName = "創建程式信息"; //填加xls文件創建程式信息 si.LastAuthor = "最後保存者信息"; //填加xls文件最後保存者信息 si.Comments = "作者信息"; //填加xls文件作者信息 si.Title = "標題信息"; //填加xls文件標題信息 si.Subject = "主題信息";//填加文件主題信息 si.CreateDateTime = System.DateTime.Now; workbook.SummaryInformation = si; } #endregion ICellStyle dateStyle = workbook.CreateCellStyle(); IDataFormat format = workbook.CreateDataFormat(); dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd"); int rowIndex = 0; #region 新建表,填充表頭,填充列頭,樣式 if (rowIndex == 65535 || rowIndex == 0) { if (rowIndex != 0) { sheet = workbook.CreateSheet(); } #region 列頭及樣式 { IRow headerRow = sheet.CreateRow(0); ICellStyle headStyle = workbook.CreateCellStyle(); headStyle.Alignment = HorizontalAlignment.Center; IFont font = workbook.CreateFont(); font.FontHeightInPoints = 10; font.Boldweight = 700; headStyle.SetFont(font); headStyle.FillPattern = FillPattern.SolidForeground; headStyle.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Yellow.Index2;//單元格背景色 HSSFPatriarch patr = sheet.CreateDrawingPatriarch() as HSSFPatriarch; HSSFClientAnchor a = new HSSFClientAnchor(); a.Dx1 = 0; a.Dy1 = 0; a.Dx2 = 0; a.Dy2 = 0; string[] str_text = { }; string[] str_field = { }; if (str_fieldtext.Length > 0) { str_text = str_fieldtext.Split(','); } if (str_fieldid.Length > 0) { str_field = str_fieldid.Split(','); } //取得列寬 int[] arrColWidth = new int[str_text.Length]; for (int i = 0; i < str_text.Length; i++) { a.Col1 = i + 1;//批註起始位置的縱坐標(當前單元格位置+2) a.Col2 = i + 3;//批註結束位置的縱坐標 a.Row1 = i + 0;//批註起始位置的橫坐標 a.Row2 = i + 4;//批註結束位置的橫坐標 HSSFComment co = patr.CreateComment(a);//實例化批註模型 co.String = new HSSFRichTextString(Convert.ToString(str_field[i]));//批註內容 co.Author = "大通軟體";//批註者 if (str_text.Length > 0) headerRow.CreateCell(i).SetCellValue(str_text[i]);//添加單元格內容 else headerRow.CreateCell(i).SetCellValue(str_field[i]);//添加單元格內容 headerRow.GetCell(i).CellComment = co;//在該單元格是那個添加批註 headerRow.GetCell(i).CellStyle = headStyle;//給該單元格添加樣式 sheet.SetColumnWidth(i, 20 * 256);//設置列寬 //sheet.SetColumnWidth(i, 250); #region 凍結 sheet.CreateFreezePane(0, 1, 0, 1);//凍結首行 #endregion } } #endregion rowIndex = 1; } #endregion using (MemoryStream ms = new MemoryStream()) { workbook.Write(ms); ms.Flush(); ms.Position = 0; ExportOut(ms, _excelName); } } /// <summary> /// 輸出方法 /// </summary> /// <param name="ms"></param> /// <param name="_excelName"></param> public void ExportOut(MemoryStream ms, string _excelName) { HttpContext curContext = HttpContext.Current; // 設置編碼和附件格式 curContext.Response.ContentType = "application/ms-excel"; curContext.Response.ContentEncoding = Encoding.UTF8; curContext.Response.Charset = ""; string fileName = _excelName + DateTime.Now.ToString("yyyyMMddHHmmss") + ".xls"; //Excel文件名稱 curContext.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(fileName, Encoding.UTF8)); //調用導出具體方法Export() curContext.Response.BinaryWrite(ms.GetBuffer()); curContext.Response.End(); }
NPOI組件: http://files.cnblogs.com/files/houlin/NPOI.zip
後言:
以上就是一些方法來自園子里好多前輩的博文,我自己沒有做什麼優化,目前只做記錄,備忘,不喜勿噴。