本文所演示的導入和導出方法並未使用Excel COM組件,而是使用原始的ASP.NET OleDb驅動程序,這使得ASP.NET應用程序即使部署在未安裝Excel的服務器上也同樣能支持導入和導出校准的Excel格式文件。
[@more@]
本文所演示的導入和導出方法並未使用Excel COM組件,而是使用原始的ASP.NET OleDb驅動程序,這使得ASP.NET應用程序即使部署在未安裝Excel的服務器上也同樣能支持導入和導出校准的Excel格式文件。
一、導出
網上有不少關於ASP.NET應用程序導出Excel文件的方法,大多都是設置Response對象的Content-Type為“application/ms-excel”后,以字符串形式輸出數據供用戶下載(可參考:http://blog.csdn.net/jilm168/archive/2007/11/06/1869118.aspx)。
雖說這種方式確實能實現導出Excel文件的目的,但其導出的Excel文件是不標准的。如果你用記事本打開使用此方式導出的文件會發現該文件是一個純文本文件,這個倒是次要的,因為強大的Excel絕對有能力識別並顯示這種“偽”Excel文件,但如果我們的應用程序要支持導入的話,那么這一文件就無法被程序正確識別了。
為了導出標准的Excel文件,我們可以首先准備好一個標准Excel文件做為導出模板,導出數據時先創建此模板的一個副本,使用OleDb驅動程序向副本中寫入數據后,將此副本的二進制字節流輸出至客戶端供用戶下載,最后再刪除此副本。
如何制做一個Excel文件模板呢?你可以在安裝有Excel的機器上新建一個“Microsoft Excel 工作表”,在工作表的第一行設置好需要的字段,然后選中整個表,點右鍵選擇“設置單元格格式”,在“數字”標簽的“分類”列表選擇“文本”,點擊“確定” 並保存文件。將單元格格式設置為“文本”主要是為了防止日后導入數據時某些數據格式無法被識別。
有了這個模板,我們就可以開始寫代碼導出數據了。本示例所使用模板文件位於站點根目錄,名為“考生成績信息表demo.xls”,共包含三個列:“准考證號”、“姓名”。
excel_template
private void Excel(DataTable dt, string FileName)
{
// 根據模板文件創建副本
string a = Guid.NewGuid().ToString();
string filePath = Server.MapPath("../xls/" + Guid.NewGuid().ToString() + ".xls");
File.Copy(Server.MapPath("../xlsDemo/考生成績信息表demo.xls"), filePath);
// 使用OleDb驅動程序連接到副本
OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties=Excel 8.0;");
using (conn)
{
conn.Open();
// 增加記錄
for (int i = 0; i < dt.Rows.Count; i++)
{
OleDbCommand cmd = new OleDbCommand("INSERT INTO [Sheet1$]([准考證號], [姓名]) VALUES('" + dt.Rows[i][0].ToString() + "', '" + dt.Rows[i][1].ToString() + "')", conn);
cmd.ExecuteNonQuery();
}
}
// 輸出副本的二進制字節流
Response.ContentType = "application/ms-excel";
Response.AppendHeader("Content-Disposition", "attachment;filename=" + Server.UrlEncode(FileName));
Response.Charset = "GB2312";
Response.BinaryWrite(File.ReadAllBytes(filePath));
// 刪除副本
File.Delete(filePath);
}
二、導入
相對於導出,導入部分的實現代碼要簡單的多:
string f_name = Server.MapPath("../xls/");
string sql = "";
string cs = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + f_name + ";Excel 8.0;HDR=Yes;IMEX=1";
OleDbConnection CNN = new OleDbConnection(cs);
CNN.Open();
string ss = "select * from [Sheet1$] ";
OleDbDataAdapter oda = new OleDbDataAdapter(ss,CNN);
DataSet ds = new DataSet();
oda.Fill(ds);
oda.Dispose();
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
sql="執行語句"
b = db.db.ExecuteSql1(sql);
}
if (b)
Maticsoft.Common.MessageBox.Show(Page, "導入完成!");
else
Maticsoft.Common.MessageBox.Show(Page, "導入失敗!");
導入時我們依舊使用OleDb驅動程序來訪問Excel文件。再次提醒讀者,此種方式只支持導入標准的Excel文件,這也是上面導出部分使用預先准備好的Excel模板文件的原因。
另外,以上演示僅針對Excel 2000-2003格式的文件,如果您要導入或導出的是Excel 2007文件(*.xlsx),那么您需要將連接字符串改為(可參考:http://www.connectionstrings.com/):
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=info.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES";
Provider=Microsoft.ACE.OLEDB.12.0;Data Source=info.xlsx;Extended Properties="Excel 12.0 Xml;HDR=YES";
-----經過實踐,上面的方法是可行,但有個問題:執行效率很低,超過255行的數據導出時,特別的慢(在網上查得是MS的限制).解決方法是:將INSERT部分不使用參數模式,而直接使用串拼接成INSERT的SQL語句,執行起來速度很快,導出時也很快,超過255時也很快,我僅測試過用SQL串語句生成並導出2000條,文件大小有3M,速度是不慢的,完成可以接受.而使用原方法,在256條時就感覺到慢了.
另外:OLEDB模式下可以先用CREATE TABLE生成SHEET1$這種EXCEL工作表,然后再INSERT數據,證實是可行的.這樣模板文件就只要一個空白的EXCEL文檔了.靈活性高很多.仍然要感謝原作者提供的方法.解決了我工作中的問題:)3Q