(1)OleDB方式

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

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

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

读取代码如下:

   1: public DataTable GetExcelTableByOleDB(string strExcelPath, string tableName)

   2: {

   3:     try

   4:     {

   5:         DataTable dtExcel = new DataTable();

   6:         //数据表

   7:         DataSet ds = new DataSet();

   8:         //获取文件扩展名

   9:         string strExtension = System.IO.Path.GetExtension(strExcelPath);

  10:         string strFileName = System.IO.Path.GetFileName(strExcelPath);

  11:         //Excel的连接

  12:         OleDbConnection objConn = null;

  13:         switch (strExtension)

  14:         {

  15:             case ".xls":

  16:                 objConn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + strExcelPath + ";" + "Extended Properties=\"Excel 8.0;HDR=NO;IMEX=1;\"");

  17:                 break;

  18:             case ".xlsx":

  19:                 objConn = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + strExcelPath + ";" + "Extended Properties=\"Excel 12.0;HDR=NO;IMEX=1;\"");

  20:                 break;

  21:             default:

  22:                 objConn = null;

  23:                 break;

  24:         }

  25:         if (objConn == null)

  26:         {

  27:             return null;

  28:         }

  29:         objConn.Open();

  30:         //获取Excel中所有Sheet表的信息

  31:         //System.Data.DataTable schemaTable = objConn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null);

  32:         //获取Excel的第一个Sheet表名

  33:         //string tableName = schemaTable.Rows[0][2].ToString().Trim();

  34:         string strSql = "select * from [" + tableName + "]";

  35:         //获取Excel指定Sheet表中的信息

  36:         OleDbCommand objCmd = new OleDbCommand(strSql, objConn);

  37:         OleDbDataAdapter myData = new OleDbDataAdapter(strSql, objConn);

  38:         myData.Fill(ds, tableName);//填充数据

  39:         objConn.Close();

  40:         //dtExcel即为excel文件中指定表中存储的信息

  41:         dtExcel = ds.Tables[tableName];

  42:         return dtExcel;

  43:     }

  44:     catch

  45:     {

  46:         return null;

  47:     }

  48: }

下面说明一下连接字符串

        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页名称集合

   2:   System.Data.DataTable schemaTable = objConn.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, null);

   3:   List<string> lstSheetNames = new List<string>();

   4:   for (int i = 0; i < schemaTable.Rows.Count; i++)

   5:   {

   6:       string strSheetName = (string)dtSheetName.Rows[i]["TABLE_NAME"];

   7:       if (strSheetName.Contains("$") && !strSheetName.Replace("'", "").EndsWith("$"))

   8:       {

   9:           //过滤无效SheetName完毕....

  10:           continue;

  11:       }

  12:       if (lstSheetNames != null && !lstSheetNames.Contains(strSheetName))

  13:           lstSheetNames.Add(strSheetName);

  14:   }

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

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

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

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

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

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

