读取Excel批量上载

企业应用中经常会遇到批量上传数据的需求,客户要求使用excel表格录入一批数据,然后通过网页上传该excel表格,实现批量导入数据。这样的 需求其实主要就是处理Excel表格,把Excel表格中的内容读取出来后,做一些必要的校验,然后上传校验成功的数据,返回失败数据的行号以及校验失败 的信息。

如何读取Excel表格,网上已经有很多方法,有些是通过oledb,有些是通过第三方组件。我参考了网上的一些代码,加上自己的封装,给大家 提供一个改良后的版本。当然,为了做到通用,我没有使用oledb的方式,而是使用了一个第三方组件。使用第三方组件的原因很简单,因为有些服务器不一定 安装Excel,有些连oledb提供程序都没有,所以哦,还是用第三方组件比较能够通吃。

这个第三方组件叫做koogra,.NET实现的开源组件,比较好用。这里是koogra项目地址:http://sourceforge.net/projects/koogra/

好了,开始我们的封装过程,为了好用我希望的方式是四种,返回的结果都是DataTable对象。

1:传入的参数包括工作簿地址、工作表名称;

2:传入的参数包括工作簿地址、工作表的索引(0表示第一个工作表);

3:传入的参数包括内存流、工作表名称;

4:传入的参数包括内存流、工作表的索引(0表示第一个工作表)。

ok,开始上代码,记得项目要引用Ionic.Utils.Zip.dll和Net.SourceForge.Koogra.dll

代码
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是文件上传控件。

代码
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>";
}

直接用内存流来处理上传的文件还是比较快的!
posted @ 2010-02-07 22:51  鲶鱼追梦  阅读(254)  评论(0编辑  收藏  举报