随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了。

其实也许我们每天面对的太多东西了,觉得很多都稀松平常了,即使很细微的地方,可能我们都已经形成习惯了。反过来,如果我们切换到其他领域,如IOS、android,那么开始我们可能对里面很多设计的规则不甚了解,开始可能也是一头雾水。

本篇继续上一篇《循序渐进开发WinForm项目(4)--Winform界面模块的集成使用》,继续介绍如何循序渐进开发Winform项目,介绍业务模块常见的导入导出操作的功能实现,使得我们能够快速,高效开发常见的模块功能。

上篇随笔我们介绍到自动代码生成的界面如下所示,具备了导入、导出操作,这个操作是针对Excel进行的。

下面我们来介绍这个在很多模块里面常见的Excel导入、Excel导出操作是如何实现的。

1、Excel数据的导出操作

由于我为了演示的目的,我在客户信息表里面只是设计了几个代表性的字段,下面我们来看看代码生成工具自动生成的界面后台代码是如何的。

        /// <summary>
/// 导出Excel的操作
/// </summary>
private void btnExport_Click(object sender, EventArgs e)
{
string file = FileDialogHelper.SaveExcel(string.Format("{0}.xls", moduleName));
if (!string.IsNullOrEmpty(file))
{
string where = GetConditionSql();
List<CustomerInfo> list = BLLFactory<Customer>.Instance.Find(where);
DataTable dtNew = DataTableHelper.CreateTable("序号|int,姓名,年龄,创建人,创建时间");
DataRow dr;
int j = ;
for (int i = ; i < list.Count; i++)
{
dr = dtNew.NewRow();
dr["序号"] = j++;
dr["姓名"] = list[i].Name;
dr["年龄"] = list[i].Age;
dr["创建人"] = list[i].Creator;
dr["创建时间"] = list[i].CreateTime;
dtNew.Rows.Add(dr);
} try
{
string error = "";
AsposeExcelTools.DataTableToExcel2(dtNew, file, out error);
if (!string.IsNullOrEmpty(error))
{
MessageDxUtil.ShowError(string.Format("导出Excel出现错误:{0}", error));
}
else
{
if (MessageDxUtil.ShowYesNoAndTips("导出成功,是否打开文件?") == System.Windows.Forms.DialogResult.Yes)
{
System.Diagnostics.Process.Start(file);
}
}
}
catch (Exception ex)
{
LogTextHelper.Error(ex);
MessageDxUtil.ShowError(ex.Message);
}
}
}

上面的代码中,FileDialogHelper.SaveExcel 函数是调用公用类库模块,弹出一个选择保存文件的对话框,如果你没有这个类,你可以自己添加代码实现这个操作(这就是公用类库的好处,在使用的时候能够快速调用,减少代码,提高效率)。

然后根据客户录入的条件检索需要的数据内容:string where = GetConditionSql();

接着就是构建一个相关字段的表格对象:DataTableHelper.CreateTable,这里面也是使用公用类库来方便创建各种字段的表格,默认字段为字符串格式,如果需要如整形格式的,可以通过|进行分割,如“序号|int” 。

创建DataTable对象后,我们遍历对象集合,把它里面的数据一行行的赋值给DataRow对象就可以了。

                for (int i = ; i < list.Count; i++)
{
dr = dtNew.NewRow();
dr["序号"] = j++;
dr["姓名"] = list[i].Name;
dr["年龄"] = list[i].Age;
dr["创建人"] = list[i].Creator;
dr["创建时间"] = list[i].CreateTime;
dtNew.Rows.Add(dr);
}

赋值后,就是需要把DataTable对象转换为Excel的操作过程了,这里操作分为两步,第一是创建Excel文档,第二个是写数据的表头和数据行信息,也就是数据的写入操作,这里面我们把它封装在公用类库里面,方便模块之间的调用。

导出Excel模块采用了基于Aspose.Cell的组件进行数据的写入操作:AsposeExcelTools.DataTableToExcel2

导出完成后,我们提示用户是否打开Excel文件。

if (MessageDxUtil.ShowYesNoAndTips("导出成功,是否打开文件?") == System.Windows.Forms.DialogResult.Yes)
{
System.Diagnostics.Process.Start(file);
}

最终,完成功能后,我们运行程序,导出Excel数据的效果如下所示。

2、Excel数据的导入操作

