您的位置:首页 > 编程语言 > C#

c#通过OleDb方式读取Excel的最佳做法,不会丢数据

2012-09-13 08:50 801 查看
关于c#读取Excel,目前为止,我一共发现三种方式

oledb,com组件、第三方类库

三种方式各有优缺点。本文介绍使用oledb读取excel的最佳做法。

首先说一下为什么不使用其他两种方式:

com组件,使用起来比较麻烦。

第三方类库,我只用过ExcelLibrary这个类库,很不错,只是,它以gpl授权发布,我可不想受它的感染。

所以我采用oledb的方式,方便,无限制。

当然oledb也有它的问题,默认情况下,他检查表中数据行的前8行,来决定列的类型,

此时,就会面临一个问题,如果一个表的前8行是数字,而到了第9行,是字母或是汉字什么的,无法转换成数字格式,就没法读取数据了。

解决此问题的方法是,在连接字符串中设置HDR=no,不把第一行认为是列名,而直接把第一行认为是普通数据,

这样,在读取到dataTable里,oledb会自动生成列名,f1、f2、f3之类,这样的话,我只需要保证列名不是纯数字,然后根据第一行的数据,

改一下列名,再把第一行数据删除,就得到我们想要的DataTable了。

以下代码出自我的开源项目,都是平时的积累,还有一些其他的东西,以后会慢慢介绍给大家:

http://lmcommon.codeplex.com/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Text.RegularExpressions;

namespace Lm.Common.Excel
{
public class ExcelReader
{
public DataTable Read(string file)
{
string ConnectionString = @"Provider=Microsoft.Jet.OleDb.4.0;Data Source=" + file + ";" +
"Extended Properties='Excel 8.0;HDR=no;IMEX=1';";
var con = new System.Data.OleDb.OleDbConnection(ConnectionString);
try
{
con.Open();
var tables = con.GetOleDbSchemaTable(System.Data.OleDb.OleDbSchemaGuid.Tables, new object[] { });
con.Close();
if (tables.Rows.Count == 0)
{ throw new Exception("Excel必须包含一个表"); }
var firstTableName = tables.Rows[0]["TABLE_NAME"].ToString();
System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand("select * from [" + firstTableName + "] ", con);
System.Data.OleDb.OleDbDataAdapter apt = new System.Data.OleDb.OleDbDataAdapter(cmd);
var dt = new System.Data.DataTable();
apt.Fill(dt);
if (dt.Rows.Count < 2)
{ throw new Exception("表必须包含数据"); }
var headRow = dt.Rows[0];
foreach (DataColumn c in dt.Columns)
{
var headValue = (headRow[c.ColumnName] == DBNull.Value || headRow[c.ColumnName] == null) ? "" : headRow[c.ColumnName].ToString().Trim();
if (headValue.Length == 0)
{ throw new Exception("必须输入列标题"); }
if (Regex.IsMatch(headValue, "^[\u4e00-\u9fa5,a-z,A-Z]{0,}$") == false)
{ throw new Exception("列标题只能输入汉字或英文字母:" + headValue); }
if (dt.Columns.Contains(headValue))
{ throw new Exception("不能用重复的列标题:" + headValue); }
c.ColumnName = headValue;
}
dt.Rows.RemoveAt(0);
return dt;
}
catch (Exception ee)
{ throw ee; }
finally
{ con.Close(); }
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: