今天學(xué)習(xí)的是從FTP上下載Excel文件,DataTable接收數(shù)據(jù)之后,在DataTable中通過(guò)篩選,刪減修改之后把數(shù)據(jù)插入到DB相應(yīng)表中。
優(yōu)點(diǎn):讀取方式簡(jiǎn)單、讀取速度快
缺點(diǎn):除了讀取過(guò)程不太靈活之外,這種讀取方式還有個(gè)弊端就是,當(dāng)Excel數(shù)據(jù)量很大時(shí)。會(huì)非常占用內(nèi)存,當(dāng)內(nèi)存不夠時(shí)會(huì)拋出內(nèi)存溢出的異常。
命名空間:using System.Data.OleDb;
另注:
參數(shù):HDR=NO/YES
OleDb讀入一個(gè)Excel工作表(Sheet)的數(shù)據(jù)后,工作表的第一行會(huì)變成標(biāo)題,第二行起,逐行變?yōu)镈ataTable的一個(gè)數(shù)據(jù)行(Row)
以下是代碼:
//根據(jù)excle的路徑把第一個(gè)sheel中的內(nèi)容放入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及以上版本 不能出現(xiàn)多余的空格 而且分號(hào)注意 //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(); //得到第一個(gè)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; } }
項(xiàng)目中還可以結(jié)合流文件(fileStream)的操作,檢查每一行數(shù)據(jù),數(shù)據(jù)類型等,一行一行的插入到DB的表,使用DataTable的目的就是為了檢查excel的行列數(shù)(主要是列數(shù))是否符合要求,比如今天的測(cè)試中,
網(wǎng)友有個(gè)說(shuō)法:string sqlExcel = ('select * from [計(jì)劃上sheet$A3:D8]'); sheet$后面是范圍A3到D8的 如果行不確定 要取到后面行 就把D8改成D
后來(lái)看到的,所以還沒(méi)測(cè)試,
以上這個(gè)問(wèn)題我也在想,是不是excel里面sheet的活動(dòng)界面的問(wèn)題,select * from [sheetName]選取了所有的列數(shù),所以導(dǎo)致可能DaTaTable導(dǎo)致空列,建議在DaTaTable進(jìn)行刪改,或者用datagrid修改,隨后保存修改到DATATABLE中。
對(duì)于其他的excel讀取方式,參見(jiàn)博客地址:http://www.cnblogs.com/icyJ/p/ReadExcel.html
另外對(duì)于參數(shù)connstring字符串的標(biāo)準(zhǔn),
1)HDR表示要把第一行作為數(shù)據(jù)還是作為列名,作為數(shù)據(jù)用HDR=no,作為列名用HDR=yes;
使用 Excel 工作簿時(shí),默認(rèn)情況下,區(qū)域中的第一行是標(biāo)題行(或字段名稱)。如果第一個(gè)區(qū)域不包含標(biāo)題,您可以在連接字符串的擴(kuò)展屬性中指定 HDR=NO。如果您在連接字符串中指定 HDR=NO,Jet OLE DB 提供程序?qū)⒆詣?dòng)為您命名字段(不管excel中的列叫什么名字,F(xiàn)1 表示第一個(gè)字段,F(xiàn)2 表示第二個(gè)字段,依此類推,select F1,F2 from [sheet1$]);
2)IMEX=1將所有讀入數(shù)據(jù)看作字符,其他值(0、2)請(qǐng)查閱相關(guān)幫助文檔;
3)如果出現(xiàn)“找不到可安裝的isam”錯(cuò)誤,一般是連接字符串錯(cuò)誤
string connstring = 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + path + ';Extended Properties='Excel 8.0;HDR=NO;IMEX=1';';
HDR表示要把第一行作為數(shù)據(jù)還是作為列名,作為數(shù)據(jù)用HDR=no,作為列名用HDR=yes;
string connstring = 'Provider=Microsoft.ACE.OLEDB.12.0;Data Source=' + path + ';Extended Properties='Excel 8.0;HDR=YES;IMEX=1';';
接著繼續(xù):
這里出現(xiàn)的問(wèn)題是:
很容易造成讀入很多的空行到datatable中,比如下面的excel,我們基本上看不出到底有多少實(shí)際的行數(shù):
string sql = string.Format('SELECT * FROM [{0}]', firstSheetName); //查詢字符串
string sql = string.Format('SELECT * FROM [{0}] WHERE [日期] is not null', firstSheetName); //查詢字符串,字段名注意一定要和excel中標(biāo)題名一致,有空格哦~
note:這時(shí)HDR參數(shù)必須是YES,否則會(huì)報(bào)異常
參考:http://www.devba.com/index.php/archives/4024.html
Excel讀取存在空白的原因:表格有兩個(gè)后臺(tái)屬性,分別是已使用的最大行數(shù)和已使用的最大列數(shù)。這個(gè) adapter可能是按這兩個(gè)屬性來(lái)的,沒(méi)法改。讀取代碼部分如圖所示,圖示為主要解析Excel到DataTable.經(jīng)過(guò)仔細(xì)監(jiān)視代碼我們會(huì)發(fā)現(xiàn)在 da.Fill(dt)時(shí),把空白行填充到DataTable了??傮w來(lái)講這個(gè)是有微軟提供的方法和規(guī)則,那么是沒(méi)辦法改的。
解決辦法有以下幾個(gè):
1、在讀取的時(shí)候SQL語(yǔ)句上進(jìn)行過(guò)濾:Select * From SheetName where col1 is not null and col2 is not null 在讀取的過(guò)程時(shí),對(duì)空白行進(jìn)行非空顧慮,建議過(guò)濾非空時(shí),根據(jù)業(yè)務(wù),把不可為空的Excel中的列作為col1和col2;當(dāng)然可以先刪除空白行后再進(jìn)行 讀取;總之先把空白行在讀取到Excel前除掉;
2、在讀取Excel到DataTable后再過(guò)濾掉空白行;DataTable空白行處理空白行方法應(yīng)該很多的;但是在進(jìn)行業(yè)務(wù)校驗(yàn)的時(shí)候一定需要先刪除空白行!