相对于数据的导出操作,Excel数据的导入操作会稍微麻烦一点,你至少需要选择一个文件,文件最好以固定的模板进行导入,因此为了让用户确认数据的有效性,我们最好能提供了一个把Excel数据显示出来再确认导入的过程,这样可以减少导入错误数据的可能。

我们知道,这种常见的导入操作,很多业务模块可能都需要,因此有必要考虑把它抽象出来,作为一个通用的导入模块,这样我们可以多次利用,非常方便,因此我们提炼这个通用导入的模块特性如下所示。

Excel数据的导入模块,默认生成界面的时候,也已经一并生成了,我们来看看其中的代码。

        private string moduleName = "客户信息";
/// <summary>
/// 导入Excel的操作
/// </summary>
private void btnImport_Click(object sender, EventArgs e)
{
string templateFile = string.Format("{0}-模板.xls", moduleName);
FrmImportExcelData dlg = new FrmImportExcelData();
dlg.SetTemplate(templateFile, System.IO.Path.Combine(Application.StartupPath, templateFile));
dlg.OnDataSave += new FrmImportExcelData.SaveDataHandler(ExcelData_OnDataSave);
dlg.OnRefreshData += new EventHandler(ExcelData_OnRefreshData);
dlg.ShowDialog();
}

其中FrmImportExcelData 是一个界面基础模块中定义的一个通用导入模块,里面实现了一些如显示Excel数据,模板信息关联,保存数据的接口等操作。我们来看看它的程序运行的效果。

其中我们通过代码 dlg.SetTemplate 指定模板就是用来关联Excel模板信息的,我们让可以尽可能的选择正确的模板进行录入数据。

用户通过第2的标识,指定要导入的Excel数据文件,选择文件后,数据会自动显示出来方便确认。

但我们选择保存数据的操作的时候,这个通用模块会执行保存的逻辑代码,并调用由创建者实现的代码逻辑,如上面代码的dlg.OnDataSave就是在执行保存的时候,执行的代码逻辑,我们来看看生成的一些代码实现。

        bool ExcelData_OnDataSave(DataRow dr)
{
bool success = false;
bool converted = false;
DateTime dtDefault = Convert.ToDateTime("1900-01-01");
DateTime dt;
CustomerInfo info = new CustomerInfo();
info.Name = dr["姓名"].ToString();
info.Age = dr["年龄"].ToString().ToInt32();
info.Creator = dr["创建人"].ToString();
converted = DateTime.TryParse(dr["创建时间"].ToString(), out dt);
if (converted && dt > dtDefault)
{
info.CreateTime = dt;
} success = BLLFactory<Customer>.Instance.Insert(info);
return success;
}

我们知道,导入的时候,是遍历每行Excel进行数据保存操作的,因此我们这里给出了一个一行的操作代码即可:bool ExcelData_OnDataSave(DataRow dr),里面的逻辑,在数据保存的时候会被模块进行调用。

上面的操作,是一条条的进行操作,如果累计超过3条记录出错,模块提示是否继续还是退出。

这里面并没有采用事务的操作,对于一些如Sqlite的大批量的数据操作(速度提升很快),建议采用事务进行处理,关于这个可以参考《Winform开发框架之通用数据导入导出操作的事务性操作完善》进行修改调整。

最后,我们的Excel数据导入完成后,为了及时更新主界面的数据,我们也定义了一个事件作为回调,如下所示。

dlg.OnRefreshData += new EventHandler(ExcelData_OnRefreshData);

这个事件的实现代码就是在主界面的数据绑定更新。

        void ExcelData_OnRefreshData(object sender, EventArgs e)
{
BindData();
}

循序渐进开发WInform项目--系列文章导引:

循序渐进开发WinForm项目(5)--Excel数据的导入导出操作

循序渐进开发WinForm项目(4)--Winform界面模块的集成使用

循序渐进开发WinForm项目(3)--Winform界面层的项目设计

循序渐进开发WinForm项目(2)--项目代码的分析

循序渐进开发WinForm项目(1) --数据库设计和项目框架的生成

