C#读取Excel的三种方式以及比较分析

(1)oledb方式

优点:将Excel直接当做数据源处理,通过SQL直接读取内容,读取速度较快。

缺点:读取数据方式不够灵活,无法直接读取某一个单元格,只有将整个Sheet页读取出来后(结果为Datatable)再在Datatable中根据行列数来获取指定的值。

当Excel数据量很大时。会非常占用内存,当内存不够时会抛出内存溢出的异常。

读取代码如下:

  1.  public DataTable GetExcelTableByOleDB(string strExcelPath, string tableName){  try  {    DataTable dtExcel = new DataTable();    //数据表    DataSet ds = new DataSet();    //获取文件扩展名    string strExtension = System.IO.Path.GetExtension(strExcelPath);    string strFileName = System.IO.Path.GetFileName(strExcelPath);    //Excel的连接    OleDbConnection objConn = null;    switch (strExtension)    {      case ".xls":        objConn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + strExcelPath + ";" + "Extended Properties="Excel 8.0;HDR=NO;IMEX=1;"");        break;      case ".xlsx":        objConn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + strExcelPath + ";" + "Extended Properties="Excel 12.0;HDR=NO;IMEX=1;"");        break;      default:        objConn = null;        break;    }    if (objConn == null)    {      return null;    }    objConn.Open();    //获取Excel中所有Sheet表的信息    //System.Data.DataTable schemaTable = objConn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null);    //获取Excel的第一个Sheet表名    //string tableName = schemaTable.Rows[0][2].ToString().Trim();    string strSql = "select * from [" + tableName + "]";    //获取Excel指定Sheet表中的信息    OleDbCommand objCmd = new OleDbCommand(strSql, objConn);    OleDbDataAdapter myData = new OleDbDataAdapter(strSql, objConn);    myData.Fill(ds, tableName);//填充数据    objConn.Close();    //dtExcel即为excel文件中指定表中存储的信息    dtExcel = ds.Tables[tableName];    return dtExcel;  }  catch  {    return null;  }}

登录后复制

   

下面说明一下连接字符串

HDR=Yes,这代表第一行是标题,不做为数据使用(但是我在实际使用中,如果第一行存在复杂数值,那么读取得到的Datatable列标题会自动设置为F1、F2等方式命名,与实际应用不符,所以当时是通过HDR=No方式将所有内容读取到Datatable中,然后手动将第一行设置成标题的);IMEX ( IMport EXport mode )设置 
IMEX 有三种模式: 
0 is Export mode 
1 is Import mode 
2 is Linked mode (full update capabilities) 
我这里特别要说明的就是 IMEX 参数了,因为不同的模式代表著不同的读写行为: 
当 IMEX=0 时为“汇出模式”,这个模式开启的 Excel 档案只能用来做“写入”用途。 
当 IMEX=1 时为“汇入模式”,这个模式开启的 Excel 档案只能用来做“读取”用途。 
当 IMEX=2 时为“链接模式”,这个模式开启的 Excel 档案可同时支援“读取”与“写入”用途。

———————————

另外,读取Excel2007版本的文件时,版本应该从8.0改为12.0,同时驱动不能再用Jet,而应该用ACE。负责会造成“找不到可安装的 ISAM”的错误。

———————————

在网上还发现采用这种方式存在取出的Sheet表的个数多于实际Excel表中的Sheet表个数的情况,其原因有二:

1. 取出的名称中,包括了XL命名管理器中的名称(参见XL2007的公式–命名管理器, 快捷键Crtl+F3);

2. 取出的名称中,包括了FilterDatabase后缀的, 这是XL用来记录Filter范围的。

对于第一点比较简单, 删除已有命名管理器中的内容即可;第二点处理起来比较麻烦, Filter删除后这些名称依然保留着,简单的做法是新增Sheet然后将原Sheet Copy进去。但实际情况并不能为每个Excel做以上检查。下面给出了过滤的方案。(此问题我们有验证过,大家自己验证一下吧)

  1. //objConn为读取Excel的链接,下面通过过滤来获取有效的Sheet页名称集合 System.Data.DataTable schemaTable = objConn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null); List lstSheetNames = new List(); for (int i = 0; i 

    因为读取出来无效SheetName一般情况最后一个字符都不会是$。如果SheetName有一些特殊符号,读取出来的SheetName会自动加上单引号。比如在Excel中将SheetName编辑成MySheet(1),此时读取出来的SheetName就为:'MySheet(1)$',所以判断最后一个字符是不是$之前最好过滤一下单引号。

    ---------------------------------

    (2)Com组件的方式(通过添加 Microsoft.Office.Interop.Excel引用实现)

    优点:能够非常灵活的读取Excel中的数据,用户可以灵活的调用各种函数进行处理。

    缺点:基于单元格的处理,读取速度较慢,对于数据量较大的文件最好不要使用此种方式读取。

    需要添加相应的DLL引用,必须存在此引用才可使用,如果是Web站点部署在IIS上时,还需要服务器机子已安装了Excel,有时候还需要为配置IIS权限。

    读取代码如下:

    private Stopwatch wath = new Stopwatch();/// /// 使用COM读取Excel/// /// 路径/// DataTabelpublic System.Data.DataTable GetExcelData(string excelFilePath){  Excel.Application app = new Excel.Application();  Excel.Sheets sheets;  Excel.Workbook workbook = null;  object oMissiong = System.Reflection.Missing.Value;  System.Data.DataTable dt = new System.Data.DataTable();  wath.Start();  try  {    if (app == null)    {      return null;    }    workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,      oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);    //将数据读入到DataTable中——Start     sheets = workbook.Worksheets;    Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//读取第一张表    if (worksheet == null)      return null;    string cellContent;    int iRowCount = worksheet.UsedRange.Rows.Count;    int iColCount = worksheet.UsedRange.Columns.Count;    Excel.Range range;    //负责列头Start    DataColumn dc;    int ColumnID = 1;    range = (Excel.Range)worksheet.Cells[1, 1];    while (range.Text.ToString().Trim() != "")    {      dc = new DataColumn();      dc.DataType = System.Type.GetType("System.String");      dc.ColumnName = range.Text.ToString().Trim();      dt.Columns.Add(dc);       range = (Excel.Range)worksheet.Cells[1, ++ColumnID];    }    //End    for (int iRow = 2; iRow /// 使用COM,多线程读取Excel(1 主线程、4 副线程)/// /// 路径/// DataTabelpublic System.Data.DataTable ThreadReadExcel(string excelFilePath){  Excel.Application app = new Excel.Application();  Excel.Sheets sheets = null;  Excel.Workbook workbook = null;  object oMissiong = System.Reflection.Missing.Value;  System.Data.DataTable dt = new System.Data.DataTable();  wath.Start();  try  {    if (app == null)    {      return null;    }    workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong,      oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);    //将数据读入到DataTable中——Start     sheets = workbook.Worksheets;    Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//读取第一张表    if (worksheet == null)      return null;    string cellContent;    int iRowCount = worksheet.UsedRange.Rows.Count;    int iColCount = worksheet.UsedRange.Columns.Count;    Excel.Range range;    //负责列头Start    DataColumn dc;    int ColumnID = 1;    range = (Excel.Range)worksheet.Cells[1, 1];    while (iColCount >= ColumnID)    {      dc = new DataColumn();      dc.DataType = System.Type.GetType("System.String");      string strNewColumnName = range.Text.ToString().Trim();      if (strNewColumnName.Length == 0) strNewColumnName = "_1";      //判断列名是否重复      for (int i = 1; i  500)    {      //开始多线程读取数据      //新建线程      int b2 = (iRowCount - 1) / 10;      DataTable dt1 = new DataTable("dt1");      dt1 = dt.Clone();      SheetOptions sheet1thread = new SheetOptions(worksheet, iColCount, 2, b2 + 1, dt1);      Thread othread1 = new Thread(new ThreadStart(sheet1thread.SheetToDataTable));      othread1.Start();      //阻塞 1 毫秒,保证第一个读取 dt1      Thread.Sleep(1);      DataTable dt2 = new DataTable("dt2");      dt2 = dt.Clone();      SheetOptions sheet2thread = new SheetOptions(worksheet, iColCount, b2 + 2, b2 * 2 + 1, dt2);      Thread othread2 = new Thread(new ThreadStart(sheet2thread.SheetToDataTable));      othread2.Start();      DataTable dt3 = new DataTable("dt3");      dt3 = dt.Clone();      SheetOptions sheet3thread = new SheetOptions(worksheet, iColCount, b2 * 2 + 2, b2 * 3 + 1, dt3);      Thread othread3 = new Thread(new ThreadStart(sheet3thread.SheetToDataTable));      othread3.Start();      DataTable dt4 = new DataTable("dt4");      dt4 = dt.Clone();      SheetOptions sheet4thread = new SheetOptions(worksheet, iColCount, b2 * 3 + 2, b2 * 4 + 1, dt4);      Thread othread4 = new Thread(new ThreadStart(sheet4thread.SheetToDataTable));      othread4.Start();      //主线程读取剩余数据      for (int iRow = b2 * 4 + 2; iRow 

       

    (3)NPOI方式读取Excel(此方法未经过测试)

    NPOI 是 POI 项目的 .NET 版本。POI是一个开源的Java读写Excel、WORD等微软OLE2组件文档的项目。使用 NPOI 你就可以在没有安装 Office 或者相应环境的机器上对 WORD/EXCEL 文档进行读写。

    优点:读取Excel速度较快,读取方式操作灵活性

    缺点:需要下载相应的插件并添加到系统引用当中。

    /// /// 将excel中的数据导入到DataTable中/// /// excel工作薄sheet的名称/// 第一行是否是DataTable的列名/// 返回的DataTablepublic DataTable ExcelToDataTable(string sheetName, bool isFirstRowColumn){  ISheet sheet = null;  DataTable data = new DataTable();  int startRow = 0;  try  {    fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);    if (fileName.IndexOf(".xlsx") > 0) // 2007版本      workbook = new XSSFWorkbook(fs);    else if (fileName.IndexOf(".xls") > 0) // 2003版本      workbook = new HSSFWorkbook(fs);    if (sheetName != null)    {      sheet = workbook.GetSheet(sheetName);    }    else    {      sheet = workbook.GetSheetAt(0);    }    if (sheet != null)    {      IRow firstRow = sheet.GetRow(0);      int cellCount = firstRow.LastCellNum; //一行最后一个cell的编号 即总的列数      if (isFirstRowColumn)      {        for (int i = firstRow.FirstCellNum; i 

    更多C#读取Excel的三种方式以及比较分析相关文章请关注PHP中文网!

  2. 登录后复制

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
编程技术

ASP.NET(C#)读取Excel的文件内容

2025-3-6 6:32:49

编程技术

C#实现将数据导出到word或者Excel中的方法

2025-3-6 6:32:58

0 条回复 A文章作者 M管理员
欢迎您,新朋友,感谢参与互动!
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
私信列表
搜索