大凡微軟的導入導出無(wú)論是asp.net、winform、抑或是wpf導出的方法大致相同。無(wú)非就是實(shí)例化Excel類(lèi),創(chuàng )建工作簿,創(chuàng )建工作表,然后保存或提取數據。以至于如此簡(jiǎn)便的操作感覺(jué)都變得理所當然了。
PS:以下基于VS2010+Framework 4.0
先看看wpf是如何導出數據到Excel文件里面的。
導出數據到Excel
首先引用.net 4.0的組件Microsoft.Office.Interop.Excel;
private void btnExport_Click(object sender, RoutedEventArgs e)
{
//首先模擬建立將要導出的數據,這些數據都存于DataTable中
System.Data.DataTable dt = new System.Data.DataTable();
dt.Columns.Add("ID", typeof(int));
dt.Columns.Add("NickName", typeof(string));
dt.Columns.Add("QNumber", typeof(string));
DataRow row = dt.NewRow();
row["ID"] = 1;
row["NickName"] = "sanjiawan";
row["QNumber"] = "12345678";
dt.Rows.Add(row);
row = dt.NewRow();
row["ID"] = 2;
row["NickName"] = "人物2";
row["QNumber"] = "9058307";
dt.Rows.Add(row);
//創(chuàng )建Excel
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Workbook excelWB = excelApp.Workbooks.Add(System.Type.Missing); //創(chuàng )建工作簿(WorkBook:即Excel文件主體本身)
Worksheet excelWS = (Worksheet)excelWB.Worksheets[1]; //創(chuàng )建工作表(即Excel里的子表sheet) 1表示在子表sheet1里進(jìn)行數據導出
//excelWS.Cells.NumberFormat = "@"; // 如果數據中存在數字類(lèi)型 可以讓它變文本格式顯示
//將數據導入到工作表的單元格
for (int i = 0; i < dt.Rows.Count; i++)
{
for (int j = 0; j < dt.Columns.Count; j++)
{
excelWS.Cells[i + 1, j + 1] = dt.Rows[i][j].ToString(); //Excel單元格第一個(gè)從索引1開(kāi)始
}
}
excelWB.SaveAs("D:\\sanjiawan.xlsx"); //將其進(jìn)行保存到指定的路徑
excelWB.Close();
excelApp.Quit(); //KillAllExcel(excelApp); 釋放可能還沒(méi)釋放的進(jìn)程
}
注意:因為我們應用了Microsoft.Office.Interop.Excel這個(gè)組件,所以里面有些類(lèi)名會(huì )和System.Data中的類(lèi)名相同,就容易出現程序運行起來(lái)報錯。那么我們需要做的就是細化這些類(lèi)到底屬于哪個(gè)組件,就像上面的System.Data.DataTable。大家不必擔心并不熟悉這些組件的名稱(chēng),VS2010會(huì )給出智能提示。
有時(shí)候Excel會(huì )長(cháng)時(shí)間占用進(jìn)程,那么我們需要做釋放進(jìn)程的操作。
public bool KillAllExcel(Microsoft.Office.Interop.Excel.Application excelApp)
{
try
{
if (excelApp != null)
{
excelApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp);
//釋放COM組件,其實(shí)就是將其引用計數減1
//System.Diagnostics.Process theProc;
foreach (System.Diagnostics.Process theProc in System.Diagnostics.Process.GetProcessesByName("EXCEL"))
{
//先關(guān)閉圖形窗口。如果關(guān)閉失敗.有的時(shí)候在狀態(tài)里看不到圖形窗口的excel了,
//但是在進(jìn)程里仍然有EXCEL.EXE的進(jìn)程存在,那么就需要釋放它
if (theProc.CloseMainWindow() == false)
{
theProc.Kill();
}
}
excelApp = null;
return true;
}
}
catch
{
return false;
}
return true;
}
#endregion
從上面的代碼來(lái)看,很自然的就完成了Excel的導出工作,那么如果我們需要要求設計導出的樣式我們還可以用到下面代碼。
導出Excel的樣式設計
Workbook excelWB = excelApp.Workbooks.Add(System.Type.Missing);//創(chuàng )建工作簿(WorkBook:即Excel文件主體本身)
Worksheet excelWS = (Worksheet)excelWB.Worksheets[1];//創(chuàng )建工作表(即Excel里的子表sheet) 1表示在子表sheet1里進(jìn)行數據導出
Range range = null;
#region 表格屬性設置
excelWS.Name = "sanjiawan"; //設置工作表名
range = (Range)excelWS.get_Range("A1", "E1"); //獲取Excel多個(gè)單元格區域:本例做為Excel表頭
range.Merge(0); //單元格合并動(dòng)作 要配合上面的get_Range()進(jìn)行設計
excelWS.Cells[1, 1] = "Excel單元格賦值"; //Excel單元格賦值
range.Font.Size = 15; //設置字體大小
range.Font.Underline = true; //設置字體是否有下劃線(xiàn)
range.Font.Name="黑體"; //設置字體的種類(lèi)
range.HorizontalAlignment=XlHAlign.xlHAlignCenter; //設置字體在單元格內的對其方式
range.ColumnWidth=15; //設置單元格的寬度
range.Cells.Interior.Color = System.Drawing.Color.FromArgb(255, 204, 153).ToArgb(); //設置單元格的背景色
range.Borders.LineStyle=1; //設置單元格邊框的粗細
range.BorderAround(XlLineStyle.xlContinuous, XlBorderWeight.xlThick, XlColorIndex.xlColorIndexAutomatic, System.Drawing.Color.FromArgb(255, 204, 153).ToArgb()); //給單元格加邊框
range.Borders.get_Item(Microsoft.Office.Interop.Excel.XlBordersIndex.xlEdgeTop).LineStyle = Microsoft.Office.Interop.Excel.XlLineStyle.xlLineStyleNone; //設置單元格上邊框為無(wú)邊框
range.EntireColumn.AutoFit(); //自動(dòng)調整列寬
range.WrapText = true; //文本自動(dòng)換行
range.Interior.ColorIndex = 39; //填充顏色為淡紫色
range.Font.Color = System.Drawing.Color.FromArgb(255, 204, 153).ToArgb(); //字體顏色
excelApp.DisplayAlerts = false; //保存Excel的時(shí)候,不彈出是否保存的窗口直接進(jìn)行保存
#endregion
//如果需要用到上面的這些樣式 我們還有一種方法導出的方法可以運用到Range設計出的樣式
//以下代碼可以替換上面的“將數據導入到工作表的單元格”操作
Range range = null;
range = excelWS.get_Range("A1", System.Type.Missing); //設置表格左上角開(kāi)始顯示的位置
for (int i = 0; i < table.Rows.Count; i++)
{
for (int j = 0; j < table.Columns.Count; j++)
{
range.get_Offset(i, j).Cells.Value = table.Rows[i][j].ToString();
}
}
導出的功能就到這了,接下來(lái)我們來(lái)看下Excel文件中的數據是如何導入到程序中去的
Excel數據導入到程序
先看下如何獲取到的Excel數據
public System.Data.DataTable LoadExcel(string pPath)
{
string connString = "Driver={Driver do Microsoft Excel(*.xls)};DriverId=790;SafeTransactions=0;ReadOnly=1;MaxScanRows=16;Threads=3;MaxBufferSize=2024;UserCommitSync=Yes;FIL=excel 8.0;PageTimeout=5;"; //連接字符串
//簡(jiǎn)單解釋下這個(gè)連續字符串,Driver={Driver do Microsoft Excel(*.xls)} 這種連接寫(xiě)法不需要創(chuàng )建一個(gè)數據源DSN,DRIVERID表示驅動(dòng)ID,Excel2003后都使用790,
//FIL表示Excel文件類(lèi)型,Excel2007用excel 8.0,MaxBufferSize表示緩存大小, 如果你的文件是2010版本的,也許會(huì )報錯,所以要找到合適版本的參數設置。
connString += "DBQ=" + pPath; //DBQ表示讀取Excel的文件名(全路徑)
OdbcConnection conn = new OdbcConnection(connString);
OdbcCommand cmd = new OdbcCommand();
cmd.Connection = conn;
//獲取Excel中第一個(gè)Sheet名稱(chēng),作為查詢(xún)時(shí)的表名
string sheetName = this.GetExcelSheetName(pPath);
string sql = "select * from [" + sheetName.Replace('.', '#') + "$]";
cmd.CommandText = sql;
OdbcDataAdapter da = new OdbcDataAdapter(cmd);
DataSet ds = new DataSet();
try
{
da.Fill(ds);
return ds.Tables[0]; //返回Excel數據中的內容,保存在DataTable中
}
catch (Exception x)
{
ds = null;
throw new Exception("從Excel文件中獲取數據時(shí)發(fā)生錯誤!可能是Excel版本問(wèn)題,可以考慮降低版本或者修改連接字符串值");
}
finally
{
cmd.Dispose();
cmd = null;
da.Dispose();
da = null;
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
conn = null;
}
}
// 獲取工作表名稱(chēng)
private string GetExcelSheetName(string pPath)
{
//打開(kāi)一個(gè)Excel應用
Microsoft.Office.Interop.Excel.Application excelApp;
Workbook excelWB;//創(chuàng )建工作簿(WorkBook:即Excel文件主體本身)
Workbooks excelWBs;
Worksheet excelWS;//創(chuàng )建工作表(即Excel里的子表sheet)
Sheets excelSts;
excelApp = new Microsoft.Office.Interop.Excel.Application();
if (excelApp == null)
{
throw new Exception("打開(kāi)Excel應用時(shí)發(fā)生錯誤!");
}
excelWBs = excelApp.Workbooks;
//打開(kāi)一個(gè)現有的工作薄
excelWB = excelWBs.Add(pPath);
excelSts = excelWB.Sheets;
//選擇第一個(gè)Sheet頁(yè)
excelWS = excelSts.get_Item(1);
string sheetName = excelWS.Name;
ReleaseCOM(excelWS);
ReleaseCOM(excelSts);
ReleaseCOM(excelWB);
ReleaseCOM(excelWBs);
excelApp.Quit();
ReleaseCOM(excelApp);
return sheetName;
}
// 釋放資源
private void ReleaseCOM(object pObj)
{
try
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(pObj);
}
catch
{
throw new Exception("釋放資源時(shí)發(fā)生錯誤!");
}
finally
{
pObj = null;
}
}
數據我們已經(jīng)獲取到了,接下來(lái)我們在我們程序應用中只需要傳遞文件的路徑就可以直接獲取到里面的數據了
{
System.Data.DataTable dt = LoadExcel("D:\\sanjiawan"); //通過(guò)路徑獲取到的數據
//此時(shí)我們就可以用這數據進(jìn)行處理了,比如綁定到顯示數據的控件當中去
MessageBox.Show("導入成功");
}
通過(guò)獲取Excel數據會(huì )發(fā)現,其操作機制和數據庫操作機制幾乎一樣。我們可以把Excel當成是數據庫來(lái)進(jìn)行操作。
無(wú)論是導入還是導出,我們都看到了釋放資源的操作。這樣可以做到及時(shí)的進(jìn)程優(yōu)化,從而不影響程序的性能。
希望對大家有所幫助
本文來(lái)自sanjiawan的博客,原文地址:http://blog.csdn.net/sanjiawan/article/details/6818921

