第一種:流導出
SaveFileDialog exe = new SaveFileDialog(); exe.Filter = "Execl files (*.xls)|*.xls"; exe.FilterIndex = 0; exe.RestoreDirectory = true; //exe.CreatePrompt = true; exe.Title = "Export Excel File"; exe.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); exe.FileName = string.Format("{0}_{1}", DateTime.Now.ToString("yyyy-MM-dd HH時mm分ss秒"), "導出"); DialogResult dr = exe.ShowDialog(); if (dr != DialogResult.OK) { return; } Stream ms; ms = exe.OpenFile(); StreamWriter sw = new StreamWriter(ms, System.Text.Encoding.GetEncoding(-0)); string str = ""; try { for (int i = 0; i < dtb.Columns.Count; i++) { if (i > 0) { str += "\t"; } str += dtb.Columns[i].HeaderText; } sw.WriteLine(str); for (int j = 0; j < dtb.Rows.Count; j++) { string temp = ""; for (int k = 0; k < dtb.Columns.Count; k++) { if (k > 0) { temp += "\t"; } string cell = dtb.Rows[j].Cells[k].Value.ToString(); cell = cell.Replace(" ", "").Replace("\r", "").Replace("\n", "").Replace("\r\n", ""); temp += cell; } sw.WriteLine(temp); } sw.Close(); ms.Close(); } catch (Exception ex) { MessageBox.Show(ex.Message); return; } finally { sw.Close(); ms.Close(); }
第二種:使用 Microsoft.Office.Interop.Excel.dll
Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application(); if (xlApp == null) { MessageBox.Show("無法創建Excel對象,可能您的機子未安裝Excel"); return; } try { Workbooks wbs = xlApp.Workbooks; Workbook wb = wbs.Add(XlWBATemplate.xlWBATWorksheet); Worksheet ws = (Worksheet)wb.Worksheets[1]; Range range = xlApp.Range[ws.Cells[1, 1], ws.Cells[1, colcount]]; range.Font.Size = 10; range.Font.Bold = true; range.Interior.ColorIndex = 15; range.HorizontalAlignment = Constants.xlCenter; object[,] obj = new object[rowcount + 1, colcount]; foreach (DataGridViewColumn col in dtb.Columns) { obj[rowindex, colindex++] = col.HeaderText; } for (rowindex = 1; rowindex < rowcount + 1; rowindex++) { for (colindex = 0; colindex < colcount; colindex++) { obj[rowindex, colindex] = "'" + dtb[colindex, rowindex - 1].Value; } System.Windows.Forms.Application.DoEvents(); } range = ws.Range[xlApp.Cells[1, 1], xlApp.Cells[rowcount + 1, colcount]]; range.Value2 = obj; wb.Saved = true; wb.SaveCopyAs(exe.FileName); //for (int i = 0; i < dtb.ColumnCount; i++) //{ // if (dtb.Columns[i].Visible) // { // colindex++; // ws.Cells[1, colindex] = dtb.Columns[i].HeaderText; // } //} //for (int r = 0; r < dtb.Rows.Count; r++) //{ // colindex = 0; // for (int i = 0; i < dtb.ColumnCount; i++) // { // if (dtb.Columns[i].Visible) // { // colindex++; // ws.Cells[r + 2, colindex] = "'" + dtb.Rows[r].Cells[i].Value; // } // } //} //System.Windows.Forms.Application.DoEvents(); //wb.SaveAs(exe.FileName); } catch (Exception ex) { MessageBox.Show("導出文件時出錯,文件可能正被打開!\n" + ex.Message); } finally { xlApp.Quit(); GC.Collect(); }
這兩種方法導出 .xlsx 格式的 Excel 文件時,沒辦法打開。導出 .xls 格式的,會提示文件格式和擴展名不匹配(沒找到辦法解決,找到的園友留下言),但是可以打開的。
第二種電腦必須要安裝 office,而且導出速度慢,導出大數據時性能很差。
第三種:Microsoft.Jet.OLEDB
// Excel 2003 版本連接字符串 string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:/xxx.xls;Extended Properties='Excel 8.0;HDR=Yes;IMEX=2;'"; // Excel 2007 以上版本連接字符串 string strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:/xxx.xlsx;Extended Properties='Excel 12.0;HDR=Yes;IMEX=2;'";
Provider:驅動程序名稱
Data Source:指定 Excel 文件的路徑
Extended Properties:Excel 8.0 針對 Excel 2000 及以上版本;Excel 12.0 針對 Excel 2007 及以上版本。
HDR:Yes 表示第一行包含列名,在計算行數時就不包含第一行。NO 則完全相反。
IMEX:0 寫入模式;1 讀取模式;2 讀寫模式。如果報錯為“不能修改表 sheet1 的設計。它在只讀數據庫中”,那就去掉這個,問題解決。
private string ToExcel(DataGridView dtb,string filename) { try { int colcount = dtb.ColumnCount; int rowcount = dtb.RowCount; if (rowcount > 0) { string path = @"export\"; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } string pfilename = path + filename + ".xls"; File.Copy(path + "model.xls", pfilename); //string strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + pfilename + ";Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=2;\""; using (OleDbConnection ole =new OleDbConnection()) { //ole.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + pfilename + ";Extended Properties=\"Excel 12.0 Xml;HDR=Yes\""; ole.ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + pfilename + ";Extended Properties=\"Excel 8.0;HDR=Yes;\""; ole.Open(); using(OleDbCommand oleCmd=new OleDbCommand()) { oleCmd.Connection = ole; //System.Data.DataTable dtsheet = ole.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "Table" }); //foreach(DataRow dr in dtsheet.Rows) //{ // oleCmd.CommandText = "drop table [" + dr["TABLE_NAME"].ToString() + "]"; // oleCmd.ExecuteNonQuery(); //} //oleCmd.CommandText = "drop table [Sheet1$]"; //oleCmd.ExecuteNonQuery(); ArrayList alCol = new ArrayList(); OleDbParameter[] para = new OleDbParameter[colcount]; ArrayList aric = new ArrayList(); ArrayList ariv = new ArrayList(); for(int i = 0; i < colcount; i++) { para[i] = new OleDbParameter("@" + dtb.Columns[i].HeaderText, OleDbType.VarChar); alCol.Add("[" + dtb.Columns[i].HeaderText + "] VarChar"); aric.Add("[" + dtb.Columns[i].HeaderText + "]"); ariv.Add("@" + dtb.Columns[i].HeaderText); } string strIs = "insert into [Sheet1$] (" + string.Join(",", aric.ToArray()) + ") values (" + string.Join(",", ariv.ToArray()) + ")"; string strCs = "create table [Sheet1$] (" + string.Join(",", alCol.ToArray()) + ")"; oleCmd.CommandText = strCs; int en = oleCmd.ExecuteNonQuery(); List<OleDbParameter> lop = new List<OleDbParameter>(); ArrayList arrow = new ArrayList(); for(int j = 0; j < rowcount; j++) { arrow.Clear(); lop.Clear(); oleCmd.Parameters.Clear(); for(int k = 0; k < colcount; k++) { para[k].Value = dtb[k, j].Value.ToString(); oleCmd.Parameters.Add(para[k]); } //oleCmd.Connection = ole; oleCmd.CommandText = strIs; oleCmd.ExecuteNonQuery(); } } } return "success"; }else { return "null"; } }catch(Exception ex) { return ex.Message; } }
這種方法需要指定一個已經存在的 Excel 文件作為寫入數據的模板,不然的話就得使用流創建一個新的 Excel 文件,但是這樣是沒法識別的,那就需要用到 Microsoft.Office.Interop.Excel.dll 里面的 Microsoft.Office.Interop.Excel.Workbook.SaveCopyAs() 方法另存為一下,這樣性能也就更差了。
使用操作命令創建的表都是在最后面的,前面的也沒法刪除(我是沒有找到方法),當然也可以不再創建,直接寫入數據也可以。但是很奇怪,直接寫入時列頭下的第一行會空白着,數據從第三行開始寫入。如果是新建表寫入數據就不會出現這種情況。