读取代码如下:

   1: private Stopwatch wath = new Stopwatch();

   2: /// <summary>

   3: /// 使用COM读取Excel

   4: /// </summary>

   5: /// <param name="excelFilePath">路径</param>

   6: /// <returns>DataTabel</returns>

   7: public System.Data.DataTable GetExcelData(string excelFilePath)

   8: {

   9:     Excel.Application app = new Excel.Application();

  10:     Excel.Sheets sheets;

  11:     Excel.Workbook workbook = null;

  12:     object oMissiong = System.Reflection.Missing.Value;

  13:     System.Data.DataTable dt = new System.Data.DataTable();

  14:     wath.Start();

  15:     try

  16:     {

  17:         if (app == null)

  18:         {

  19:             return null;

  20:         }

  21:         workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, 

  22:             oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);

  23:         //将数据读入到DataTable中——Start   

  24:         sheets = workbook.Worksheets;

  25:         Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//读取第一张表

  26:         if (worksheet == null)

  27:             return null;

  28:         string cellContent;

  29:         int iRowCount = worksheet.UsedRange.Rows.Count;

  30:         int iColCount = worksheet.UsedRange.Columns.Count;

  31:         Excel.Range range;

  32:         //负责列头Start

  33:         DataColumn dc;

  34:         int ColumnID = 1;

  35:         range = (Excel.Range)worksheet.Cells[1, 1];

  36:         while (range.Text.ToString().Trim() != "")

  37:         {

  38:             dc = new DataColumn();

  39:             dc.DataType = System.Type.GetType("System.String");

  40:             dc.ColumnName = range.Text.ToString().Trim();

  41:             dt.Columns.Add(dc);

  42:  

  43:             range = (Excel.Range)worksheet.Cells[1, ++ColumnID];

  44:         }

  45:         //End

  46:         for (int iRow = 2; iRow <= iRowCount; iRow++)

  47:         {

  48:             DataRow dr = dt.NewRow();

  49:             for (int iCol = 1; iCol <= iColCount; iCol++)

  50:             {

  51:                 range = (Excel.Range)worksheet.Cells[iRow, iCol];

  52:                 cellContent = (range.Value2 == null) ? "" : range.Text.ToString();

  53:                     dr[iCol - 1] = cellContent;

  54:             }

  55:             dt.Rows.Add(dr);

  56:         }

  57:         wath.Stop();

  58:         TimeSpan ts = wath.Elapsed;

  59:         //将数据读入到DataTable中——End

  60:         return dt;

  61:     }

  62:     catch

  63:     {

  64:         return null;

  65:     }

  66:     finally

  67:     {

  68:         workbook.Close(false, oMissiong, oMissiong);

  69:         System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);

  70:         workbook = null;

  71:         app.Workbooks.Close();

  72:         app.Quit();

  73:         System.Runtime.InteropServices.Marshal.ReleaseComObject(app);

  74:         app = null;

  75:         GC.Collect();

  76:         GC.WaitForPendingFinalizers();

  77:     }

  78: }

  79: /// <summary>

  80: /// 使用COM,多线程读取Excel(1 主线程、4 副线程)

  81: /// </summary>

  82: /// <param name="excelFilePath">路径</param>

  83: /// <returns>DataTabel</returns>

  84: public System.Data.DataTable ThreadReadExcel(string excelFilePath)

  85: {

  86:     Excel.Application app = new Excel.Application();

  87:     Excel.Sheets sheets = null;

  88:     Excel.Workbook workbook = null;

  89:     object oMissiong = System.Reflection.Missing.Value;

  90:     System.Data.DataTable dt = new System.Data.DataTable();

  91:     wath.Start();

  92:     try

  93:     {

  94:         if (app == null)

  95:         {

  96:             return null;

  97:         }

  98:         workbook = app.Workbooks.Open(excelFilePath, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, 

  99:             oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong, oMissiong);

 100:         //将数据读入到DataTable中——Start   

 101:         sheets = workbook.Worksheets;

 102:         Excel.Worksheet worksheet = (Excel.Worksheet)sheets.get_Item(1);//读取第一张表

 103:         if (worksheet == null)

 104:             return null;

 105:         string cellContent;

 106:         int iRowCount = worksheet.UsedRange.Rows.Count;

 107:         int iColCount = worksheet.UsedRange.Columns.Count;

 108:         Excel.Range range;

 109:         //负责列头Start

 110:         DataColumn dc;

 111:         int ColumnID = 1;

 112:         range = (Excel.Range)worksheet.Cells[1, 1];

 113:         while (iColCount >= ColumnID)

 114:         {

 115:             dc = new DataColumn();

 116:             dc.DataType = System.Type.GetType("System.String");

 117:             string strNewColumnName = range.Text.ToString().Trim();

 118:             if (strNewColumnName.Length == 0) strNewColumnName = "_1";

 119:             //判断列名是否重复

 120:             for (int i = 1; i < ColumnID; i++)

 121:             {

 122:                 if (dt.Columns[i - 1].ColumnName == strNewColumnName)

 123:                     strNewColumnName = strNewColumnName + "_1";

 124:             }

 125:             dc.ColumnName = strNewColumnName;

 126:             dt.Columns.Add(dc);

 127:             range = (Excel.Range)worksheet.Cells[1, ++ColumnID];

 128:         }

 129:         //End

 130:         //数据大于500条,使用多进程进行读取数据

 131:         if (iRowCount - 1 > 500)

 132:         {

 133:             //开始多线程读取数据

 134:             //新建线程

 135:             int b2 = (iRowCount - 1) / 10;

 136:             DataTable dt1 = new DataTable("dt1");

 137:             dt1 = dt.Clone();

 138:             SheetOptions sheet1thread = new SheetOptions(worksheet, iColCount, 2, b2 + 1, dt1);

 139:             Thread othread1 = new Thread(new ThreadStart(sheet1thread.SheetToDataTable));

 140:             othread1.Start();

 141:             //阻塞 1 毫秒,保证第一个读取 dt1

 142:             Thread.Sleep(1);

 143:             DataTable dt2 = new DataTable("dt2");

 144:             dt2 = dt.Clone();

 145:             SheetOptions sheet2thread = new SheetOptions(worksheet, iColCount, b2 + 2, b2 * 2 + 1, dt2);

 146:             Thread othread2 = new Thread(new ThreadStart(sheet2thread.SheetToDataTable));

 147:             othread2.Start();

 148:             DataTable dt3 = new DataTable("dt3");

 149:             dt3 = dt.Clone();

 150:             SheetOptions sheet3thread = new SheetOptions(worksheet, iColCount, b2 * 2 + 2, b2 * 3 + 1, dt3);

 151:             Thread othread3 = new Thread(new ThreadStart(sheet3thread.SheetToDataTable));

 152:             othread3.Start();

 153:             DataTable dt4 = new DataTable("dt4");

 154:             dt4 = dt.Clone();

 155:             SheetOptions sheet4thread = new SheetOptions(worksheet, iColCount, b2 * 3 + 2, b2 * 4 + 1, dt4);

 156:             Thread othread4 = new Thread(new ThreadStart(sheet4thread.SheetToDataTable));

 157:             othread4.Start();

 158:             //主线程读取剩余数据

 159:             for (int iRow = b2 * 4 + 2; iRow <= iRowCount; iRow++)

 160:             {

 161:                 DataRow dr = dt.NewRow();

 162:                 for (int iCol = 1; iCol <= iColCount; iCol++)

 163:                 {

 164:                     range = (Excel.Range)worksheet.Cells[iRow, iCol];

 165:                     cellContent = (range.Value2 == null) ? "" : range.Text.ToString();

 166:                     dr[iCol - 1] = cellContent;

 167:                 }

 168:                 dt.Rows.Add(dr);

 169:             }

 170:             othread1.Join();

 171:             othread2.Join();

 172:             othread3.Join();

 173:             othread4.Join();

 174:             //将多个线程读取出来的数据追加至 dt1 后面

 175:             foreach (DataRow dr in dt.Rows)

 176:                 dt1.Rows.Add(dr.ItemArray);

 177:             dt.Clear();

 178:             dt.Dispose();

 179:             foreach (DataRow dr in dt2.Rows)

 180:                 dt1.Rows.Add(dr.ItemArray);

 181:             dt2.Clear();

 182:             dt2.Dispose();

 183:             foreach (DataRow dr in dt3.Rows)

 184:                 dt1.Rows.Add(dr.ItemArray);

 185:             dt3.Clear();

 186:             dt3.Dispose();

 187:             foreach (DataRow dr in dt4.Rows)

 188:                 dt1.Rows.Add(dr.ItemArray);

 189:             dt4.Clear();

 190:             dt4.Dispose();

 191:             return dt1;

 192:         }

 193:         else

 194:         {

 195:             for (int iRow = 2; iRow <= iRowCount; iRow++)

 196:             {

 197:                 DataRow dr = dt.NewRow();

 198:                 for (int iCol = 1; iCol <= iColCount; iCol++)

 199:                 {

 200:                     range = (Excel.Range)worksheet.Cells[iRow, iCol];

 201:                     cellContent = (range.Value2 == null) ? "" : range.Text.ToString();

 202:                     dr[iCol - 1] = cellContent;

 203:                 }

 204:                 dt.Rows.Add(dr);

 205:             }

 206:         }

 207:         wath.Stop();

 208:         TimeSpan ts = wath.Elapsed;

 209:         //将数据读入到DataTable中——End

 210:         return dt;

 211:     }

 212:     catch

 213:     {

 214:         return null;

 215:     }

 216:     finally

 217:     {

 218:         workbook.Close(false, oMissiong, oMissiong);

 219:         System.Runtime.InteropServices.Marshal.ReleaseComObject(workbook);

 220:         System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);

 221:         workbook = null;

 222:         app.Workbooks.Close();

 223:         app.Quit();

 224:         System.Runtime.InteropServices.Marshal.ReleaseComObject(app);

 225:         app = null;

 226:         GC.Collect();

 227:         GC.WaitForPendingFinalizers();

 228:     }

 229: }

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

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

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

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

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

   1: /// <summary>

   2: /// 将excel中的数据导入到DataTable中

   3: /// </summary>

   4: /// <param name="sheetName">excel工作薄sheet的名称</param>

   5: /// <param name="isFirstRowColumn">第一行是否是DataTable的列名</param>

   6: /// <returns>返回的DataTable</returns>

   7: public DataTable ExcelToDataTable(string sheetName, bool isFirstRowColumn)

   8: {

   9:     ISheet sheet = null;

  10:     DataTable data = new DataTable();

  11:     int startRow = 0;

  12:     try

  13:     {

  14:         fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);

  15:         if (fileName.IndexOf(".xlsx") > 0) // 2007版本

  16:             workbook = new XSSFWorkbook(fs);

  17:         else if (fileName.IndexOf(".xls") > 0) // 2003版本

  18:             workbook = new HSSFWorkbook(fs);

  19:         if (sheetName != null)

  20:         {

  21:             sheet = workbook.GetSheet(sheetName);

  22:         }

  23:         else

  24:         {

  25:             sheet = workbook.GetSheetAt(0);

  26:         }

  27:         if (sheet != null)

  28:         {

  29:             IRow firstRow = sheet.GetRow(0);

  30:             int cellCount = firstRow.LastCellNum; //一行最后一个cell的编号 即总的列数

  31:             if (isFirstRowColumn)

  32:             {

  33:                 for (int i = firstRow.FirstCellNum; i < cellCount; ++i)

  34:                 {

  35:                     DataColumn column = new DataColumn(firstRow.GetCell(i).StringCellValue);

  36:                     data.Columns.Add(column);

  37:                 }

  38:                 startRow = sheet.FirstRowNum + 1;

  39:             }

  40:             else

  41:             {

  42:                 startRow = sheet.FirstRowNum;

  43:             }

  44:             //最后一列的标号

  45:             int rowCount = sheet.LastRowNum;

  46:             for (int i = startRow; i <= rowCount; ++i)

  47:             {

  48:                 IRow row = sheet.GetRow(i);

  49:                 if (row == null) continue; //没有数据的行默认是null       

  50:                 

  51:                 DataRow dataRow = data.NewRow();

  52:                 for (int j = row.FirstCellNum; j < cellCount; ++j)

  53:                 {

  54:                     if (row.GetCell(j) != null) //同理,没有数据的单元格都默认是null

  55:                         dataRow[j] = row.GetCell(j).ToString();

  56:                 }

  57:                 data.Rows.Add(dataRow);

  58:             }

  59:         }

  60:         return data;

  61:     }

  62:     catch (Exception ex)

  63:     {

  64:         Console.WriteLine("Exception: " + ex.Message);

  65:         return null;

  66:     }

  67: }

