博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.NET WinForm下一个支持更新ProgressBar进度的DataGridView导出数据到Excel的类
阅读量:5079 次
发布时间:2019-06-12

本文共 4268 字,大约阅读时间需要 14 分钟。

将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线程中被执行而失去模态对话框的作用。

  类的完整代码:

  前端调用的例子:

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();
    }
}
 原文地址:

转载于:https://www.cnblogs.com/jeriffe/articles/2223439.html

你可能感兴趣的文章
基于grunt构建的前端集成开发环境
查看>>
利用循环播放dataurl的视频来防止锁屏:NoSleep.js
查看>>
python3 生成器与迭代器
查看>>
java编写提升性能的代码
查看>>
Abstract Factory Pattern
查看>>
list 容器 排序函数.xml
查看>>
《Genesis-3D开源游戏引擎完整实例教程-跑酷游戏篇03:暂停游戏》
查看>>
CPU,寄存器,一缓二缓.... RAM ROM 外部存储器等简介
查看>>
windows下编译FreeSwitch
查看>>
git .gitignore 文件不起作用
查看>>
Alan Turing的纪录片观后感
查看>>
c#自定义控件中的事件处理
查看>>
django Models 常用的字段和参数
查看>>
IOS--沙盒机制
查看>>
使用 JointCode.Shuttle 访问任意 AppDomain 的服务
查看>>
sqlite的坑
查看>>
digitalocean --- How To Install Apache Tomcat 8 on Ubuntu 16.04
查看>>
【题解】[P4178 Tree]
查看>>
Jquery ui widget开发
查看>>
关于indexOf的使用
查看>>