.net操作Excel的支持库下载 http://115.com/file/c2hkh144#NOPI.zip
以前用过依赖于office的方法对Excel文件进行操作,在自己机器上运行正常,到服务器上就不能运行。
这个问题困扰了我好久,终于找到了好的解决方法 。
使用不依赖于office的外部dll来操作Excel。。
首先,我自己建立的类,NpoiHelper,用来进行Excel与DataSet之间的转化,放于自己的类库Tools中
类的内容如下:
using System; using System.Collections.Generic; using System.Text; using System.IO; using NPOI.HSSF.UserModel; using System.Data; using System.Collections; namespace Tools { /// <summary> /// Excel文件到DataSet的转换类 /// </summary> public class NpoiHelper { #region 读取Excel文件内容转换为DataSet /// <summary> /// 读取Excel文件内容转换为DataSet,列名依次为 "c0"……c[columnlength-1] /// </summary> /// <param name="FileName">文件绝对路径</param> /// <param name="startRow">数据开始行数(1为第一行)</param> /// <param name="ColumnDataType">每列的数据类型</param> /// <returns></returns> public static DataSet ReadExcel(string FileName, int startRow, params datatype[] ColumnDataType) { int ertime = 0; int intime = 0; DataSet ds = new DataSet("ds"); DataTable dt = new DataTable("dt"); DataRow dr; StringBuilder sb = new StringBuilder(); using (FileStream stream = new FileStream(@FileName, FileMode.Open, FileAccess.Read)) { HSSFWorkbook workbook = new HSSFWorkbook(stream);//整个Excel文件 HSSFSheet sheet = workbook.GetSheetAt(0);//得到里面第一个sheet int j; for (j = 0; j < ColumnDataType.Length; j++) dt.Columns.Add("c" + j, Type.GetType("System.String")); for (int i = startRow - 1; i <= sheet.LastRowNum; i++) { HSSFRow row = sheet.GetRow(i);//得到第i行 try { dr = dt.NewRow(); for (j = 0; j < ColumnDataType.Length; j++) dr["c" + j] = GetCellData(ColumnDataType[j], row, j).ToString(); dt.Rows.Add(dr); intime++; } catch (Exception er) { ertime++; sb.Append(string.Format("第{0}行出错:{1}\r\n", i + 1, er.Message)); continue; } } ds.Tables.Add(dt); } if (ds.Tables[0].Rows.Count == 0 && sb.ToString() != "") throw new Exception(sb.ToString()); return ds; } #endregion #region 从DataSet导出到MemoryStream流 /// <summary> /// 从DataSet导出到MemoryStream流 /// </summary> /// <param name="SheetName">Excel文件中的Sheet名称</param> /// <param name="ds">存储数据的DataSet</param> /// <param name="HeaderNames">DataSet中的表头(数组形式)</param> /// <param name="columnNames">DataSet中的列名集合(数组形式)</param> /// <param name="datatypes">DataSet中的列名对应的数据类型(datatype枚举类)集合(数组形式)</param> public static MemoryStream CreateExcel(string SheetName, DataSet ds, string[] columnNames, string[] HeaderNames, datatype[] datatypes) { try { HSSFWorkbook wb = new HSSFWorkbook(); HSSFSheet sheet = wb.CreateSheet(SheetName); HSSFRow row; HSSFCell cell; DataRow dr; int j; string column; object columnValue; #region 创建表头 row = sheet.CreateRow(0);//创建第i行 for (j = 0; j < columnNames.Length; j++) { column = columnNames[j]; columnValue = HeaderNames[j]; try { cell = row.CreateCell(j);//创建第0行的第j列 try { cell.SetCellType(HSSFCell.CELL_TYPE_STRING); cell.SetCellValue(columnValue.ToString()); } catch { } } catch { continue; } } #endregion #region 创建每一行 for (int i = 0; i < ds.Tables[0].Rows.Count; i++) { dr = ds.Tables[0].Rows[i]; row = sheet.CreateRow(i + 1);//创建第i行 for (j = 0; j < columnNames.Length; j++) { column = columnNames[j]; columnValue = dr[column]; try { cell = row.CreateCell(j);//创建第i行的第j列 #region 插入第j列的数据 try { switch (datatypes[j]) { case datatype.String: { cell.SetCellType(HSSFCell.CELL_TYPE_STRING); cell.SetCellValue(columnValue.ToString()); } break; case datatype.Datetime: { cell.SetCellType(HSSFCell.CELL_TYPE_STRING); cell.SetCellValue(Convert.ToDateTime(columnValue)); } break; case datatype.Double: { cell.SetCellType(HSSFCell.CELL_TYPE_NUMERIC); cell.SetCellValue(Convert.ToDouble(columnValue)); } break; case datatype.Bool: { cell.SetCellType(HSSFCell.CELL_TYPE_BOOLEAN); cell.SetCellValue(Convert.ToBoolean(columnValue)); } break; case datatype.Richtext: { cell.SetCellType(HSSFCell.CELL_TYPE_FORMULA); cell.SetCellValue(columnValue.ToString()); } break; } } catch { cell.SetCellType(HSSFCell.CELL_TYPE_STRING); cell.SetCellValue(columnValue.ToString()); } #endregion } catch { continue; } } } #endregion //using (FileStream fs = new FileStream(@SaveFileName, FileMode.OpenOrCreate))//生成文件在服务器上 //{ // wb.Write(fs); //} using (MemoryStream ms = new MemoryStream()) { wb.Write(ms); return ms; } } catch (Exception er) { throw er; } } #endregion #region 得到不同数据类型单元格的数据 /// <summary> /// 得到不同数据类型单元格的数据 /// </summary> /// <param name="datatype">数据类型</param> /// <param name="row">数据中的一行</param> /// <param name="column">哪列</param> /// <returns></returns> public static object GetCellData(datatype datatype, HSSFRow row, int column) { switch (datatype) { case datatype.String: try { return row.GetCell(column).StringCellValue; } catch { return row.GetCell(column).NumericCellValue; } case datatype.Bool: try { return row.GetCell(column).BooleanCellValue; } catch { return row.GetCell(column).StringCellValue; } case datatype.Datetime: try { return row.GetCell(column).DateCellValue; } catch { return row.GetCell(column).StringCellValue; } case datatype.Double: try { return row.GetCell(column).NumericCellValue; } catch { return row.GetCell(column).StringCellValue; } case datatype.Richtext: try { return row.GetCell(column).RichStringCellValue; } catch { return row.GetCell(column).StringCellValue; } default: return ""; } } #endregion #region 枚举(单元格数据类型) /// <summary> /// 枚举(单元格数据类型) /// </summary> public enum datatype { /// <summary> /// String=1 /// </summary> String = 1, /// <summary> /// Bool=2 /// </summary> Bool=2, /// <summary> /// Datetime=3 /// </summary> Datetime=3, /// <summary> /// Double=4 /// </summary> Double=4, /// <summary> /// Richtext=5 /// </summary> Richtext=5 } #endregion } }
这样,就能操作Excel了,使用时只需要调用就行了。
友情提示:
使用时请注意:有些人分不清服务器对文件怎么操作的
在web应用程序里,客户端选择一个文件,就调用函数来转化为DataSet
这种情况,除非你直接在服务器的电脑上操作,否则操作不可能成功,服务器上没那个文件,你让他转化什么呢?
这个文件,肯定得在服务器上存在,可以先从客户端上传,再确定上传后的服务器路径,mappath一下,转化为全路径才可以操作
一、上面的可以将Excel导入到DataSet,操作DataSet应该不是我要说的内容问题了。呵呵
二、那么将DataSet保存到Excel,应该还要一个方法转化一下。上面的方法,只是把Excel保存为 MemoryStream内存流,方便转化成其它数据流的。
写一个方法将MemoryStream转化为Excel文件
1、asp.net网页的解决方法,保存到服务器的内存流中,再弹出给客户端下载 。
#region (asp.net网页中)二进制byte[] 导出到文件(文件要有正确的后缀) /// <summary> /// (asp.net网页中)二进制byte[] 导出到文件(文件要有正确的后缀) /// </summary> /// <param name="pg">页面,传 this</param> /// <param name="bytes">文件的二进制数据</param> /// <param name="FileName">导出的文件名(Excel:.xls)</param> public static void BytesToFile(System.Web.UI.Page pg, byte[] bytes, string FileName) { pg.Response.Buffer = true; pg.Response.Clear(); pg.Response.ContentType = "application/download"; FileName = HttpUtility.UrlEncode(FileName, System.Text.Encoding.UTF8); pg.Response.AddHeader("Content-Disposition", "attachment;filename=" + FileName + ";"); pg.Response.BinaryWrite(bytes); pg.Response.Flush(); } #endregion
BytesToFile(this.Page,MemoryStream1.ToArray(),"文件1.xls");2、winform中的解决方法直接保存:
FileStream SaveFile = new FileStream("file1.xls", FileMode.Create, FileAccess.ReadWrite); ms.WriteTo(SaveFile);