C#中DataGridView数据导出到Excel

时间:2022-08-30 22:57:54

最近在做一个小程序,需要将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格式的文件。但在打开这个文件时会出现如下问题:

C#中DataGridView数据导出到Excel
在网上搜上了一下,这种方法生成的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;