最近在做一个小程序,需要将DataGridView中的数据导出到Excel中显示和保存。最开始用使用如下代码实现:
SaveFileDialog dlg = new SaveFileDialog(); //实例化一个SaveFileDialog保存文件对话框 dlg.Filter = "Excel files (*.xls)|*.xls"; dlg.FilterIndex = 0; dlg.RestoreDirectory = true; dlg.CreatePrompt = true; dlg.Title = "保存为excel文件"; if (dlg.ShowDialog() == DialogResult.OK) { Stream mystream; //stream类是读写字节数据的数据流类中最基础的基类 mystream = dlg.OpenFile(); //打开用户选定的具有读写权限的文件,并把获取的文件路径赋值给mystream StreamWriter sw = new StreamWriter(mystream, System.Text.Encoding.GetEncoding(-0)); //实例化数据流的写入,encoding获取编码方式 string columntitle = ""; try { //写入列标题 for (int i = 0; i < dataGridView_resultDisplay.ColumnCount; i++) { if (i > 0) { columntitle += "\t"; //添加一个分隔符 } columntitle += dataGridView_resultDisplay.Columns[i].HeaderText; } sw.WriteLine(columntitle); //写入列内容 for (int j = 0; j < dataGridView_resultDisplay.Rows.Count; j++) { string columnvalue = ""; for (int k = 0; k < dataGridView_resultDisplay.Columns.Count; k++) { if (k > 0) columnvalue += "\t"; if (dataGridView_resultDisplay.Rows[j].Cells[k].Value == null) columnvalue += ""; else columnvalue += dataGridView_resultDisplay.Rows[j].Cells[k].Value.ToString().Trim(); } sw.WriteLine(columnvalue); } sw.Close(); mystream.Close(); textExportPath.Text = dlg.FileName; MessageBox.Show("分类汇总结果已保存到【" + dlg.FileName + "】"); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } finally { sw.Close(); mystream.Close(); } }利用上述代码实现后,能够保存.xls格式的文件。但在打开这个文件时会出现如下问题:
在网上搜上了一下,这种方法生成的Excel根本不是Excel,只不过扩展名是xls而已,所以打开的时候会提示“您尝试打开的文件**.xls的格式与文件扩展名指定的格式不一致”这是Excel的安全问题,暂时解决办法如下,取消Exce的安全检测。怎么样取消Excel的安全检测,可以到修改注册表:
1、开始 -> 运行 -> 输入regedit -> 确定
2、找到注册表子项HKEY_CURRENT_USER\Software\Microsoft\Office\12.0\Excel\Security
3、在右侧空白处点击鼠标右键,选择“新建 -> DWORD值(D)”,输入"ExtensionHardening"点击确定。
4、用鼠标右键点击ExtensionHardening,然后单击“修改(M)”,在数值数据中填写"0"即可确定。
5、关闭注册表编辑器,再次打开xls文件看看是不是提示是不是不见了?
拓展:ExtensionHardening设置的值的数据设置:
0:不检查文件扩展名和文件类型并绕过该函数的警告消息。
1:检查文件扩展名和文件类型。如果它们不匹配会显示警告消息。
2:检查文件扩展名和文件类型。如果它们不匹配不要打开该文件
为了长久解决上面的问题,又查找了一些资料,找到另一条途径实现:
在项目引用中添加了Microsoft Excel11 Object Libray,用如下代码实现,即可解决(若无法使用” Microsoft.Office.Interop.Excel”,可参考我的另一篇文章解决):
int iRows = 0; int iCols = 0; int iTrueCols = 0; int i, j, k; string SheetName = "test"; Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application(); Microsoft.Office.Interop.Excel.Workbook wb = app.Workbooks.Add(System.Reflection.Missing.Value); Microsoft.Office.Interop.Excel.Worksheet ws = null; if (wb.Worksheets.Count > 0) { ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1); } else { wb.Worksheets.Add(System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value); ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1); } if (ws != null) { if (SheetName.Trim() != null) { ws.Name = SheetName; } iRows = dataGridView_resultDisplay.Rows.Count; iTrueCols = dataGridView_resultDisplay.Columns.Count; for (i = 0; i < dataGridView_resultDisplay.Columns.Count; i++) { if (dataGridView_resultDisplay.Columns[i].Visible) { iCols++; } } MessageBox.Show(Convert.ToString(iTrueCols) + " "+Convert.ToString(iRows)); for (j = 0; j < iTrueCols; j++) { if (dataGridView_resultDisplay.Columns[j].Visible) { if (dataGridView_resultDisplay.Columns[j].HeaderText.Trim() != null) ws.Rows[1].Cells[j + 1] = dataGridView_resultDisplay.Columns[j].HeaderText.Trim(); } } for (i = 1; i < iRows; i++) { for (j = 0; j < iTrueCols; j++) { string str; if (dataGridView_resultDisplay.Rows[i - 1].Cells[j].Value.ToString().Trim() == null) { str = "0"; } else { str = dataGridView_resultDisplay.Rows[i - 1].Cells[j].Value.ToString().Trim(); } ws.Cells[i + 1, j+1] = str; } } ws.Range[ws.Cells[1, 1], ws.Cells[1, iCols]].Font.Bold = true; ws.Range[ws.Cells[1, 1], ws.Cells[iRows + 1, iCols]].Font.Size = 10.0; ws.Range[ws.Cells[1, 1], ws.Cells[iRows + 1, iCols]].RowHeight = 14.25; for (j = 0, k = 0; j < iTrueCols; j++) { //省略Visible = false的列 if (dataGridView_resultDisplay.Columns[j].Visible) { ws.Range[ws.Cells[1, k + 1], ws.Cells[1, k + 1]].ColumnWidth = (dataGridView_resultDisplay.Columns[j].Width / 8.4) > 255 ? 255 : (dataGridView_resultDisplay.Columns[j].Width / 8.4); k++; } } app.Visible = true; }
上面的运行后,DataGridView保存到Excel中的数据都是一致的,比如数值类型对应数值类型,文本类型对应文本类型。当然如果你想要保存的数据类型都是字符串或者文本,可以先通过一个二维的String数组将DataGridView的数据保存起来,然后再将数组赋值给Excel。代码改动如下:
int iRows = 0; int iCols = 0; int iTrueCols = 0; Microsoft.Office.Interop.Excel.Application app = new Microsoft.Office.Interop.Excel.Application(); Microsoft.Office.Interop.Excel.Workbook wb = app.Workbooks.Add(System.Reflection.Missing.Value); Microsoft.Office.Interop.Excel.Worksheet ws = null; if (wb.Worksheets.Count > 0) { ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1); } else { wb.Worksheets.Add(System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value, System.Reflection.Missing.Value); ws = (Microsoft.Office.Interop.Excel.Worksheet)wb.Worksheets.get_Item(1); } if (ws != null) { if (SheetName.Trim() != "") { ws.Name = SheetName; } iRows = datagridview.Rows.Count; //加上列头行 iTrueCols = datagridview.Columns.Count; //包含隐藏的列,一共有多少列 //求列数,省略Visible = false的列 for (int i = 0; i < datagridview.Columns.Count; i++) { if (datagridview.Columns[i].Visible) iCols++; } string[,] dimArray = new string[iRows + 1, iCols]; for (int j = 0, k = 0; j < iTrueCols; j++) { //省略Visible = false的列 if (datagridview.Columns[j].Visible) { dimArray[0, k] = datagridview.Columns[j].HeaderText; k++; } } for (int i = 0; i < iRows; i++) { for (int j = 0, k = 0; j < iTrueCols; j++) { //省略Visible = false的列 if (datagridview.Columns[j].Visible) { dimArray[i + 1, k] = datagridview.Rows[i].Cells[j].Value.ToString(); k++; } } } ws.get_Range(ws.Cells[1, 1], ws.Cells[iRows + 1, iCols]).Value2 = dimArray; ws.get_Range(ws.Cells[1, 1], ws.Cells[1, iCols]).Font.Bold = true; ws.get_Range(ws.Cells[1, 1], ws.Cells[iRows + 1, iCols]).Font.Size = 10.0; ws.get_Range(ws.Cells[1, 1], ws.Cells[iRows + 1, iCols]).RowHeight = 14.25; //ws.Columns[.ColumnWidth = datagridview.Columns[0].Width; for (int j = 0, k = 0; j < iTrueCols; j++) { //省略Visible = false的列 if (datagridview.Columns[j].Visible) { ws.get_Range(ws.Cells[1, k + 1], ws.Cells[1, k + 1]).ColumnWidth = (datagridview.Columns[j].Width / 8.4) > 255 ? 255 : (datagridview.Columns[j].Width / 8.4); //ws.Columns.c = datagridview.Columns[j].Width; k++; } } } app.Visible = true;