本文使用.NET开源组件koogra实现读取excel内容批量上传,在企业应用中经常会遇到批量上传数据的需求,客户要求使用excel表格录入一批数据,然后通过网页上传该excel表格,实现批量导入数据。这样的需求其实主要就是处理Excel表格,把Excel表格中的内容读取出来后,做一些必要的校验,然后上传校验成功的数据,返回失败数据的行号以及校验失败的信息。
koogra项目组件下载地址:
http://sourceforge.net/projects/koogra/
下面开始我们的封装过程,为了好用我希望的方式是四种,返回的结果都是DataTable对象。
1:传入的参数包括工作簿地址、工作表名称;
2:传入的参数包括工作簿地址、工作表的索引(0表示第一个工作表);
3:传入的参数包括内存流、工作表名称;
4:传入的参数包括内存流、工作表的索引(0表示第一个工作表)。
开始上代码,记得项目要引用Ionic.Utils.Zip.dll和Net.SourceForge.Koogra.dll
Code [http://www.oeedu.com] using System; using System.Collections.Generic; using System.Text; using System.Data; using Net.SourceForge.Koogra.Excel; namespace Gren.Framework.Office{ /// <summary> /// Excel工具类 /// </summary> public class ExcelUtils { private Workbook book; public ExcelUtils( string path) { this .book = new Workbook(path); } public ExcelUtils(System.IO.Stream stream) { this .book = new Workbook(stream); } protected DataTable SaveAsDataTable(Worksheet sheet) { DataTable dt = new DataTable(); uint minRow = sheet.Rows.MinRow; uint maxRow = sheet.Rows.MaxRow; Row firstRow = sheet.Rows[minRow]; uint minCol = firstRow.Cells.MinCol; uint maxCol = firstRow.Cells.MaxCol; for ( uint i = minCol; i <= maxCol; i ) { dt.Columns.Add(firstRow.Cells[i].FormattedValue()); } for ( uint i = minRow 1 ; i <= maxRow; i ) { Row row = sheet.Rows[i]; if (row != null ) { DataRow dr = dt.NewRow(); for ( uint j = minCol; j <= maxCol; j ) { Cell cell = row.Cells[j]; if (cell != null ) { dr[Convert.ToInt32(j)] = cell.Value != null ? cell.Value.ToString() : string .Empty; } } dt.Rows.Add(dr); } } return dt; } public DataTable ToDataTable( int index) { Worksheet sheet = this .book.Sheets[index]; if (sheet == null ) { throw new ApplicationException( string .Format( " 索引[{0}]所指定的电子表格不存在! " , index)); } return this .SaveAsDataTable(sheet); } public DataTable ToDataTable( string sheetName) { Worksheet sheet = this .book.Sheets.GetByName(sheetName); if (sheet == null ) { throw new ApplicationException( string .Format( " 名称[{0}]所指定的电子表格不存在! " , sheetName)); } return this .SaveAsDataTable(sheet); } #region 静态方法 /// <summary> /// 单元格格式为日期时间,使用此方法转换为DateTime类型,若解析失败则返回‘0001-01-01’ /// </summary> public static DateTime ParseDateTime( string cellValue) { DateTime date = default (DateTime); double value = default ( double ); if ( double .TryParse(cellValue, out value)) { date = DateTime.FromOADate(value); } else { DateTime.TryParse(cellValue, out date); } return date; } /// <summary> /// 转换为DataTable(文件路径 表名) /// </summary> public static DataTable TranslateToTable( string path, string sheetName) { ExcelUtils utils = new ExcelUtils(path); return utils.ToDataTable(sheetName); } /// <summary> /// 转换为DataTable(文件路径 表索引) /// </summary> public static DataTable TranslateToTable( string path, int sheetIndex) { ExcelUtils utils = new ExcelUtils(path); return utils.ToDataTable(sheetIndex); } /// <summary> /// 转换为DataTable(文件路径) /// </summary> public static DataTable TranslateToTable( string path) { ExcelUtils utils = new ExcelUtils(path); return utils.ToDataTable( 0 ); } /// <summary> /// 转换为DataTable(内存流 表名) /// </summary> public static DataTable TranslateToTable(System.IO.Stream stream, string sheetName) { ExcelUtils utils = new ExcelUtils(stream); return utils.ToDataTable(sheetName); } /// <summary> /// 转换为DataTable(内存流 表索引) /// </summary> public static DataTable TranslateToTable(System.IO.Stream stream, int sheetIndex) { ExcelUtils utils = new ExcelUtils(stream); return utils.ToDataTable(sheetIndex); } /// <summary> /// 转换为DataTable(内存流) /// </summary> public static DataTable TranslateToTable(System.IO.Stream stream) { ExcelUtils utils = new ExcelUtils(stream); return utils.ToDataTable( 0 ); } #endregion }}
ParseDateTime这个静态方法是用来处理日期时间类型单元格的,在Excel表格里面日期时间类型读取出来的时候是一个double类型的数据,使用这个方法可以得到正确的DataTime类型的值。仔细的人可以发现这个方法其实除了把double类型的数据转换为DateTime之外,还会在转换失败的时候尝试把该单元格的内容做为字符串转换为DateTime,因为如果单元格是文本类型的话,那么用户输入的日期时间就不是一个double了。
好了,读取Excel的类就封装好了,那么在asp.net页面中如何使用呢?再看下面的代码,fileUpload1是文件上传控件。
Code [http://www.oeedu.com] if (fileUpload1.HasFile){ DataTable dt = null ; try { using (System.IO.MemoryStream stream = new System.IO.MemoryStream(fileUpload1.FileBytes)) { dt = Gren.Framework.Office.ExcelUtils.TranslateToTable(stream, " sheet1 " ); } // 得到DataTable对象后,做你自己的处理 } catch (Exception ex) { lblMessage.Text = " <p><span class=/"c_red ft_bold/">处理数据文件错误:</span></p> " ; lblMessage.Text = " <div class=/"c_red/"> " Server.HtmlEncode(ex.Message) " </div> " ; }} else { lblMessage.Text = " <p><span class=/"c_red ft_bold/">请选择数据文件</span></p> " ;}
直接用内存流来处理上传的文件还是比较快的,大家试试吧.