轉化成Access檔案下載的例項

weixin_34262482發表於2009-05-16
昨天有位朋友問起一個問題,客戶相要一個Access格式的資料,現在的情況是程式已經實現了匯出Excel,問題轉化成了Excel怎麼樣轉成Access,這點實現起來相對來說比較容易,office本身就有這個功能,但問題是,從web頁面匯出的Excel不能很相容的導成Access,這是一點,還有一個方面是讓客戶去做這個轉化工作不是太好,為了提高使用者體驗,最好是用程式碼實現了。
能不能一下子轉成Access出來呢?這是我一下想的的問題,如果有的話,客戶就省很多力氣了,但找了一些相關資料,沒有找到把GridView直接導成Access的,也就是客戶端比較難實現。想到這裡,客戶端難實現,服務端應該好實現吧,先把我資料庫中的資料轉化成一個access的檔案,然後客戶再下載下來,這個相對來說比較容易實現。
主要思路:在服務端,把一種資料中的資料,生成access檔案,下載給客戶商。
分步實現:
第一:建立Access檔案
第二:複製資料庫格式,在Access檔案中建立新表
第三:複製資料到Access檔案中
第四:實現下載
建立Access檔案
原本建立Access檔案的語法比較簡單
首先引入名稱空間using ADOX;    該名稱空間位於Interop.ADOX.dll檔案中,
ADOX.CatalogClass cat = new ADOX.CatalogClass();
     cat.Create(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=D:\Data.mdb;");
這樣,就能在指定的D盤下建立一個Data.mdb的Access檔案。檔案是建立好了,但引來了後續的一些問題,因為我們在實現下載時,要用到Response.WriteFile(檔案),此時的Response.WriteFile()要求是獨立享有這個檔案操作許可權,但前期建立時的程式一直釋放不掉(如果誰有好的方法可以告我如何釋放),這裡還得考慮多人操作,有可能同時有多要在建立Access檔案或釋放這個檔案。這樣就會出現執行時錯誤,提示該檔案被其他程式獨佔。
為了解決這個問題,同時還涉及到防止程式的釋放帶來的其他問題,這裡我捌了一下彎來實現,先建立一個Data.mdb存放在網站的App_Data資料夾下,後期所有客戶端要下匯出Access表,都在這裡拷貝一份,然後對新檔案進行操作。另外再新建一個DownLoad資料夾用來存使用者下載的Access檔案。
程式碼如下:
//拷貝Access資料表,不移動
string newfile=DateTime .Now.ToString ("MMddhhmmss")+".mdb";
File.Copy(Server.MapPath("~") + @"\App_Data\data.mdb", Server.MapPath("~") + @"\App_Data\" + newfile);
複製資料庫格式,在Access檔案中建立新表
在這裡,我是從SQL Server中生表生成Access的表,當然,可以用相關的工具完成些功能,但如果對方的資料庫不是SQL Server可能就不太好用了。這裡選擇SQL Server只是一種演示資料庫。
我們知道,建立一張表有幾個要素,表名,欄位名,欄位型別,欄位大小,這裡,我們得先從SQL Server中查出該表的這些要素,然後建立Access表,如果是其他資料庫,就要相應的轉化一下對應的資料型別格式。
程式碼實現如下:
在web.config中建立兩個連線字串
<add name="AccessConStr" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=|DataDirectory|\data.mdb;Persist Security Info=True;" providerName="System.Data.OleDb"/>
<add name="SqlConStr" connectionString="server=.;database=cum_data;uid=sa;pwd=sa;" providerName="System.Data.SqlClient"/>
這兩個字元,一個用來連線SQL Server資料庫一個用來連線我們建立的Access資料庫。
接來檢視導庫的程式碼:
string SqlConstr = ConfigurationManager.ConnectionStrings["SqlConStr"].ConnectionString;
string sql = "select column_name,data_type,character_maximum_length from information_schema.columns where table_name='kh'";
SqlConnection con = new SqlConnection(SqlConstr);
SqlCommand cmd = new SqlCommand(sql, con);
string AccSql = "";//用來組合生成Access表的SQL語句
try
{
con.Open();
SqlDataReader DR = cmd.ExecuteReader();
while (DR.Read())
{
if (DR.GetValue(2).ToString() == "")
{
AccSql += DR.GetValue(0).ToString() + " " + DR.GetValue(1).ToString() + ",";
}
else
{
AccSql += DR.GetValue(0).ToString() + " " + DR.GetValue(1).ToString() + "(" + DR.GetValue(2).ToString() + "),";
}
}
}
catch
{ }
finally
{
con.Close();
}
AccSql = AccSql.Substring(0, AccSql.Length - 1);
string AccConstr = ConfigurationManager.ConnectionStrings["AccessConStr"].ConnectionString.Replace ("data.mdb",newfile );
OleDbConnection CON = new OleDbConnection(AccConstr);
OleDbCommand CMD = new OleDbCommand();
CMD.Connection = CON;
try
{
CON.Open();
CMD.CommandText = "create table kh(" + AccSql + ")";
CMD.ExecuteNonQuery();
}
catch
{ }
finally
{
CON.Close();
}
在上述程式碼中,SQL語句是比較關鍵的,“select column_name,data_type,character_maximum_length from information_schema.columns where table_name='kh'”,本SQL查詢語句是從把原表的欄位名,欄位型別,欄位大小查詢出來,當然,不同的資料庫,這個語句不近相同。
複製資料到Access檔案中
到現在,我們已建立好了資料表格式,接下來,就是要把資料導到Access中。
程式碼如下:
SqlDataAdapter DA = new SqlDataAdapter("select * from kh", SqlConstr);
DataTable DT = new DataTable();
DA.Fill(DT);
foreach (DataRow DRR in DT.Rows)
{
DRR.SetAdded();
}
OleDbDataAdapter ODA = new OleDbDataAdapter("select * from kh", AccConstr);
OleDbCommandBuilder cmb = new OleDbCommandBuilder(ODA);
ODA.Update(DT);
這裡用到了Adapter的一個方法,Update,可以把DataTable中RowState為Add的資料提交會資料庫,這樣做起來相對要省力些。
在裡,要把有資料的Access檔案,移動到DownLoad資料夾下
File.Move(Server.MapPath("~") + @"\App_Data\"+newfile , Server.MapPath("~") + @"\DownLoad\" + newfile);
實現下載
Response.Clear();
Response.ClearHeaders();
Response.Charset = "utf-8";
Response.Buffer = false ;
this.EnableViewState = false;
Response.ContentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.AppendHeader("Content-Disposition", "attachment;filename=" + newfile);
Response.WriteFile(Server.MapPath("~") + @"\DownLoad\" + newfile ,true );
Response.Flush();
Response.Close();
Response.End();
下載程式碼是通用的程式碼,這裡不作說明。
整個解決方案就是把檔案操作,資料操作,檔案下載有機的結合在一起,實現這個使用者下載Access檔案的需求。
其實有時候我們去實現一個問題的時候,總體是有一定難度的,但當我們想辦法,通過分解問題來實現的時候,相對來說就比較簡單的實現了。

相關文章