最近在做一个小程序,需要将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;