大凡微软的导入导出无论是asp.net、winform、抑或是wpf导出的方法大致相同。无非就是实例化Excel类,创建工作簿,创建工作表,然后保存或提取数据。以至于如此简便的操作感觉都变得理所当然了。
PS:以下基于VS2010+Framework 4.0
先看看wpf是如何导出数据到Excel文件里面的。
导出数据到Excel
首先引用.net 4.0的组件Microsoft.Office.Interop.Excel;
using 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); //创建Excel Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application(); Workbook excelWB = excelApp.Workbooks.Add(System.Type.Missing); //创建工作簿(WorkBook:即Excel文件主体本身) Worksheet excelWS = (Worksheet)excelWB.Worksheets[1]; //创建工作表(即Excel里的子表sheet) 1表示在子表sheet1里进行数据导出 //excelWS.Cells.NumberFormat = "@"; // 如果数据中存在数字类型 可以让它变文本格式显示 //将数据导入到工作表的单元格 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单元格第一个从索引1开始 } } excelWB.SaveAs("D:\\sanjiawan.xlsx"); //将其进行保存到指定的路径 excelWB.Close(); excelApp.Quit(); //KillAllExcel(excelApp); 释放可能还没释放的进程 }
注意:因为我们应用了Microsoft.Office.Interop.Excel这个组件,所以里面有些类名会和System.Data中的类名相同,就容易出现程序运行起来报错。那么我们需要做的就是细化这些类到底属于哪个组件,就像上面的System.Data.DataTable。大家不必担心并不熟悉这些组件的名称,VS2010会给出智能提示。
有时候Excel会长时间占用进程,那么我们需要做释放进程的操作。
#region 释放Excel进程 public bool KillAllExcel(Microsoft.Office.Interop.Excel.Application excelApp) { try { if (excelApp != null) { excelApp.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(excelApp); //释放COM组件,其实就是将其引用计数减1 //System.Diagnostics.Process theProc; foreach (System.Diagnostics.Process theProc in System.Diagnostics.Process.GetProcessesByName("EXCEL")) { //先关闭图形窗口。如果关闭失败.有的时候在状态里看不到图形窗口的excel了, //但是在进程里仍然有EXCEL.EXE的进程存在,那么就需要释放它 if (theProc.CloseMainWindow() == false) { theProc.Kill(); } } excelApp = null; return true; } } catch { return false; } return true; } #endregion
从上面的代码来看,很自然的就完成了Excel的导出工作,那么如果我们需要要求设计导出的样式我们还可以用到下面代码。
导出Excel的样式设计
Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application(); Workbook excelWB = excelApp.Workbooks.Add(System.Type.Missing);//创建工作簿(WorkBook:即Excel文件主体本身) Worksheet excelWS = (Worksheet)excelWB.Worksheets[1];//创建工作表(即Excel里的子表sheet) 1表示在子表sheet1里进行数据导出 Range range = null; #region 表格属性设置 excelWS.Name = "sanjiawan"; //设置工作表名 range = (Range)excelWS.get_Range("A1", "E1"); //获取Excel多个单元格区域:本例做为Excel表头 range.Merge(0); //单元格合并动作 要配合上面的get_Range()进行设计 excelWS.Cells[1, 1] = "Excel单元格赋值"; //Excel单元格赋值 range.Font.Size = 15; //设置字体大小 range.Font.Underline = true; //设置字体是否有下划线 range.Font.Name="黑体"; //设置字体的种类 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; //设置单元格上边框为无边框 range.EntireColumn.AutoFit(); //自动调整列宽 range.WrapText = true; //文本自动换行 range.Interior.ColorIndex = 39; //填充颜色为淡紫色 range.Font.Color = System.Drawing.Color.FromArgb(255, 204, 153).ToArgb(); //字体颜色 excelApp.DisplayAlerts = false; //保存Excel的时候,不弹出是否保存的窗口直接进行保存 #endregion //如果需要用到上面的这些样式 我们还有一种方法导出的方法可以运用到Range设计出的样式 //以下代码可以替换上面的“将数据导入到工作表的单元格”操作 Range range = null; range = excelWS.get_Range("A1", System.Type.Missing); //设置表格左上角开始显示的位置 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(); } }
导出的功能就到这了,接下来我们来看下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;"; //连接字符串 //简单解释下这个连续字符串,Driver={Driver do Microsoft Excel(*.xls)} 这种连接写法不需要创建一个数据源DSN,DRIVERID表示驱动ID,Excel2003后都使用790, //FIL表示Excel文件类型,Excel2007用excel 8.0,MaxBufferSize表示缓存大小, 如果你的文件是2010版本的,也许会报错,所以要找到合适版本的参数设置。 connString += "DBQ=" + pPath; //DBQ表示读取Excel的文件名(全路径) OdbcConnection conn = new OdbcConnection(connString); OdbcCommand cmd = new OdbcCommand(); cmd.Connection = conn; //获取Excel中第一个Sheet名称,作为查询时的表名 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文件中获取数据时发生错误!可能是Excel版本问题,可以考虑降低版本或者修改连接字符串值"); } finally { cmd.Dispose(); cmd = null; da.Dispose(); da = null; if (conn.State == ConnectionState.Open) { conn.Close(); } conn = null; } } // 获取工作表名称 private string GetExcelSheetName(string pPath) { //打开一个Excel应用 Microsoft.Office.Interop.Excel.Application excelApp; Workbook excelWB;//创建工作簿(WorkBook:即Excel文件主体本身) Workbooks excelWBs; Worksheet excelWS;//创建工作表(即Excel里的子表sheet) Sheets excelSts; excelApp = new Microsoft.Office.Interop.Excel.Application(); if (excelApp == null) { throw new Exception("打开Excel应用时发生错误!"); } excelWBs = excelApp.Workbooks; //打开一个现有的工作薄 excelWB = excelWBs.Add(pPath); excelSts = excelWB.Sheets; //选择第一个Sheet页 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("释放资源时发生错误!"); } finally { pObj = null; } }
数据我们已经获取到了,接下来我们在我们程序应用中只需要传递文件的路径就可以直接获取到里面的数据了
private void btnImport_Click(object sender, RoutedEventArgs e) { System.Data.DataTable dt = LoadExcel("D:\\sanjiawan"); //通过路径获取到的数据 //此时我们就可以用这数据进行处理了,比如绑定到显示数据的控件当中去 MessageBox.Show("导入成功"); }
通过获取Excel数据会发现,其操作机制和数据库操作机制几乎一样。我们可以把Excel当成是数据库来进行操作。
无论是导入还是导出,我们都看到了释放资源的操作。这样可以做到及时的进程优化,从而不影响程序的性能。
希望对大家有所帮助