本文轉自:http://www.cnblogs.com/yongfa365/archive/2010/05/10/NPOI-MyXls-DataTable-To-Excel-From-Excel.html
Excel導入及導出問題產生: 從接觸.net到現在一直在維護一個DataTable導出到Excel的類,時不時還會維護一個導入類。以下是時不時就會出現的問題: 導出問題: 如果是asp.net,你得在服務器端裝Office,幾百M呢,還得及時更新它,以防漏洞,還得設定權限允許ASP.net訪問COM+,聽說如果導出過程中出問題可能導致服務器宕機。 Excel會把只包含數字的列進行類型轉換,本來是文本型的,它非要把你轉成數值型的,像身份證后三位變成000,編號000123會變成123,夠智能吧,夠郁悶吧。不過這些都還是可以變通解決的,在他們前邊加上一個字母,讓他們不只包含數字。 導出時,如果你的字段內容以"-"或"="開頭,Excel好像把它當成了公式什么的,接下來就出錯,提示:類似,保存到Sheet1的問題 導入問題: Excel會根據你的 Excel文件前8行分析數據類型,如果正好你前8行某一列只是數字,那它會認為你這一列就是數值型的,然后,身份證,手機,編號都轉吧變成類似這樣的1.42702E+17格式,日期列變成 包含日期和數字的,亂的很,可以通過改注冊表讓Excel分析整個表,但如果整列都是數字,那這個問題還是解決不了。 以上問題,一般人初次做時肯定得上網查查吧,一個問題接着另一個問題,查到你郁郁而死,還有很多問題沒解決,最終感覺已經解決的不錯了,但還不能保證某一天還會出個什么問題。 使用第三方開源組件導入及導出Excel的解決方案: 偶然間發現了NPOI與MyXls,相見恨晚,害的我在Excel上浪費了那么多時間,他們倆的好處是:就是.net的自定義類庫,可以直接對Excel進行讀或寫,而不依賴Office 的 Excel,這不管對於ASP.net或Winform都非常有利,不用擔心Excel進程的釋放問題,服務器安全,設置,導出,導入“Excel智能識別”,公式日期等問題,可以說以前的Excel問題,全都不用管了,它們可以很好的幫你解決,NPOI || MyXls == 研究幾年Excel。 NPOI開源地址:http://npoi.codeplex.com/ NPOI中文文檔:http://www.cnblogs.com/tonyqus/archive/2009/04/12/1434209.html MyXls開源地址:http://sourceforge.net/projects/myxls/ 下面來兩個簡單入門例子: MyXls 快速入門例子: 1 /// <summary> 2 /// MyXls簡單Demo,快速入門代碼 3 /// </summary> 4 /// <param name="dtSource"></param> 5 /// <param name="strFileName"></param> 6 /// <remarks>MyXls認為Excel的第一個單元格是:(1,1)</remarks> 7 /// <Author>柳永法 http://www.yongfa365.com/ 2010-5-8 22:21:41</Author> 8 public static void ExportEasy(DataTable dtSource, string strFileName) 9 { 10 XlsDocument xls = new XlsDocument(); 11 Worksheet sheet = xls.Workbook.Worksheets.Add("Sheet1"); 12 13 //填充表頭 14 foreach (DataColumn col in dtSource.Columns) 15 { 16 sheet.Cells.Add(1, col.Ordinal + 1, col.ColumnName); 17 } 18 19 //填充內容 20 for (int i = 0; i < dtSource.Rows.Count; i++) 21 { 22 for (int j = 0; j < dtSource.Columns.Count; j++) 23 { 24 sheet.Cells.Add(i + 2, j + 1, dtSource.Rows[i][j].ToString()); 25 } 26 } 27 28 //保存 29 xls.FileName = strFileName; 30 xls.Save(); 31 } NPOI 快速入門例子: 1 /// <summary> 2 /// NPOI簡單Demo,快速入門代碼 3 /// </summary> 4 /// <param name="dtSource"></param> 5 /// <param name="strFileName"></param> 6 /// <remarks>NPOI認為Excel的第一個單元格是:(0,0)</remarks> 7 /// <Author>柳永法 http://www.yongfa365.com/ 2010-5-8 22:21:41</Author> 8 public static void ExportEasy(DataTable dtSource, string strFileName) 9 { 10 HSSFWorkbook workbook = new HSSFWorkbook(); 11 HSSFSheet sheet = workbook.CreateSheet(); 12 13 //填充表頭 14 HSSFRow dataRow = sheet.CreateRow(0); 15 foreach (DataColumn column in dtSource.Columns) 16 { 17 dataRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); 18 } 19 20 21 //填充內容 22 for (int i = 0; i < dtSource.Rows.Count; i++) 23 { 24 dataRow = sheet.CreateRow(i + 1); 25 for (int j = 0; j < dtSource.Columns.Count; j++) 26 { 27 dataRow.CreateCell(j).SetCellValue(dtSource.Rows[i][j].ToString()); 28 } 29 } 30 31 32 //保存 33 using (MemoryStream ms = new MemoryStream()) 34 { 35 using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)) 36 { 37 workbook.Write(fs); 38 } 39 } 40 workbook.Dispose(); 41 } 接下來是柳永法(yongfa365)'Blog封裝的可以用在實際項目中的類,實現的功能有(僅NPOI): 1.支持web及winform從DataTable導出到Excel。 2.生成速度很快。 3.准確判斷數據類型,不會出現身份證轉數值等上面提到的一系列問題。 4.如果單頁條數大於65535時會新建工作表。 5.列寬自適應。 6.支持讀取Excel。 7.調用方便,只一調用一個靜態類就OK了。 8.因為測試期間發現MyXls導出速度要比NPOI慢3倍,而NPOI既能滿足我們的導出需求,又能很好的滿足我們的導入需求,所以只針對NPOI進行全方位功能實現及優化。 MyXls導出相關類: 1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using org.in2bits.MyXls; 6 using org.in2bits.MyXls.ByteUtil; 7 using System.Data; 8 9 class ExcelHelper 10 { 11 public static void Export(DataTable dtSource, string strHeaderText, string strFileName) 12 { 13 XlsDocument xls = new XlsDocument(); 14 xls.FileName = DateTime.Now.ToString("yyyyMMddHHmmssffff", System.Globalization.DateTimeFormatInfo.InvariantInfo); 15 xls.SummaryInformation.Author = "yongfa365"; //填加xls文件作者信息 16 xls.SummaryInformation.NameOfCreatingApplication = "liu yongfa"; //填加xls文件創建程序信息 17 xls.SummaryInformation.LastSavedBy = "LastSavedBy"; //填加xls文件最后保存者信息 18 xls.SummaryInformation.Comments = "Comments"; //填加xls文件作者信息 19 xls.SummaryInformation.Title = "title"; //填加xls文件標題信息 20 xls.SummaryInformation.Subject = "Subject";//填加文件主題信息 21 xls.DocumentSummaryInformation.Company = "company";//填加文件公司信息 22 23 24 Worksheet sheet = xls.Workbook.Worksheets.Add("Sheet1");//狀態欄標題名稱 25 Cells cells = sheet.Cells; 26 27 foreach (DataColumn col in dtSource.Columns) 28 { 29 Cell cell = cells.Add(1, col.Ordinal + 1, col.ColumnName); 30 cell.Font.FontFamily = FontFamilies.Roman; //字體 31 cell.Font.Bold = true; //字體為粗體 32 33 } 34 #region 填充內容 35 XF dateStyle = xls.NewXF(); 36 dateStyle.Format = "yyyy-mm-dd"; 37 38 for (int i = 0; i < dtSource.Rows.Count; i++) 39 { 40 for (int j = 0; j < dtSource.Columns.Count; j++) 41 { 42 43 int rowIndex = i + 2; 44 int colIndex = j + 1; 45 string drValue = dtSource.Rows[i][j].ToString(); 46 47 switch (dtSource.Rows[i][j].GetType().ToString()) 48 { 49 case "System.String"://字符串類型 50 cells.Add(rowIndex, colIndex, drValue); 51 break; 52 case "System.DateTime"://日期類型 53 DateTime dateV; 54 DateTime.TryParse(drValue, out dateV); 55 cells.Add(rowIndex, colIndex, dateV, dateStyle); 56 break; 57 case "System.Boolean"://布爾型 58 bool boolV = false; 59 bool.TryParse(drValue, out boolV); 60 cells.Add(rowIndex, colIndex, boolV); 61 break; 62 case "System.Int16"://整型 63 case "System.Int32": 64 case "System.Int64": 65 case "System.Byte": 66 int intV = 0; 67 int.TryParse(drValue, out intV); 68 cells.Add(rowIndex, colIndex, intV); 69 break; 70 case "System.Decimal"://浮點型 71 case "System.Double": 72 double doubV = 0; 73 double.TryParse(drValue, out doubV); 74 cells.Add(rowIndex, colIndex, doubV); 75 break; 76 case "System.DBNull"://空值處理 77 cells.Add(rowIndex, colIndex, null); 78 break; 79 default: 80 cells.Add(rowIndex, colIndex, null); 81 break; 82 } 83 } 84 } 85 86 #endregion 87 88 xls.FileName = strFileName; 89 xls.Save(); 90 } 91 } 92 NPOI導入導出相關類: 1 using System; 2 using System.Collections.Generic; 3 using System.Data; 4 using System.IO; 5 using System.Text; 6 using System.Web; 7 using NPOI; 8 using NPOI.HPSF; 9 using NPOI.HSSF; 10 using NPOI.HSSF.UserModel; 11 using NPOI.HSSF.Util; 12 using NPOI.POIFS; 13 using NPOI.Util; 14 15 16 public class ExcelHelper 17 { 18 /// <summary> 19 /// DataTable導出到Excel文件 20 /// </summary> 21 /// <param name="dtSource">源DataTable</param> 22 /// <param name="strHeaderText">表頭文本</param> 23 /// <param name="strFileName">保存位置</param> 24 /// <Author>柳永法 http://www.yongfa365.com/ 2010-5-8 22:21:41</Author> 25 public static void Export(DataTable dtSource, string strHeaderText, string strFileName) 26 { 27 using (MemoryStream ms = Export(dtSource, strHeaderText)) 28 { 29 using (FileStream fs = new FileStream(strFileName, FileMode.Create, FileAccess.Write)) 30 { 31 byte[] data = ms.ToArray(); 32 fs.Write(data, 0, data.Length); 33 fs.Flush(); 34 } 35 } 36 } 37 38 /// <summary> 39 /// DataTable導出到Excel的MemoryStream 40 /// </summary> 41 /// <param name="dtSource">源DataTable</param> 42 /// <param name="strHeaderText">表頭文本</param> 43 /// <Author>柳永法 http://www.yongfa365.com/ 2010-5-8 22:21:41</Author> 44 public static MemoryStream Export(DataTable dtSource, string strHeaderText) 45 { 46 HSSFWorkbook workbook = new HSSFWorkbook(); 47 HSSFSheet sheet = workbook.CreateSheet(); 48 49 #region 右擊文件 屬性信息 50 { 51 DocumentSummaryInformation dsi = PropertySetFactory.CreateDocumentSummaryInformation(); 52 dsi.Company = "http://www.yongfa365.com/"; 53 workbook.DocumentSummaryInformation = dsi; 54 55 SummaryInformation si = PropertySetFactory.CreateSummaryInformation(); 56 si.Author = "柳永法"; //填加xls文件作者信息 57 si.ApplicationName = "NPOI測試程序"; //填加xls文件創建程序信息 58 si.LastAuthor = "柳永法2"; //填加xls文件最后保存者信息 59 si.Comments = "說明信息"; //填加xls文件作者信息 60 si.Title = "NPOI測試"; //填加xls文件標題信息 61 si.Subject = "NPOI測試Demo";//填加文件主題信息 62 si.CreateDateTime = DateTime.Now; 63 workbook.SummaryInformation = si; 64 } 65 #endregion 66 67 HSSFCellStyle dateStyle = workbook.CreateCellStyle(); 68 HSSFDataFormat format = workbook.CreateDataFormat(); 69 dateStyle.DataFormat = format.GetFormat("yyyy-mm-dd"); 70 71 //取得列寬 72 int[] arrColWidth = new int[dtSource.Columns.Count]; 73 foreach (DataColumn item in dtSource.Columns) 74 { 75 arrColWidth[item.Ordinal] = Encoding.GetEncoding(936).GetBytes(item.ColumnName.ToString()).Length; 76 } 77 for (int i = 0; i < dtSource.Rows.Count; i++) 78 { 79 for (int j = 0; j < dtSource.Columns.Count; j++) 80 { 81 int intTemp = Encoding.GetEncoding(936).GetBytes(dtSource.Rows[i][j].ToString()).Length; 82 if (intTemp > arrColWidth[j]) 83 { 84 arrColWidth[j] = intTemp; 85 } 86 } 87 } 88 89 90 91 int rowIndex = 0; 92 93 foreach (DataRow row in dtSource.Rows) 94 { 95 #region 新建表,填充表頭,填充列頭,樣式 96 if (rowIndex == 65535 || rowIndex == 0) 97 { 98 if (rowIndex != 0) 99 { 100 sheet = workbook.CreateSheet(); 101 } 102 103 #region 表頭及樣式 104 { 105 HSSFRow headerRow = sheet.CreateRow(0); 106 headerRow.HeightInPoints = 25; 107 headerRow.CreateCell(0).SetCellValue(strHeaderText); 108 109 HSSFCellStyle headStyle = workbook.CreateCellStyle(); 110 headStyle.Alignment = CellHorizontalAlignment.CENTER; 111 HSSFFont font = workbook.CreateFont(); 112 font.FontHeightInPoints = 20; 113 font.Boldweight = 700; 114 headStyle.SetFont(font); 115 116 headerRow.GetCell(0).CellStyle = headStyle; 117 118 sheet.AddMergedRegion(new Region(0, 0, 0, dtSource.Columns.Count - 1)); 119 headerRow.Dispose(); 120 } 121 #endregion 122 123 124 #region 列頭及樣式 125 { 126 HSSFRow headerRow = sheet.CreateRow(1); 127 128 129 HSSFCellStyle headStyle = workbook.CreateCellStyle(); 130 headStyle.Alignment = CellHorizontalAlignment.CENTER; 131 HSSFFont font = workbook.CreateFont(); 132 font.FontHeightInPoints = 10; 133 font.Boldweight = 700; 134 headStyle.SetFont(font); 135 136 137 foreach (DataColumn column in dtSource.Columns) 138 { 139 headerRow.CreateCell(column.Ordinal).SetCellValue(column.ColumnName); 140 headerRow.GetCell(column.Ordinal).CellStyle = headStyle; 141 142 //設置列寬 143 sheet.SetColumnWidth(column.Ordinal, (arrColWidth[column.Ordinal] + 1) * 256); 144 145 } 146 headerRow.Dispose(); 147 } 148 #endregion 149 150 rowIndex = 2; 151 } 152 #endregion 153 154 155 #region 填充內容 156 HSSFRow dataRow = sheet.CreateRow(rowIndex); 157 foreach (DataColumn column in dtSource.Columns) 158 { 159 HSSFCell newCell = dataRow.CreateCell(column.Ordinal); 160 161 string drValue = row[column].ToString(); 162 163 switch (column.DataType.ToString()) 164 { 165 case "System.String"://字符串類型 166 newCell.SetCellValue(drValue); 167 break; 168 case "System.DateTime"://日期類型 169 DateTime dateV; 170 DateTime.TryParse(drValue, out dateV); 171 newCell.SetCellValue(dateV); 172 173 newCell.CellStyle = dateStyle;//格式化顯示 174 break; 175 case "System.Boolean"://布爾型 176 bool boolV = false; 177 bool.TryParse(drValue, out boolV); 178 newCell.SetCellValue(boolV); 179 break; 180 case "System.Int16"://整型 181 case "System.Int32": 182 case "System.Int64": 183 case "System.Byte": 184 int intV = 0; 185 int.TryParse(drValue, out intV); 186 newCell.SetCellValue(intV); 187 break; 188 case "System.Decimal"://浮點型 189 case "System.Double": 190 double doubV = 0; 191 double.TryParse(drValue, out doubV); 192 newCell.SetCellValue(doubV); 193 break; 194 case "System.DBNull"://空值處理 195 newCell.SetCellValue(""); 196 break; 197 default: 198 newCell.SetCellValue(""); 199 break; 200 } 201 202 } 203 #endregion 204 205 rowIndex++; 206 } 207 208 209 using (MemoryStream ms = new MemoryStream()) 210 { 211 workbook.Write(ms); 212 ms.Flush(); 213 ms.Position = 0; 214 215 sheet.Dispose(); 216 //workbook.Dispose();//一般只用寫這一個就OK了,他會遍歷並釋放所有資源,但當前版本有問題所以只釋放sheet 217 return ms; 218 } 219 220 } 221 222 223 /// <summary> 224 /// 用於Web導出 225 /// </summary> 226 /// <param name="dtSource">源DataTable</param> 227 /// <param name="strHeaderText">表頭文本</param> 228 /// <param name="strFileName">文件名</param> 229 /// <Author>柳永法 http://www.yongfa365.com/ 2010-5-8 22:21:41</Author> 230 public static void ExportByWeb(DataTable dtSource, string strHeaderText, string strFileName) 231 { 232 233 HttpContext curContext = HttpContext.Current; 234 235 // 設置編碼和附件格式 236 curContext.Response.ContentType = "application/vnd.ms-excel"; 237 curContext.Response.ContentEncoding = Encoding.UTF8; 238 curContext.Response.Charset = ""; 239 curContext.Response.AppendHeader("Content-Disposition", 240 "attachment;filename=" + HttpUtility.UrlEncode(strFileName, Encoding.UTF8)); 241 242 curContext.Response.BinaryWrite(Export(dtSource, strHeaderText).GetBuffer()); 243 curContext.Response.End(); 244 245 } 246 247 248 /// <summary>讀取excel 249 /// 默認第一行為標頭 250 /// </summary> 251 /// <param name="strFileName">excel文檔路徑</param> 252 /// <returns></returns> 253 public static DataTable Import(string strFileName) 254 { 255 DataTable dt = new DataTable(); 256 257 HSSFWorkbook hssfworkbook; 258 using (FileStream file = new FileStream(strFileName, FileMode.Open, FileAccess.Read)) 259 { 260 hssfworkbook = new HSSFWorkbook(file); 261 } 262 HSSFSheet sheet = hssfworkbook.GetSheetAt(0); 263 System.Collections.IEnumerator rows = sheet.GetRowEnumerator(); 264 265 HSSFRow headerRow = sheet.GetRow(0); 266 int cellCount = headerRow.LastCellNum; 267 268 for (int j = 0; j < cellCount; j++) 269 { 270 HSSFCell cell = headerRow.GetCell(j); 271 dt.Columns.Add(cell.ToString()); 272 } 273 274 for (int i = (sheet.FirstRowNum + 1); i <= sheet.LastRowNum; i++) 275 { 276 HSSFRow row = sheet.GetRow(i); 277 DataRow dataRow = dt.NewRow(); 278 279 for (int j = row.FirstCellNum; j < cellCount; j++) 280 { 281 if (row.GetCell(j) != null) 282 dataRow[j] = row.GetCell(j).ToString(); 283 } 284 285 dt.Rows.Add(dataRow); 286 } 287 return dt; 288 } 289 290 } 以上相關源碼及測試用例下載地址: http://download.csdn.net/source/2330821 參考地址: NPOI導出Excel表功能實現(多個工作簿):http://www.cnblogs.com/zhengjuzhuan/archive/2010/02/01/1661103.html 在 Server 端存取 Excel 檔案的利器:NPOI Library:http://msdn.microsoft.com/zh-tw/ee818993.aspx ASP.NET使用NPOI類庫導出Excel:http://www.cnblogs.com/niunan/archive/2010/03/30/1700706.html 總結: 通過以上分析,我們不難發現,用NPOI或MyXls代替是Excel是很明智的,在發文前,我看到NPOI及MyXls仍然在活躍的更新中。在使用過程中發現這兩個組件極相似,以前看過文章說他們使用的內核是一樣的。還有NPOI是國人開發的,且有相關中文文檔,在很多地方有相關引用,下載量也很大。並且它支持Excel,看到MyXls相關問題基本上沒人回答,所以推薦使用NPOI。MyXls可以直接Cell.Font.Bold操作,而NPOI得使用CellType多少感覺有點麻煩。 本文同時發布於:.net 通過NPOI或MyXls把DataTable導出到Excel