循序渐进开发WinForm项目(5)--Excel数据的导入导出操作的更多相关文章

  1. 循序渐进开发WinForm项目(6)--开发使用混合式Winform模块

    1.Winform数据访问模式定义 传统的Winform程序模块:用于传统的数据库通讯获取数据,这种方式获取数据,方便快捷,可以用于常规的业务系统的场景,用于单机版软件或者基于局域网内的业务系统软件. ...

  2. 循序渐进开发WinForm项目(4)--Winform界面模块的集成使用

    随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...

  3. 循序渐进开发WinForm项目(3)--Winform界面层的项目设计

    随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...

  4. 循序渐进开发WinForm项目(2)--项目代码的分析

    随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...

  5. 循序渐进开发WinForm项目(1) --数据库设计和项目框架的生成

    随笔背景:在很多时候,很多入门不久的朋友都会问我:我是从其他语言转到C#开发的,有没有一些基础性的资料给我们学习学习呢,你的框架感觉一下太大了,希望有个循序渐进的教程或者视频来学习就好了. 其实也许我 ...

  6. 使用phpExcel实现Excel数据的导入导出(完全步骤)

    使用phpExcel实现Excel数据的导入导出(完全步骤)   很多文章都有提到关于使用phpExcel实现Excel数据的导入导出,大部分文章都差不多,或者就是转载的,都会出现一些问题,下面是本人 ...

  7. 利用PHPExcel 实现excel数据的导入导出(源码实现)

    利用PHPExcel 实现excel数据的导入导出(源码实现) 在开发过程中,经常会遇到导入导出的需求,利用phpexcel类实现起来也是比较容易的,下面,我们一步一步实现 提前将phpexcel类下 ...

  8. VB中Excel 2010的导入导出操作

    VB中Excel 2010的导入导出操作 编写人:左丘文 2015-4-11 近来这已是第二篇在讨论VB的相关问题,今天在这里,我想与大家一起分享一下在VB中如何从Excel中导入数据和导出数据到Ex ...

  9. java项目中Excel文件的导入导出

    package poi.excel; import java.io.IOException; import java.io.InputStream; import java.io.OutputStre ...

随机推荐

  1. 关于VS2010出现“此方法显式使用的 CAS 策略已被 .NET Framework 弃用... ...请使用 NetFx40_LegacySecurityPolicy 配置开关”解决办法

    有时候VS会出现“此方法显式使用的 CAS 策略已被 .NET Framework 弃用.若要出于兼容性原因而启用 CAS 策略,请使用 NetFx40_LegacySecurityPolicy 配置 ...

  2. HBase修改压缩格式及Snappy压缩实测分享

    一.要点 有关Snappy的相关介绍可参看Hadoop压缩-SNAPPY算法,如果想安装Snappy,可以参看Hadoop HBase 配置 安装 Snappy 终极教程. 1. HBase修改Tab ...

  3. Android之NDK开发

    转自:http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html 一.NDK产生的背景 Android平台从诞生起,就已经支持C ...

  4. 数据人员Sql必会——行转列

    今天被问到列转行的问题,竟然没有回答上来,回想自己也是数据开发人员,平时的积累真是不到位,下面总结一下列转行. 假设咱们有一个学生得分数据表:student_score CREATE TABLE st ...

  5. 【转】--在Android源码树中添加userspace I2C读写工具(i2c-util)

    通过/dev/i2c-n节点,用户可以在userspace直接访问板上的i2c外设寄存器,主要是透过I2C_RDWR这个IO控制命令将i2c_msg数组传递给kernel去执行.下面的代码可以完成这个 ...

  6. 如何在wp8 中调试cocos2dx c++ 代码

    有的时候在win32上运行良好的cocos2dx程序移植到wp8的时候就出了问题,我们想把断点放到c++代码中,需要设置一下VS 2012 右击项目属性 把ui任务 设置为仅限本机 即可.

  7. Unix sed实用教程系列目录[已完成]

    本系列文章已经译完了,译自awk-sed@theunixschool,收获颇丰,作者没有讲明白的我做了补充,并且尝试讲的更清楚,整理成系列索引,方便学习,开篇非译文,是我为了方便后面的理解写的一篇,感 ...

  8. Qt Error: dependent '..\***' does not exist.

    大概意思:所依赖的资源不存在. 实际上是工程找不到所依赖的资源. 本人的解决方案(可能拙劣,也不一定是正道):将资源拷贝到工程目录下.

  9. java中String byte HexString的转换

    原文:http://blog.sina.com.cn/s/blog_62e9ec530101ebv6.html HexString——>byte public static byte[] hex ...

  10. ruby -- 基础学习(八)中文字符串截取的函数

    学习来源:http://www.codesky.net/article/200910/166595.html truncate(text, length = 30, truncate_string = ...