C#导出数据到EXCEL方法谈
(附实例源码和详细讲解)
如果你耐心仔细看完本文,相信以后再遇到导出EXCLE操作的时候你会很顺手觉得SO EASY,主要给新手朋友们看的,老鸟可以直接飘过了,花了一晚上的时间写的很辛苦,如果觉得对你有帮助烦请留言支持一下,我会写更多基础的原创内容来回报大家。
C#导出数据到EXCEL表格是个老生常谈的问题了,写这篇文章主要是给和我一样的新手朋友提供两种导出EXCEL的方法并探讨一下导出的效率问题,本文中的代码直接就可用,其中部分代码参考其他的代码并做了修改,抛砖引玉,希望大家一起探讨,如有不对的地方还请大家多多包涵并指出来,我也是个新手,出错也是难免的。
首先先总结下自己知道的导出EXCEL表格的方法,大致有以下几种,有疏漏的请大家补充。
数据逐条逐条的写入EXCEL
通过OLEDB把EXCEL做为数据源来写
通过RANGE范围写入多行多列内存数据到EXCEL
利用系统剪贴板写入EXCEL
好了,我想这些方法已经足够完成我们要实现的功能了,方法不在多,在精,不是么?以上4中方法都可以实现导出EXCEL,方法1为最基础的方法,意思就是效率可能不是太高,当遇到数据量过大时所要付出的时间也是巨大的,后面3种方法都是第一种的衍生,在第一种方法效率低下的基础上改进的,这里主要就是一个效率问题了,当然如果你数据量都很小,我想4种方法就代码量和复杂程度来说第1种基本方法就可以了,或当你的硬件非常牛逼了,那再差的方法也可以高效的完成也没有探讨的实际意义了,呵呵说远了,本文主要是在不考虑硬件或同等硬件条件下单从软件角度出发探讨较好的解决方案。
此项目代码已打包在附件中,几乎注释的无微不至,在配合本文中我唐僧般的娓娓道来(靠,谁丢臭鸡蛋砸俺了),相信即使刚入门C#的朋友也能看得懂了吧,大家可以自行下载,代码中演示了两种方法,上述的方法1和方法3,我想足够了,方法3的效率应该是四种中最高的了,其他两种有兴趣的朋友自己实现下哈(方法2在我的程序中也有用到一些,看完你就知道了),程序如下图所示,先加载一个EXCEL表格进DATAGRIDVIEW作为数据源,然后两种方法导出EXCEL,配上一个计数功能给大家直观的看到导出的耗时,大家可以准备个几万行和十多行的两个EXCEL作为数据源来测试,也可以用我打包里的XLS来测试下。
首先使用前都需要加载COM组件Microsoft.Office.Interop.Excel.dll
(已打包)
关键代码如下:
方法1,最基本方法,用FOR循环逐条写入EXCEL的CELL中,其
他的看代码就行了,关键代码如下
public void ToExcel1(DataGridView gridView, SaveFileDialog
saveFileDialog)
{
...........................
for (int i = 0; i < gridView.RowCount; i++)
{
for (int j = 0; j < gridView.ColumnCount; j++)
{
if (gridView[j, i].Value == typeof(string))
{
excel.Cells[i + 2, j + 1] = "" + gridView[i, j].Value.ToString();
}
else
{
excel.Cells[i + 2, j + 1] = gridView[j, i].Value.ToString();
}
}
//进度条加1
progressBar1.Value++;
/*
* 注意此Application.DoEvents(),如果无此句,当切换窗口后回到本
程序无法重绘窗体会出现假死状态
* 此处我试过用委托和线程异步调用的方法,但效果没有这句效果好
*/
System.Windows.Forms.Application.DoEvents();
...................
}
方法2,快速保存内存中大量数据到Excel的WorkSheet。关键之处是
使用Range一次存储多行多列数据。
public void ToExcel2(DataGridView gridView, SaveFileDialog
saveFileDialog)
{
....................
System.Reflection.Missing miss = System.Reflection.Missing.Value;
//创建EXCEL对象appExcel,Workbook对象,Worksheet对象,Range对
象
Microsoft.Office.Interop.Excel.Application appExcel;
appExcel = new Microsoft.Office.Interop.Excel.Application();
Microsoft.Office.Interop.Excel.Workbook workbookData;
Microsoft.Office.Interop.Excel.Worksheet worksheetData;
Microsoft.Office.Interop.Excel.Range rangedata;
//设置对象不可见
appExcel.Visible = false;
/* 在调用Excel应用程序,或创建Excel工作簿之前,记着加上下面的
两行代码
* 这是因为Excel有一个Bug,如果你的操作系统的环境不是英文的,
而Excel就会在执行下面的代码时,报异常。
*/
System.Globalization.CultureInfo CurrentCI =
System.Threading.Thread.CurrentThread.CurrentCulture;
System.Threading.Thread.CurrentThread.CurrentCulture = new
System.Globalization.CultureInfo("en-US");
workbookData = appExcel.Workbooks.Add(miss);
worksheetData
=(Microsoft.Office.Interop.Excel.Worksheet)workbookData.Workshee
s.Add(miss, miss, miss, miss);
//给工作表赋名称
worksheetData.Name = "saved";
//清零计数并开始计数
TimeP = new System.DateTime(0);
timer1.Start();
label1.Text = TimeP.ToString("HH:mm:ss");
// 保存到WorkSheet的表头,你应该看到,是一个Cell一个Cell的存
储,这样效率特别低,解决的办法是,使用Rang,一块一块地存储到
Excel
for (int i = 0; i < gridView.ColumnCount; i++)
{
worksheetData.Cells[1, i + 1] =
gridView.Columns[i].HeaderText.ToString();
}
//先给Range对象一个范围为A2开始,Range对象可以给一个CELL的
范围,也可以给例如A1到H10这样的范围
//因为第一行已经写了表头,所以所有数据都应该从A2开始
rangedata = worksheetData.get_Range("A2", miss);
Microsoft.Office.Interop.Excel.Range xlRang = null;
//iRowCount为实际行数,最大行
int iRowCount = gridView.RowCount;
int iParstedRow = 0, iCurrSize = 0;
//iEachSize为每次写行的数值,可以自己设置,每次写1000行和每次
写2000行大家可以自己测试下效率
int iEachSize = 1000;
//iColumnAccount为实际列数,最大列数
int iColumnAccount = gridView.ColumnCount;
//在内存中声明一个iEachSize×iColumnAccount的数组,iEachSize是
每次最大存储的行数,iColumnAccount就是存储的实际列数
object[,] objVal = new object[iEachSize, iColumnAccount];
try
{
//给进度条赋最大值为实际行数最大值
progressBar1.Maximum = gridView.RowCount;
iCurrSize = iEachSize;
while (iParstedRow < iRowCount)
{
if ((iRowCount - iParstedRow) < iEachSize)
iCurrSize = iRowCount - iParstedRow;
//用FOR循环给数组赋值
for (int i = 0; i < iCurrSize; i++)
{
for (int j = 0; j < iColumnAccount; j++)
objVal[i, j] = gridView[j, i + iParstedRow].Value.ToString();
progressBar1.Value++;
System.Windows.Forms.Application.DoEvents();
}
/*
* 建议使用设置断点研究下哈
* 例如A1到H10的意思是从A到H,第一行到第十行
* 下句很关键,要保证获取Sheet中对应的Range范围
* 下句实际上是得到这样的一个代码语句xlRang =
worksheetData.get_Range("A2","H100");
* 注意看实现的过程
* 'A' + iColumnAccount - 1这儿是获取你的最后列,A的数字码为65,
大家可以仔细看下是不是得到最后列的字母
* iParstedRow + iCurrSize + 1获取最后行
* 若WHILE第一次循环的话这应该是A2,最后列字母+最后行数字
* iParstedRow + 2要注意,每次循环这个值不一样,他取决于你每次
循环RANGE取了多大,循环了几次,也就是iEachSize设置值的大小
哦
*/
xlRang = worksheetData.get_Range("A" + ((int)(iParstedRow +
2)).ToString(), ((char)('A' + iColumnAccount - 1)).ToString() +
((int)(iParstedRow + iCurrSize + 1)).ToString());
// 调用Range的Value2属性,把内存中的值赋给Excel
xlRang.Value2 = objVal;
iParstedRow = iParstedRow + iCurrSize;
}
//保存工作表
worksheetData.SaveAs(strName, miss, miss, miss, miss, miss,
Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange,
miss, miss, miss);
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRang
;
xlRang = null;
progressBar1.Value = 0;
//调用方法关闭EXCEL进程,大家可以试下不用的话如果程序不关闭在
进程里一直会有EXCEL.EXE这个进程并锁定你的EXCEL表格
this.KillSpecialExcel(appExcel);
timer1.Stop();
MessageBox.Show("数据已经成功导出到:" +
saveFileDialog.FileName.ToString(), "导出完成",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
timer1.Stop();
return;
}
// 别忘了在结束程序之前恢复你的环境!
System.Threading.Thread.CurrentThread.CurrentCulture = CurrentCI
最后再顺便说下本程序中的一些部分:
1.做过EXCEL导出的朋友应该遇到过一个情况,当导出完毕后进程中
那个讨厌的EXCEL.EXE老是无法关闭,造成锁定导出的XLS文件,要
关闭程序后该进程才退出,网上也有一种方法就是我方法ToExcel1()用
到的那个方法(详见下载的代码),但我写ToExcel2()方法的时候发现
这种关闭的方法突然不好使了,这我用到了另一种方法
KillSpecialExcel,调用的时候这样调用this.KillSpecialExcel(appExcel)
大家可以试下把ToExcel2()改为ToExcel1()的关闭EXCEL方法看是否
有效,代码如下
#region 结束EXCEL.EXE进程的方法
/// <summary>
/// 结束EXCEL.EXE进程的方法
/// </summary>
/// <param name="m_objExcel">EXCEL对象</param>
[DllImport("user32.dll", SetLastError = true)]
static extern int GetWindowThreadProcessId(IntPtr hWnd, out int
lpdwProcessId);
public void KillSpecialExcel(Microsoft.Office.Interop.Excel.Application
m_objExcel)
{
try
{
if (m_objExcel != null)
{
int lpdwProcessId;
GetWindowThreadProcessId(new IntPtr(m_objExcel.Hwnd), out
lpdwProcessId);
System.Diagnostics.Process.GetProcessById(lpdwProcessId).Kill();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
代码里写了个加载EXCEL到DATAGRIDVIEW的方法,就是想本来
就是在写EXCEL操作相关嘛,干脆数据源也用EXCEL,该方法就是
把EXCEL作为OLEDB数据源这样来操作的,你是不是想到前面我所
提到的四种导出EXCEL中的《方法2通过OLEDB把EXCEL做为数
据源来写》呢,对了,有兴趣你可以尝试修改下通过OLEDB这样来
导出EXCEL,当然,新手朋友可以看下如何加载EXCEL数据,你应
该希望去尝试接着如何把这些数据储存到数据库之类的操作
System.Windows.Forms.Application.DoEvents(),当运行 Windows
窗体时,它将创建新窗体,然后该窗体等待处理事件。该窗体在每次
处理事件时,均将处理与该事件关联的所有代码。所有其他事件在队
列中等待。在代码处理事件时,应用程序并不响应。例如,当将另一
窗口拖到该窗口前面时,该窗口不重新绘制。如果在代码中调用
DoEvents,则您的应用程序可以处理其他事件。例如,如果您有向
ListBox 添加数据的窗体,并将 DoEvents 添加到代码中,那么当将
另一窗口拖到您的窗体上时,该窗体将重新绘制。如果从代码中移除
DoEvents,那么在按钮的单击事件处理程序执行结束以前,您的窗体
不会重新绘制。
这里说远一点,关于如何防止UI假死其实还有更科学的方法,就是使
用委托加线程异步执行,把耗时的操作另起进程执行,从而减轻UI的
压力,使得前台UI流畅运行而不假死,多用this.Invoke等,但在我程
序用我也测试过反而直接DoEvents效果还好的多,而且线程和委托可
能对新手朋友稍微复杂了些,推荐一般应用用DoEvents足够了哦。
原文网址:http://blog.csdn.net/smallwhiteyt/article/details/4784771
- 大小: 46.9 KB
分享到:
相关推荐
本教程将引导初学者了解如何使用C#来打开、读取、修改和保存Excel文件,这对于数据处理和报表生成至关重要。下面将详细阐述相关知识点。 1. **安装必要的库** 在C#中操作Excel,首先需要引入一个第三方库,如`...
C# 创建 Excel 并保存数组数据到指定列 C# 创建 Excel 文档并将数组数据保存到指定列是很多开发者需要掌握的一项技术。本文将详细讲述如何使用 C# 创建 Excel 文档,并将数组数据保存到指定的列中。 首先,为了...
第二个示例可能使用了EPPlus库,其工作方式是创建一个ExcelPackage对象,然后添加工作表,填充数据,最后保存为文件。示例如下: ```csharp using OfficeOpenXml; using (var package = new ExcelPackage(new ...
在.NET开发环境中,C#语言提供了多种库来处理Excel文件,其中之一便是NPOI库。NPOI是一个开源项目,它允许开发者在不依赖Microsoft Office的情况下读写Excel文件,不仅支持旧版的.xls格式,也支持.xlsx的新XML格式。...
当用户选择了保存文件的路径和文件名后,我们可以使用以下代码来保存Excel文件: ```csharp if (S_file.FileName != "") { m_objBook._SaveAs(S_file.FileName, Missing.Value, Missing.Value, Missing.Value, ...
在C#编程环境中,开发人员经常需要处理用户界面与数据操作的任务。本示例着重讲解如何从`DataGridView`控件中导出数据到Excel文件,并同时在操作过程中使用`ProgressBar`来显示进度和当前的工作状态。`DataGridView`...
本主题将详细探讨如何使用C#实现从Excel文件导入数据到ListView控件,以及如何将ListView中的数据导出回Excel文件。这两个操作在数据分析、报表生成和数据管理等场景中非常常见。 首先,要导入Excel文件到ListView...
本篇将详细讲解如何使用C#将Excel表格转换为图片,并提供相关的源码示例。 首先,我们需要一个能够处理Excel文件的库。在.NET Framework中,Microsoft.Office.Interop.Excel是常见的选择,但这个库依赖于安装了...
### C#操作Excel知识点 #### 一、C#读取Excel的方法 在C#中,可以通过多种方式来读取Excel文件。本节介绍两种方法: ##### 方法一:使用`Microsoft.Office.Interop.Excel` 此方法适用于Office版本的Excel文件...
在C#编程环境中,导入Excel并读取其中的图片上传是一项常见的任务,特别是在处理数据导入、数据分析或报表生成等场景。下面将详细讲解如何利用C#实现这一功能,包括使用.NET框架提供的组件以及第三方库。 首先,...
通过使用Microsoft.Office.Interop.Excel命名空间,开发者可以在C#程序中使用Excel对象模型来创建、编辑和保存Excel文件。 在C#操作Excel函数中,开发者可以使用Excel对象模型来创建新的Excel文件、打开现有的Excel...
在完成操作后,记得保存更改并关闭Excel应用: ```csharp workbook.Save(); workbook.Close(false); excelApp.Quit(); ``` 以上就是使用C#通过VS2005读取Excel图表的基本步骤。需要注意的是,由于使用了Interop...
Excel文件在商业环境中广泛使用,因此,了解如何在C#中导出数据到Excel文件是一项重要的技能。本篇文章将深入探讨如何使用C#来创建和导出Excel文件。 首先,你需要一个库来处理Excel文件。Microsoft提供了`...
Aspose.Excel是针对C#开发者的一款高效库,它允许程序员无需借助Microsoft Office组件,就能直接处理Excel文件,包括读取、写入、创建和转换Excel文档。这个库的强大之处在于它提供了一种独立于Office的解决方案,...
本项目“C#保存导出数据到excel工程”是关于如何利用C#编程来实现将数据导出到Excel文件的一个实例。Excel是Microsoft Office套件中的一个组件,通常用于创建和管理电子表格,其格式兼容性和数据处理能力使得它在...
本文将深入探讨标题为“excel控件大全c#嵌入excel”的主题,主要关注其中提到的两个控件——koogra和myxls,并结合C#编程语言来讲解如何在应用程序中嵌入Excel功能。 首先,让我们了解koogra控件。Koogra是一款用于...
在C#编程中,处理Excel文件是常见的任务之一,特别是在数据处理、报表生成或数据分析的场景下。"C#合并EXCEL单元格"的主题涉及到如何使用C#编程语言操作Microsoft Excel文档,特别是针对那些需要将相同内容的单元格...
本实例主要涉及Excel的读取、保存以及相关操作,利用的是.NET Framework中的Microsoft.Office.Interop.Excel库,这是一个允许C#与Excel进行交互的接口。下面将详细阐述相关知识点。 1. **Excel Interop库的引入**:...
在导出Excel文件时,经常会遇到“文件格式与扩展名指定格式不一致”的问题,这是因为大多数人在导出Excel文件时,都是默认保存Excel的格式,忽略了SaveAs方法里的参数。实际上,SaveAs方法的第二个参数FileFormat...