.NET WinForm下一个支持更新ProgressBar进度的DataGridView导出数据到Excel的类-阿里云开发者社区

开发者社区> 浣熊干面包> 正文

.NET WinForm下一个支持更新ProgressBar进度的DataGridView导出数据到Excel的类

简介:
+关注继续查看

将DataGridView数据导出到Excel的方法大家应该都不陌生,无非就是对DataGridView进行行和列的遍历,将数据写入到Excel Workbook中,不过项目中需要添加对Excel的COM引用,这个会受到客户端环境的限制。如果直接将数据以CSV的形式导出就更简单了,CSV是一种简单的以分隔符(如逗号,Tab制表符等)分隔数据的文件,支持用Excel或记事本打开。一般而言,直接将数据导出到CSV文件中速度会比较快,但是如果将数据导出到Excel标准格式的文件中时需要调用COM组件中的对象,因此速度会慢一些,这时考虑在UI中加入一个实时进度条是有必要的。如何在多线程中使用ProgressBar相信很多人也都不陌生了,最简单的方法就是使用BackgroundWorker组件,将数据导出的代码放到BackgroundWorker的DoWork事件处理程序中去完成,并实时报告进度,BackgroundWorker的ProgressChanged事件用于更新UI线程中ProgressBar的值,BackgroundWorker的RunWorkerCompleted事件则用来处理操作完成之后的一些事情,例如隐藏ProgressBar,或者显示错误信息等。但是,这里会有一个问题。数据导出的方法一般来说是一个公共方法,它允许在应用程序的不同地方被调用,因此该方法不应该依赖于任何一个窗体或UI元素,我们应该想办法将它独立出来专门写成一个类,同时它还要能支持ProgressBar的更新。

  按照传统的使用BackgroundWorker的方法,我们需要将BackgroundWorker传递到这个类中,同时类里面还需要处理与BackgroundWorker相关的事件,以及与UI相关的一些事情,这显然违背了敏捷开发中的“单一职责原则——一个类只允许有一个引起它变化的原因”。引入太多与UI相关的元素会导致类不够通用,实现起来也很困难。如何从DataGridView导出数据到Excel或CSV文件应该不是什么难事,现在的主要问题是如何支持ProgressBar的进度实时更新。

  一个比较好的办法是采用.NET的事件驱动方式。我们可以在类中定义几个事件,例如开始进行数据导出时的事件,数据正在导出时的事件,数据导出完成之后的事件。调用端通过注册这些事件来取得与类的联系。说白了,联系的纽带就是事件,这个和WinForm程序中各个窗体之间进行互动的原理一样。来看看这些事件的主要用途。

  1. 开始进行数据导出时的事件

  该事件在数据真正开始导出之前被触发,用来获取数据导出总共需要多少步(通常可以认为是DataGridView数据中行和列的总和,试具体导出方式而定)。调用方在事件处理程序中可以更新ProgressBar的属性,如Value,Maximnm,Visible等。

  2. 数据正在导出时的事件

  该事件主要负责更新ProgressBar的进度。我们规定每导出一行或一列数据即触发一次事件。调用方在事件处理程序中更新ProgressBar的进度。

  3. 数据导出完成之后的事件

  在导出数据的方法中,无论什么情况(成功结束或抛出异常)只要结束了数据导出即触发该事件,同时传递一个自定义的继承自EventArgs类的参数。调用方在事件处理程序可以根据这个参数来判断数据导出是否成功完成,从而决定是在UI线程中显示错误信息或给出工程完成的提示信息。

  注意调用方在事件处理程序中必须使用Invoke通过代理来更新UI,否则会抛跨线程UI操作的异常。而对于像MessageBox.Show()这样的模态对话框,如果不是在Invoke中通过代理来调用,它会因为在非UI线程中被执行而失去模态对话框的作用。

  类的完整代码:ExportDataGridViewToExcel.zip

  前端调用的例子:

复制代码
private ExportDataGridViewToExcel export = null;

public DetailsTable()
{
    InitializeComponent();

    export 
= new ExportDataGridViewToExcel();
    export.DataGridViewControl 
= this.dataGridView1;
    export.ExportStartingEvent 
+= new EventHandler(export_ExportStartingEvent);
    export.ExportProgressingEvent 
+= new EventHandler(export_ExportProgressingEvent);
    export.ExportEndedEvent 
+= new EventHandler<ExportDataGridViewToExcel.ExportEndedEventArgs>(export_ExportEndedEvent);
}

