ASP .NET應(yīng)用程序常常會有從Excel文件中讀取數(shù)據(jù)或?qū)?shù)據(jù)寫入Excel的需求。一般來講,在ASP .NET中讀寫Excel文件有幾種解決方案。
使用OLE DB
使用OLE DB,可以以查詢數(shù)據(jù)庫的方式來讀取Excel文件,因為在某種程度上,Excel表格可以看成是一張一張的數(shù)據(jù)表。二者的主要區(qū)別在于所使用的數(shù)據(jù)引擎不一樣。使用OLE DB訪問Excel的要點是計算機上必須具有Microsoft Access Data Component 2.6(MADC2.6)以上版本,同時在連接字符串上必須聲明“Extended Properties=Excel 8.0”,這里指定的Excel版本號如果高于8.0可能會出錯,所以一般來講必須使用Excel 8.0。
其他的寫法就和一般的訪問數(shù)據(jù)庫一樣了,打開連接,填充數(shù)據(jù)集,再關(guān)閉連接即可。例如下面的實現(xiàn)代碼:
//創(chuàng)建一個數(shù)據(jù)鏈接
string strCon="Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=c:\\\\sample.xls;Extended Properties=Excel 8.0";
OleDbConnection myConn=new OleDbConnection(strCon);
string strCom="SELECT*FROM\[Sheet1$\]";
myConn.Open();
//打開數(shù)據(jù)鏈接,得到一個數(shù)據(jù)集
OleDbDataAdapter myCommand=new OleDbDataAdapter(strCom,myConn);
//創(chuàng)建一個DataSet對象
myDataSet=new DataSet();
//得到自己的DataSet對象
myCommand.Fill(myDataSet,"\[Sheet1$\]");
//關(guān)閉此數(shù)據(jù)鏈接
myConn.Close();
使用這種解決方案的優(yōu)點是不需要其他的服務(wù)器組件,部署非常方便,但是缺點也是明顯的,用它來讀取Excel 2003格式以上的文件,會存在數(shù)據(jù)丟失的情況,而且也無法生成Excel文件。
使用Office主互操作程序集
另外一種解決方案是使用Office主互操作程序集,采用這種方式需要在服務(wù)器上安裝Office 2003,但是卻能夠比較精細地控制Excel文件的方方面面,包括格式、字體、顏色等。
下面的代碼演示了如何讀取Excel文件中某個單元格的值:
string
Excel.Application myExcel=new Excel.ApplicationClass();
object oMissing=System .Reflection.Missing.Value;
myExcel.Application.Workbooks.Open(excelFilePath,oMissing,
oMissing,oMissing,oMissing,oMissing,
oMissing,oMissing,oMissing,oMissing,oMissing,oMissing,oMissing,oMissing,oMissing);
Excel.Workbook myBook=myExcel.Workbooks\[1\];
Excel.Worksheet mySheet=(Excel.Worksheet)myBook.Worksheets\[1\];
System .Data.DataTable dt=new System .Data.DataTable("mytable");
dt.Columns.Add("F1",System .Type.GetType("System .String"));
dt.Columns.Add("F2",System .Type.GetType("System .String"));
dt.Columns.Add("F3",System .Type.GetType("System .String"));
dt.Columns.Add("F4",System .Type.GetType("System .String"));
dt.Columns.Add("F5",System .Type.GetType("System .String"));
DataSet myDs=new DataSet();
myDs.Tables.Add(dt);
DataRow myRow;
myDs.Clear();
for(int i=2;i<=4;i++)//第一行為標題,不讀取
{
myRow=myDs.Tables\["mytable"\].NewRow();
for(int j=1;j<=5;j++)
{
Excel.Range r=(Excel.Range)mySheet.Cells\[i,j\];
string strValue=r.Text.ToString();
string aa=strValue;
string columnname="F"+j.ToString();
myRow\[columnname\]=strValue;
}
myDs.Tables\["mytable"\].Rows.Add(myRow);
}
DataGrid1.DataSource=myDs.Tables\["mytable"\].DefaultView;
DataGrid1.DataBind();
下面的代碼則演示了如何生成Excel文件,并向其中寫入值:
string filename="";
Excel.ApplicationClass oExcel;
oExcel=new Excel.ApplicationClass();
oExcel.UserControl=false;
Excel.WorkbookClass
b=(Excel.WorkbookClass)oExcel.Workbooks.Add(System .Reflection.Missing.
Value);
for(int i=1;i<=5;i++)
{
oExcel.Cells\[i,1\]=i.ToString();
oExcel.Cells\[i,2\]=""第2列";
oExcel.Cells\[i,3\]=""第3列";
oExcel.Cells\[i,4\]=""第4列";
}
wb.Saved=true;
filename=Request.PhysicalApplicationPath+"test.xls";
oExcel.ActiveWorkbook.SaveCopyAs(filename);
oExcel.Quit();
System .GC.Collect();
Response.Redirect(Request.ApplicationPath+"/test.xls");
實際上,對于ASP .NET來講,這并不是一個很好的解決方案,原因是這個解決方案將客戶端的組件用到了服務(wù)器上,這往往會帶來一些意想不到的問題,如果在處理一個Excel文件的時候出錯,那么整個線程就會死在那里,服務(wù)器上的Excel進程無法重啟動,Excel文件無法刪除,后面的Excel文件也無法處理,只能重新啟動服務(wù)器,所以這是一個很大的問題。
使用ServerDocument
在上一個解決方案中,使用Office主互操作程序集存在很大的問題,究其原因是因為將本應(yīng)在客戶端使用的Office組件用在了服務(wù)器上,這些Office組件在設(shè)計之初就沒有考慮在服務(wù)中調(diào)用的情況。對于在服務(wù)器上使用Excel文件,微軟推薦的解決方案是使用ServerDocument。
在具有Microsoft Visual Studio 2005 Tools for the Microsoft Office System自定義的Microsoft Office Word 2003文檔或Microsoft Office Excel 2003工作簿中,可以將數(shù)據(jù)存儲在嵌入的數(shù)據(jù)島中,無需啟動Excel或Word即可訪問數(shù)據(jù)島。
數(shù)據(jù)島是一個XML文檔,其中包含Office文檔中嵌入的數(shù)據(jù),無需實例化Office文檔即可訪問該XML文檔。數(shù)據(jù)實際存在于兩個地方,即文檔和單獨的嵌入數(shù)據(jù)島中。在數(shù)據(jù)島與文檔之間使用了數(shù)據(jù)綁定,以使它們保持同步。如果服務(wù)器上運行的代碼修改了數(shù)據(jù)島,則在文檔打開,并且文檔中的代碼運行時,Office文檔會與數(shù)據(jù)島進行同步。
此模型具有以下幾項優(yōu)勢:
·可以將驗證代碼添加到獨立于文檔的數(shù)據(jù)中。通過將驗證與文檔分離,可以將數(shù)據(jù)驗證代碼移植到其他文檔中。
·數(shù)據(jù)島使用可脫機使用的數(shù)據(jù)填充。當文檔中的緩存數(shù)據(jù)項包含數(shù)據(jù)時,該文檔將與數(shù)據(jù)島進行交互。
·由于可以從外部訪問數(shù)據(jù)島,因此無需實例化Office就可以修改文檔中嵌入的數(shù)據(jù),從而支持服務(wù)器上文檔的快速批處理。但是,只能訪問緩存中的數(shù)據(jù),而不是文檔中的所有數(shù)據(jù)。
下面的代碼演示了如何使用ServerDocument訪問數(shù)據(jù):
string
System .IO.StringReader schemaReader=new System .IO.StringReader(dataItem1.Schema);