读取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> " ;
}

 直接用内存流来处理上传的文件还是比较快的,大家试试吧,有什么问题记得给我留言。或者大家帮我优化增强后,也请告诉我,共同进步嘛。

测试项目:ExcelUtils.zip

你可能感兴趣的:(Excel)