// Data export end event.
void export_ExportEndedEvent(object sender, ExportDataGridViewToExcel.ExportEndedEventArgs e)
{
    
if (e.IsCompleted)
    {
        
if (this.InvokeRequired)
        {
            
this.Invoke(new MethodInvoker(delegate()
            {
                MessageBox.Show(
"Complete!""Prompt", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }));
        }
    }
    
else
    {
        
if (this.InvokeRequired)
        {
            
this.Invoke(new MethodInvoker(delegate()
            {
                MessageBox.Show(
this"Export file failed.\r\n{0}" + e.Errors == null ? string.Empty : e.Errors.Message, "Errors", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }));
        }
    }

    
if (this.InvokeRequired)
    {
        
this.Invoke(new MethodInvoker(delegate()
        {
            
this.toolStripProgressBar.Visible = false;
        }));
    }
}

// Data export in process event.
void export_ExportProgressingEvent(object sender, EventArgs e)
{
    
int nowValue = Convert.ToInt32(sender);
    
if (this.InvokeRequired)
    {
        
this.Invoke(new MethodInvoker(delegate()
        {
            
this.toolStripProgressBar.Value = nowValue;
        }));
    }
}

// Data export starting event.
void export_ExportStartingEvent(object sender, EventArgs e)
{
    
int maxValue = Convert.ToInt32(sender);
    
if (this.InvokeRequired)
    {
        
this.Invoke(new MethodInvoker(delegate()
        {
            
this.toolStripProgressBar.Value = 0;
            
this.toolStripProgressBar.Maximum = maxValue;
            
this.toolStripProgressBar.Visible = true;
        }));
    }
}

// Export to CSV.
private void exportToCSVToolStripMenuItem_ExportToCSV_Click(object sender, EventArgs e)
{
    
this.saveFileDialog_CSV.FileName = this.Text;
    
if (saveFileDialog_CSV.ShowDialog() == System.Windows.Forms.DialogResult.OK)
    {
        export.FilePath 
= saveFileDialog_CSV.FileName;
        Thread thread 
= new Thread(new ParameterizedThreadStart(export.DataGridViewToCSV));
        thread.Start(saveFileDialog_CSV.OpenFile());
    }
}

// Export to Excel.
private void exportToExcelToolStripMenuItem_ExportToExcel_Click(object sender, EventArgs e)
{
    
this.saveFileDialog_Excel.FileName = this.Text;
    
if (saveFileDialog_Excel.ShowDialog() == System.Windows.Forms.DialogResult.OK)
    {
        export.FilePath 
= saveFileDialog_Excel.FileName;
        Thread thread 
= new Thread(new ThreadStart(export.DataGridViewToExcel));
        thread.Start();
    }
}

private void copyToolStripMenuItem_Copy_Click(object sender, EventArgs e)
{
    DataObject d 
= this.dataGridView1.GetClipboardContent();
    Clipboard.SetDataObject(d);
}

private void toolStripButton_ToExcel_Click(object sender, EventArgs e)
{
    
this.exportToExcelToolStripMenuItem_ExportToExcel.PerformClick();
}

private void toolStripButton_ToCSV_Click(object sender, EventArgs e)
{
    
this.exportToCSVToolStripMenuItem_ExportToCSV.PerformClick();
}
复制代码

  最后三个事件处理程序依次是:DataGridView上下文菜单中的Copy事件;DataGridView上下文菜单中Export to Excel事件,可以直接使用exportToExcelToolStripMenuItem工具条按钮的PerformClick方法;DataGridView上下文菜单中的Export to CSV事件,直接使用exportToCSVToolStripMenuItem工具条按钮的PerformClick方法。


本文转自Jaxu博客园博客,原文链接:http://www.cnblogs.com/jaxu/archive/2011/08/03/2126497.html,如需转载请自行联系原作者


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
后疫情时代,用数据支持业务恢复创造新的可能性
2020年可以说每一天都在见证历史,新冠疫情的突然造访就如同“黑天鹅”不期而至,而企业现在还不开始数字化转型就如同“灰犀牛”存在潜在风险,当下在黑天鹅和灰犀牛的夹击下,经济和市场都产生了巨大的影响。
839 0
阿里云云效功能升级,支持快速创建多个应用的独立测试环境
作为测试人员来说,搭建测试环境是测试实施的一个重要阶段,测试环境适合与否会严重影响测试结果的真实性和正确性。为了更好地服务用户,近日,阿里云研发协同平台-云效宣布功能升级,支持快速创建多个应用的独立测试环境,对于企业开发人员和测试人员来说,又是一大福音。
4514 0
poi读取excel模板,填充内容并导出,支持导出2007支持公式自动计算
/** * 版权所有(C) 2016 * @author www.xiongge.club * @date 2016-12-7 上午10:03:29 */ package xlsx; /** * @ClassName: CreateExcel * @Description: TODO() * @author www.xiongge.club *
2008 0
使用 advanced installer 为 winform 做自动更新
原文:使用 advanced installer 为 winform 做自动更新 advanced installer 是一款打包程序,基于 windows installer 并扩展了一些功能,比如安装统计,自动更新,授权验证等,本文将介绍你如果使用 advanced installer(以下简称 ai) 为 winform 做自动更新。
1475 0
ECS支持跨地域跨资源类型的标签(TAG)操作
ECS资源可以使用标签进行分组管理,如何快速将自己多地域/多种类型的资源都打上标签(TAG)呢?
620 0
941
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载