第一种:流导出
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() 方法另存为一下,这样性能也就更差了。
使用操作命令创建的表都是在最后面的,前面的也没法删除(我是没有找到方法),当然也可以不再创建,直接写入数据也可以。但是很奇怪,直接写入时列头下的第一行会空白着,数据从第三行开始写入。如果是新建表写入数据就不会出现这种情况。