大凡微軟的導(dǎo)入導(dǎo)出無(wú)論是asp.net、winform、抑或是wpf導(dǎo)出的方法大致相同。無(wú)非就是實(shí)例化Excel類,創(chuàng)建工作簿,創(chuàng)建工作表,然后保存或提取數(shù)據(jù)。以至于如此簡(jiǎn)便的操作感覺(jué)都變得理所當(dāng)然了。
PS:以下基于VS2010+Framework 4.0
先看看wpf是如何導(dǎo)出數(shù)據(jù)到Excel文件里面的。
導(dǎo)出數(shù)據(jù)到Excel
首先引用.net 4.0的組件Microsoft.Office.Interop.Excel;
private void btnExport_Click(object sender, RoutedEventArgs e)
{
//首先模擬建立將要導(dǎo)出的數(shù)據(jù),這些數(shù)據(jù)都存于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)行數(shù)據(jù)導(dǎo)出
//excelWS.Cells.NumberFormat = "@"; // 如果數(shù)據(jù)中存在數(shù)字類型 可以讓它變文本格式顯示
//將數(shù)據(jù)導(dǎo)入到工作表的單元格
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)程
}
注意:因?yàn)槲覀儜?yīng)用了Microsoft.Office.Interop.Excel這個(gè)組件,所以里面有些類名會(huì)和System.Data中的類名相同,就容易出現(xiàn)程序運(yùn)行起來(lái)報(bào)錯(cuò)。那么我們需要做的就是細(xì)化這些類到底屬于哪個(gè)組件,就像上面的System.Data.DataTable。大家不必?fù)?dān)心并不熟悉這些組件的名稱,VS2010會(huì)給出智能提示。
有時(shí)候Excel會(huì)長(zhǎ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í)就是將其引用計(jì)數(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的導(dǎo)出工作,那么如果我們需要要求設(shè)計(jì)導(dǎo)出的樣式我們還可以用到下面代碼。
導(dǎo)出Excel的樣式設(shè)計(jì)
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)行數(shù)據(jù)導(dǎo)出
Range range = null;
#region 表格屬性設(shè)置
excelWS.Name = "sanjiawan"; //設(shè)置工作表名
range = (Range)excelWS.get_Range("A1", "E1"); //獲取Excel多個(gè)單元格區(qū)域:本例做為Excel表頭
range.Merge(0); //單元格合并動(dòng)作 要配合上面的get_Range()進(jìn)行設(shè)計(jì)
excelWS.Cells[1, 1] = "Excel單元格賦值"; //Excel單元格賦值
range.Font.Size = 15; //設(shè)置字體大小
range.Font.Underline = true; //設(shè)置字體是否有下劃線
range.Font.Name="黑體"; //設(shè)置字體的種類
range.HorizontalAlignment=XlHAlign.xlHAlignCenter; //設(shè)置字體在單元格內(nèi)的對(duì)其方式
range.ColumnWidth=15; //設(shè)置單元格的寬度
range.Cells.Interior.Color = System.Drawing.Color.FromArgb(255, 204, 153).ToArgb(); //設(shè)置單元格的背景色
range.Borders.LineStyle=1; //設(shè)置單元格邊框的粗細(xì)
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; //設(shè)置單元格上邊框?yàn)闊o(wú)邊框
range.EntireColumn.AutoFit(); //自動(dòng)調(diào)整列寬
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
//如果需要用到上面的這些樣式 我們還有一種方法導(dǎo)出的方法可以運(yùn)用到Range設(shè)計(jì)出的樣式
//以下代碼可以替換上面的“將數(shù)據(jù)導(dǎo)入到工作表的單元格”操作
Range range = null;
range = excelWS.get_Range("A1", System.Type.Missing); //設(shè)置表格左上角開(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();
}
}
導(dǎo)出的功能就到這了,接下來(lái)我們來(lái)看下Excel文件中的數(shù)據(jù)是如何導(dǎo)入到程序中去的
Excel數(shù)據(jù)導(dǎo)入到程序
先看下如何獲取到的Excel數(shù)據(jù)
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è)連續(xù)字符串,Driver={Driver do Microsoft Excel(*.xls)} 這種連接寫法不需要?jiǎng)?chuàng)建一個(gè)數(shù)據(jù)源DSN,DRIVERID表示驅(qū)動(dòng)ID,Excel2003后都使用790,
//FIL表示Excel文件類型,Excel2007用excel 8.0,MaxBufferSize表示緩存大小, 如果你的文件是2010版本的,也許會(huì)報(bào)錯(cuò),所以要找到合適版本的參數(shù)設(shè)置。
connString += "DBQ=" + pPath; //DBQ表示讀取Excel的文件名(全路徑)
OdbcConnection conn = new OdbcConnection(connString);
OdbcCommand cmd = new OdbcCommand();
cmd.Connection = conn;
//獲取Excel中第一個(gè)Sheet名稱,作為查詢時(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數(shù)據(jù)中的內(nèi)容,保存在DataTable中
}
catch (Exception x)
{
ds = null;
throw new Exception("從Excel文件中獲取數(shù)據(jù)時(shí)發(fā)生錯(cuò)誤!可能是Excel版本問(wèn)題,可以考慮降低版本或者修改連接字符串值");
}
finally
{
cmd.Dispose();
cmd = null;
da.Dispose();
da = null;
if (conn.State == ConnectionState.Open)
{
conn.Close();
}
conn = null;
}
}
// 獲取工作表名稱
private string GetExcelSheetName(string pPath)
{
//打開(kāi)一個(gè)Excel應(yīng)用
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應(yīng)用時(shí)發(fā)生錯(cuò)誤!");
}
excelWBs = excelApp.Workbooks;
//打開(kāi)一個(gè)現(xiàn)有的工作薄
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ā)生錯(cuò)誤!");
}
finally
{
pObj = null;
}
}
數(shù)據(jù)我們已經(jīng)獲取到了,接下來(lái)我們?cè)谖覀兂绦驊?yīng)用中只需要傳遞文件的路徑就可以直接獲取到里面的數(shù)據(jù)了
{
System.Data.DataTable dt = LoadExcel("D:\\sanjiawan"); //通過(guò)路徑獲取到的數(shù)據(jù)
//此時(shí)我們就可以用這數(shù)據(jù)進(jìn)行處理了,比如綁定到顯示數(shù)據(jù)的控件當(dāng)中去
MessageBox.Show("導(dǎo)入成功");
}
通過(guò)獲取Excel數(shù)據(jù)會(huì)發(fā)現(xiàn),其操作機(jī)制和數(shù)據(jù)庫(kù)操作機(jī)制幾乎一樣。我們可以把Excel當(dāng)成是數(shù)據(jù)庫(kù)來(lái)進(jìn)行操作。
無(wú)論是導(dǎo)入還是導(dǎo)出,我們都看到了釋放資源的操作。這樣可以做到及時(shí)的進(jìn)程優(yōu)化,從而不影響程序的性能。
希望對(duì)大家有所幫助
本文來(lái)自sanjiawan的博客,原文地址:http://blog.csdn.net/sanjiawan/article/details/6818921