最近被這個搞的已經頭很大了看來會更大了
Excel匯入本來在Local可執行
但放到Web Server又完全行不通了
因為加了AjaxToolkits,exception被擋掉了
找了兩天,因緣際會,開啟非Domain認證的測試Portal
才看到網頁下方的狀態列出現了錯誤訊息
(平常Portal都會將IE的狀態列跟工具列給取消)
這才發現放到Server上還要注意權限的問題啊
(真是太忽略了啊~)
以下是要注意的事項
給以後有相關需求的人可以參考
不要像我一樣花了很久的時間啦
(畢竟青春有限哪~)
《怎樣將Excel匯入》
ASP.NET要將Excel匯入有三種方法
第一、利用MS JET OLEDB 4.0
第二、利用.NET COM元件中的Excel.dll
第三、XML
總結來說
OLEDB最快
用Excel的COM元件很耗Server的資源(超級大不推)
而XML則是太複雜了,所以略過XD(有興趣請看這篇囉!)
以下是Excel匯入的範例程式給大家參考囉!
一、OLEDB
折疊
複製
展開
using System.Data.OleDb; // 別忘引用OLEDB
///<summary>
/// ImportData Class 的摘要描述
///</summary>
public class ImportData
{
public ImportData()
{
//
// TODO: 在此加入建構函式的程式碼
//
}
//利用OleDB
//這裡只示範開啟單一工作表喔!
//param: 檔案路徑, 工作表名稱
public static System.Data.DataTable getDataTable(string xlsPath, string sheetName)
{
//OleDB連線,4.0版本
string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + xlsPath
+ ";Extended Properties='Excel 8.0;IMEX=1;'" ;
//語法就是大家都知道的SQL語法啦
string strComm = "SELECT * FROM [" + sheetName + "$]" ;
OleDbConnection dataConn = new OleDbConnection(strConn);
DataSet ds = new DataSet();
try
{
dataConn.Open();
//建立Adpater來承接select出來的DataSet
OleDbDataAdapter ta = new OleDbDataAdapter(strComm, dataConn);
ta.Fill(ds);
}
catch(Exception ex)
{
throw ex;
}
finally
{
//關閉連線
if (dataConn.State == ConnectionState.Open)
{ dataConn.Close(); }
}
System.Data.DataTable dt = null;
dt = ds.Tables[0];
//將Table回傳後就可以繼續做其他事情啦
return dt;
}
}
二、Excel
在使用前,必須先將COM元件中的EXCEL加入參考後才可以引用喔!
若機器上的Office是安裝在MS Visiual Studio之前的
可能到最後會無法在Bin資料夾中產生相關的.dll
此時可以先移除掉Office後重新安裝
然後再重新加入Excel參考即可
或者在加入參考時,直接用瀏覽將Excel.exe加入參考
(請參考步驟五)
折疊
觀看步驟
步驟一、在自己的專案上→右鍵→加入參考
步驟二、.Net頁籤裡選擇
『MicroSoft.Office.Interop.Excel』按下確定
步驟三、COM標籤選擇
『Microsoft Office 11.0 Object Library』後按下確定
步驟四、這樣在Bin的資料夾就會出現相關的.dll
(圖片是Office 2003的.dll)
步驟五、如果沒有在Bin裡出現.dll檔案,可能是Office安裝在MS Visiual Studio之前
此時可以選擇(1)移除Office後重新安裝Office,再重複步驟一至四即可
(成功率較高) (2)在步驟一,選擇瀏覽,找到MS Office資料夾下的Excel.exe加入參考
(如下圖)
折疊
複製
展開
using Excel = Microsoft.Office.Interop.Excel; // 引用Excel元件並將之命名為Excel///<summary>
/// ImportData Class 的摘要描述///</summary>public class ImportData{ public ImportData()
{ //
// TODO: 在此加入建構函式的程式碼
//
} //利用Office
//這裡只示範開啟單一工作表喔!
//param: 檔案路徑, 工作表名稱 public static System.Data.DataTable getExcelTable(string xlsPath, string sheetName)
{ DataTable dt = null();
Excel.Application xApp = new Excel.Application(); if (xApp != null)
{ try { //打開檔案 Excel.Workbook xBook = (Excel.Workbook)xApp.Workbooks.Open(xlsPath, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); if (xBook != null)
{ //xApp.visible = true; //工作表可見
//讀取工作表,只獨取第一個 Excel.Worksheet xSheet = (Excel.Worksheet)xBook.Worksheets[1]; if (xSheet != null)
{ //計算列數 int rowsCount = xSheet.UsedRange.Rows.Count; //計算欄數 int colsCount = xSheet.UsedRange.Columns.Count;
Excel.Range range = null ;
dt = new DataTable(); DataRow dr = null; //建立欄名 for (int i = 0; i < colsCount; i++)
{
range = (Excel.Range)xSheet.Cells[1, i + 1];
dt.Columns.Add(range.Value2.ToString());
} //建立資料 for (int j = 2; j <= rowsCount; j++)
{
dr = dt.NewRow(); for (int k = 1; k <= colsCount; k++)
{
range = (Excel.Range)xSheet.Cells[j, k];
//若儲存格值為Null會產生exception,固判斷並轉換之
dr[k - 1] = (range.Value2 == null) ? "" : range.Value2.ToString();
}
dt.Rows.Add(dr);
} //以上效率較慢,可用下列取代 reference Excel Performance
/**
DataTable arrdt = new DataTable();
Excel.Range xRange = xSheet.UsedRange;
//利用obj物件儲存值
object[,] valueArray = (object[,])xRange.get_Value(
Excel.XlRangeValueDataType.xlRangeValueDefault);
if (valueArray.Length > 0) //陣列資料總個數大於零
{
int y = valueArray.GetLength(0); //取得維度1的長度,即列數
int x = valueArray.GetLength(1); //取得維度2的長度,即欄數
//建立欄名
for (int arri = 1; arri <= x; arri++)
{ arrdt.Columns.Add(valueArray.GetValue(1, arri).ToString()); }
DataRow arrdr = new DataRow();
//建立資料
for (int arrj = 2; arrj <= y; arrj++)
{
arrdr = arrdt.NewRow();
for (int arrk = 1; arrk <= x; arrk++)
{ arrdr[arrk - 1] = (valueArray.GetValue(arrj, arrk) == null) ? "" : valueArray.GetValue(arrj, arrk).ToString(); }
arrdt.Rows.Add(arrdr);
}
}
**/ }
}
} catch(Exception ex)
{ throw ex;
} finally { //關閉Excel xApp.Workbooks.Close(); //強制回收 GC.SuppressFinalize(xApp);
} if (dt != null)
{ dt.TableName = sheetName; } return dt;
}
}
}
《Server端設定》
若是使用第二個方法寫匯入程式
那麼就必須考量到Server端上的設定
以防USER打不開Excel而徒勞無功
請特別注意,在Server上開啟Excel是很耗資源的事情
而且若沒有正常釋放開啟Excel的資源
很容易造成Server的Loading過重
所以,還是建議不要用第二個方法做匯入動作啊~
不過,還是要把設定的過程簡單講一下!
步驟一、開始→執行,輸入『dcomcnfg』後,將會開啟元件服務
步驟二、我的電腦→DCOM→MS Excel,點右鍵選擇內容,選擇『安全性』的頁籤
將『啟動及』權限改成『自訂』
點擊『編輯』加入網站使用的User帳號,如NetWork User、Asp User之類的
允許所有權限後,按下『套用』即可
《路徑:電腦→我的電腦→DCOM設定→MS Excel應用程式》
《關於64位元的作業系統》
由於微軟目前沒有可以支援64位元的MS JET OLEDB的元件
所以利用第一個方法匯入EXCEL完全是無輒
但若採用第二個方法匯入EXCEL
除了權限問題善待解決之外
基本上,在Server端使用Office是非常不明智的動作
而微軟也建議不要在Server使用Office,而用ADO來達成目的(就是OLEDB啦)
不但會耗費相當多的資源之外
若是Excel的釋放不完全
再加上USER變多
我看Server應該是承受不了吧
加上因為是多人使用EXCEL
也有可能會出現無法開啟EXCEL的狀況
所幸也有解決方法
就是將IIS切換到32位元的模式
那麼就可以順利使用OLEDB啦
以下是碎碎念:
其實我很不喜歡讓USER用Excel做匯入動作
1. 你無法預知USER會對EXCEL做了什麼,常常會因為格式不對而導致匯入失敗
然後苦命的就是系統維護者了
必須拿到USER的檔案重新做匯入才能知道問題所在(幸運的話)
但通常都是直接COPY到新的EXCEL後匯入就OK了
2. 檢查點很多
為了避免USER傳垃圾上來、為了保持資料的正確性
就必須針對Excel的資料全部再做一次檢查
如果資料少也就算了
偏偏資料一多的話,跑回圈就會花很久的時間
USER又不是很容易忍受...= =
明明程式都寫的好好的
USER還是不會想用的...
那乾脆以後都開發Excel匯入的程式好了~
按一個匯入鈕就什麼都幫你做的好好的,多好哇!
3. 瀏覽器設置或元件下載
隨著程式語言,很可能就需要下載匯入元件或去設定瀏覽器
最常見的就是瀏覽器裡的ActivX控鍵要全部選擇啟用
偏偏在這『資訊安全』意識抬頭年代
如果能什麼東西都擋掉是最好的啊
所以我也不是很希望寫哪種需要設定瀏覽器或元件下載的程式
因為你實在不能掌握User端的電腦到底做了什麼
但是你也知道
需求排山倒海的進攻
就算再怎麼不願意還是得為了USER方便開發匯入的功能
就算其實就要快放棄了還是打起精神硬著頭皮繼續找解決的方法
而微軟就是這麼的機車
開發了64位元,卻又沒有相關的64位元件
偏偏使用OLEDB來做EXCEL匯入與匯出的動作又很多
只會拼命的叫USER昇級
自己的升級配套措施又不完全
加上.Net安全性的考量
現在要用個EXCEL匯入
還真是圈圈叉叉的麻煩啊
如果有人有其他更好的方法請提供我
關於可以在64位元OS上,利用.Net C#匯入Excel到Grid
而不會耗費太多資源的解決方法
我會很感激你的!
留言列表