C#读取Excel的三种方法及比较
(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
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 档案可同时支援“读取”与“写入”用途。
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"];
发布评论