部分内容参考http://www.cnblogs.com/Tsong/archive/2013/02/21/2920941.html。特此说明!

C#读取Excel的三种方式以及比较的更多相关文章

  1. java 学习笔记 读取配置文件的三种方式

    package com.itheima.servlet.cfg; import java.io.FileInputStream; import java.io.FileNotFoundExceptio ...

  2. POI导出excel的三种方式

    原文链接:https://www.cnblogs.com/zhaoblog/p/7661245.html poi导出excel最常用的是第一种方式HSSFWorkbook,不过这种方式数据量大的话会产 ...

  3. c# 导出excel的三种方式

    第一种:流导出 SaveFileDialog exe = new SaveFileDialog(); exe.Filter = "Execl files (*.xls)|*.xls" ...

  4. 导出excel的三种方式

    第一种是Response输出,这种方式输出的文件不符合标准的excel格式,在打开的时候会有提示,而且不好控制内容.第一种是Response输出,这种方式输出的文件不符合标准的excel格式,在打开的 ...

  5. C#读取Excel的其中一种方式OleDb读取(100万条)--快速大量插入SQL中

    主要运用表类型 Create table BulkTestTable( Id nvarchar(), UserName nvarchar(), Pwd nvarchar() ) Go CREATE T ...

  6. 使用 EasyExcel 读取Excel(两种方式)

    引入 jar 包 <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel&l ...

  7. 将datatable导出为excel的三种方式(转)

    一.使用Microsoft.Office.Interop.Excel.DLL 需要安装Office 代码如下:  2         public static bool ExportExcel(Sy ...

  8. Servlet读取配置文件的三种方式

    一.利用ServletContext.getRealPath()[或getResourceAsStream()] 特点:读取应用中的任何文件.只能在web环境下. private void text3 ...

  9. Python|读、写Excel文件(三种模块三种方式)

    python读写excel的方式有很多,不同的模块在读写的讲法上稍有区别: 用xlrd和xlwt进行excel读写: 用openpyxl进行excel读写: 用pandas进行excel读写: imp ...

随机推荐

  1. 删除Json中的不需要的键值

    var json = {'A': 1,  ,'B': 2, 'ccc': 333} delete json['ccc'];

  2. 阅读{django-restframework}源码[generics.py]学习笔记

    首先django-restframework是基于django的一个框架.   mixins.py中开头是这样写的: Basic building blocks for generic class b ...

  3. Android IOS WebRTC 音视频开发总结(七九)-- WebRTC选择H.264的四大理由

    本文主要介绍WebRTC选择H.264的理由(我们翻译和整理的,译者:weizhenwei,校验:blacker),最早发表在[编风网] 支持原创,转载必须注明出处,欢迎关注我的微信公众号blacke ...

  4. projecteuler Summation of primes

    The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. Find the sum of all the primes below two milli ...

  5. About Mysql 5.7 Installation

    After version of mysql 5.7, mysql increase its security level. CMD run as adminstratot cd c:/mysql/b ...

  6. js面向对象之创建对象

    工厂模式 function createPerson(name,age,job){ var o = new Object(); o.name = name; o.age = age; o.job = ...

  7. maven构建过程

    [转载]原地址:http://www.cnblogs.com/xdp-gacl/p/4051690.html 上一篇只是简单介绍了一下maven入门的一些相关知识,这一篇主要是体验一下Maven高度自 ...

  8. [vivado系列]Zynq开发常用文档

    时间:2016.06.13 目的:阶段性总结学习的策略 ------------------------------------------------------------------------ ...

  9. JENKINS基础使用

    JENKINS总结 修改时间 修改内容 修改人 2016.3.12 创建 刘永志 2016.5.22 添加tomcat+jenkins 刘永志 2016.6.14 添加tomcat找不到ant解决方案 ...

  10. iOS开发中多线程间关于锁的使用

    为什么需要使用锁,当然熟悉多线程的你,自然不会感到陌生. 那你在代码中是否很好的使用了锁的机制呢?你又知道几种实现锁的方法呢? main.m 1 int main(int argc, const ch ...