今天学习的是从FTP上下载Excel文件,DataTable接收数据之后,在DataTable中通过筛选,删减修改之后把数据插入到DB相应表中。
优点:读取方式简单、读取速度快
缺点:除了读取过程不太灵活之外,这种读取方式还有个弊端就是,当Excel数据量很大时。会非常占用内存,当内存不够时会抛出内存溢出的异常。
命名空间:using System.Data.OleDb;
另注:
参数:HDR=NO/YES
OleDb读入一个Excel工作表(Sheet)的数据后,工作表的第一行会变成标题,第二行起,逐行变为DataTable的一个数据行(Row)
以下是代码:
//根据excle的路径把第一个sheel中的内容放入datatable public static DataTable ReadExcelToTable(string path)//excel存放的路径 { try { //连接字符串 string connstring = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\'Excel 8.0;HDR=NO;IMEX=1\';"; // Office 07及以上版本 不能出现多余的空格 而且分号注意 //string connstring = Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + path + ";Extended Properties=\'Excel 8.0;HDR=NO;IMEX=1\';"; //Office 07以下版本 using (OleDbConnection conn = new OleDbConnection(connstring)) { conn.Open(); DataTable sheetsName = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "Table" }); //得到所有sheet的名字 string firstSheetName = sheetsName.Rows[0][2].ToString(); //得到第一个sheet的名字 string sql = string.Format("SELECT * FROM [{0}]", firstSheetName); //查询字符串
//string sql = string.Format("SELECT * FROM [{0}] WHERE [日期] is not null", firstSheetName); //查询字符串
OleDbDataAdapter ada = new OleDbDataAdapter(sql, connstring); DataSet set = new DataSet(); ada.Fill(set); return set.Tables[0]; } } catch (Exception) { return null; } }
项目中还可以结合流文件(fileStream)的操作,检查每一行数据,数据类型等,一行一行的插入到DB的表,使用DataTable的目的就是为了检查excel的行列数(主要是列数)是否符合要求,比如今天的测试中,
网友有个说法:string sqlExcel = ("select * from [计划上sheet$A3:D8]"); sheet$后面是范围A3到D8的 如果行不确定 要取到后面行 就把D8改成D
后来看到的,所以还没测试,
以上这个问题我也在想,是不是excel里面sheet的活动界面的问题,select * from [sheetName]选取了所有的列数,所以导致可能DaTaTable导致空列,建议在DaTaTable进行删改,或者用datagrid修改,随后保存修改到DATATABLE中。
对于其他的excel读取方式,参见博客地址:http://www.cnblogs.com/icyJ/p/ReadExcel.html
另外对于参数connstring字符串的标准,
1)HDR表示要把第一行作为数据还是作为列名,作为数据用HDR=no,作为列名用HDR=yes;
使用 Excel 工作簿时,默认情况下,区域中的第一行是标题行(或字段名称)。如果第一个区域不包含标题,您可以在连接字符串的扩展属性中指定 HDR=NO。如果您在连接字符串中指定 HDR=NO,Jet OLE DB 提供程序将自动为您命名字段(不管excel中的列叫什么名字,F1 表示第一个字段,F2 表示第二个字段,依此类推,select F1,F2 from [sheet1$]);
2)IMEX=1将所有读入数据看作字符,其他值(0、2)请查阅相关帮助文档;
3)如果出现“找不到可安装的isam”错误,一般是连接字符串错误
string connstring = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\'Excel 8.0;HDR=NO;IMEX=1\';";
HDR表示要把第一行作为数据还是作为列名,作为数据用HDR=no,作为列名用HDR=yes;
string connstring = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\'Excel 8.0;HDR=YES;IMEX=1\';";
接着继续:
这里出现的问题是:
很容易造成读入很多的空行到datatable中,比如下面的excel,我们基本上看不出到底有多少实际的行数:
string sql = string.Format("SELECT * FROM [{0}]", firstSheetName); //查询字符串
string sql = string.Format("SELECT * FROM [{0}] WHERE [日期] is not null", firstSheetName); //查询字符串,字段名注意一定要和excel中标题名一致,有空格哦~
note:这时HDR参数必须是YES,否则会报异常
参考:http://www.devba.com/index.php/archives/4024.html
Excel读取存在空白的原因:表格有两个后台属性,分别是已使用的最大行数和已使用的最大列数。这个 adapter可能是按这两个属性来的,没法改。读取代码部分如图所示,图示为主要解析Excel到DataTable.经过仔细监视代码我们会发现在 da.Fill(dt)时,把空白行填充到DataTable了。总体来讲这个是有微软提供的方法和规则,那么是没办法改的。
解决办法有以下几个:
1、在读取的时候SQL语句上进行过滤:Select * From SheetName where col1 is not null and col2 is not null 在读取的过程时,对空白行进行非空顾虑,建议过滤非空时,根据业务,把不可为空的Excel中的列作为col1和col2;当然可以先删除空白行后再进行 读取;总之先把空白行在读取到Excel前除掉;
2、在读取Excel到DataTable后再过滤掉空白行;DataTable空白行处理空白行方法应该很多的;但是在进行业务校验的时候一定需要先删除空白行!