在很多系统,我们都知道,Excel数据的导入导出操作是必不可少的一个功能,这种功能能够给使用者和外部进行数据交换,也能批量迅速的录入数据到系统中;但在一些系统中,为了方便,可能把很多个基础表或者相关的数据综合到一个Excel表格文件里面,然后希望通过接口进行导入,这种需求处理就显得比较复杂一点了。本文探讨在我的客户关系管理系统中,对于单个Excel表格中,集合了客户基础数据及相关数据的导入和导出操作的处理。

1、导入导出的需求分析

本随笔主要介绍如何在系统中,导入单一文件中的数据到系统中,这个文件包含了基础数据和相关数据的导入和导出操作,一般来说这样的操作对于导入数据已经足够简便了,但是,有时候数据很多的情况下,我们可能需要每次选定文件也是一个麻烦的事情。因此指定目录进行批量数据的导入操作也是一个好的需求,可以进一步简化用户的数据导入操作。

下面我们就来介绍,导入、批量导入和导出的三个重要的操作,如图所示。

导入的数据,是一个Excel,它要求包含几个不同表的数据,导入操作一次性完成数据的导入,Excel文件的格式如下所示。

2、数据导入操作的界面设计及处理

我们知道,要一次性导入几个表的数据,需要先读取Excel获取各个Sheet(工作表)的数据,然后把它转换为DataTable的数据对象,这样我们就可以根据它的字段赋值给对应的实体类,然后调用业务逻辑处理将数据写入数据库即可。

为了直观的给使用者查看将要导入的数据,我们把需要导入到数据库的数据,展现在界面上,供客户确认,如果没有问题,就可以进行导入操作。由于我们需要操作多个数据表,因此有效读取Excel里面的Sheet就是第一步工作。

查看Excel数据的操作代码如下所示,主要的逻辑就是调用Apose.Cell的封装类进行处理

AsposeExcelTools.ExcelFileToDataSet(this.txtFilePath.Text, out myDs, out error);

把Excel文件里面多个Sheet的数据转换为DataSet,然后每个进行依次的处理,展示代码如下所示。

        private void ViewData(){if (this.txtFilePath.Text == ""){MessageDxUtil.ShowTips("请选择指定的Excel文件");return;}try{myDs.Tables.Clear();myDs.Clear();this.gridCustomer.DataSource = null;string error = "";AsposeExcelTools.ExcelFileToDataSet(this.txtFilePath.Text, out myDs, out error);this.gridCustomer.DataSource = myDs.Tables[0];this.gridView1.PopulateColumns();this.gridFollow.DataSource = myDs.Tables[1];this.gridView2.PopulateColumns();this.gridContact.DataSource = myDs.Tables[2];this.gridView3.PopulateColumns();this.gridSupplier.DataSource = myDs.Tables[3];this.gridView4.PopulateColumns();}catch (Exception ex){LogTextHelper.Error(ex);MessageDxUtil.ShowError(ex.Message);}}

由于导入过程中需要耗费一定的时间,因此我们可以通过后台线程结合进度条的方式提示用户,界面设计效果如下效果所示。

刚才说到,保存数据,我们把它放到后台线程BackgroudWorker进行处理即可,处理代码如下所示。

        private void btnSaveData_Click(object sender, EventArgs e){if (worker.IsBusy)return;if (this.txtFilePath.Text == ""){MessageDxUtil.ShowTips("请选择指定的Excel文件");return;}if (MessageDxUtil.ShowYesNoAndWarning("该操作将把数据导入到系统数据库中,您确定是否继续?") == DialogResult.Yes){if (myDs != null && myDs.Tables[0].Rows.Count > 0){this.progressBar1.Visible = true;worker.RunWorkerAsync();}}}

后台线程操作的主要业务逻辑代码如下所示,就是依次把不同的数据进行解析,并保存即可。

        void worker_DoWork(object sender, DoWorkEventArgs e){if (myDs != null && myDs.Tables.Count >= 4 && myDs.Tables[0].Rows.Count > 0){try{ImportCustomerDataHelper helper = new ImportCustomerDataHelper();helper.LoginUserInfo = LoginUserInfo;//写入或更新客户信息string customerID = helper.UpdateCustomer(myDs.Tables[0]);if (!string.IsNullOrEmpty(customerID)){helper.AddFollow(customerID, myDs.Tables[1], worker);helper.AddContact(customerID, myDs.Tables[2], worker);helper.AddSupplier(customerID, myDs.Tables[3], worker);e.Result = "操作完成";}else{e.Result = "操作失败";}}catch (Exception ex){e.Result = ex.Message;LogTextHelper.Error(ex);MessageDxUtil.ShowError(ex.ToString());}}else{e.Result = "请检查数据记录是否存在";}}

3、数据批量导入操作

虽然上面可以一次性导入客户和其相关数据,但是还是一次性导入一个Excel,如果对于客户数据比较多的情况下,一次次导入操作也是很繁琐的事情,因此客户提出,需要按照目录把所有相关的Excel数据一次性导入,这种导入有个问题就是我们不能再中途干预导入操作,因此为了数据的安全性,我提供一个界面让客户选择目录,然后把目录里面的Excel文件列出来,然后在让客户确认是否进一步导入。

上面操作的实现代码我逐一介绍,首先第一步是需要递归列出目录下面的Excel文件,然后显示出来供用户确认导入的清单。

        private void btnSelectPath_Click(object sender, EventArgs e){string mydocDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);string selectPath = FileDialogHelper.OpenDir(mydocDir);if (!string.IsNullOrEmpty(selectPath)){       //清空就记录this.lstPath.Items.Clear();string[] fileArray = Directory.GetFiles(selectPath, "*.xls", SearchOption.AllDirectories);if (fileArray != null && fileArray.Length > 0){foreach (string file in fileArray){string fileName = Path.GetFileName(file);this.lstPath.Items.Add(new CListItem(fileName, file));}}}}

当用户确认操作的时候,提示客户确认是否进行,确认后将统一批量导入列表里面的文件,这个地方也是为了方便,使用后台线程进行数据的导出操作,并在过程中提供进度条的指示。

        private void btnConfirm_Click(object sender, EventArgs e){if (worker.IsBusy)return;if (this.lstPath.Items.Count > 0){if (MessageDxUtil.ShowYesNoAndTips("您确认导入列表的Excel文件吗?") == System.Windows.Forms.DialogResult.Yes){List<string> fileList = new List<string>();foreach (object item in this.lstPath.Items){CListItem fileItem = item as CListItem;if (fileItem != null){fileList.Add(fileItem.Value);}}this.progressBar1.Visible = true;worker.RunWorkerAsync(fileList);}}}

这个后台线程的处理逻辑和单个文件导入的操作差不多,只不过这里需要增加一个文件列表的遍历处理而已,具体代码如下所示。

        void worker_DoWork(object sender, DoWorkEventArgs e){List<string> fileList = e.Argument as List<string>;if (fileList == null || fileList.Count == 0) return;bool hasError = false;ImportCustomerDataHelper helper = new ImportCustomerDataHelper();helper.LoginUserInfo = LoginUserInfo;foreach (string file in fileList){DataSet myDs = new DataSet();string error = "";AsposeExcelTools.ExcelFileToDataSet(file, out myDs, out error);if (myDs != null && myDs.Tables.Count >= 4 && myDs.Tables[0].Rows.Count > 0){try{//写入或更新客户信息string customerID = helper.UpdateCustomer(myDs.Tables[0]);if (!string.IsNullOrEmpty(customerID)){
                            helper.AddFollow(customerID, myDs.Tables[1], worker);helper.AddContact(customerID, myDs.Tables[2], worker);helper.AddSupplier(customerID, myDs.Tables[3], worker);}}catch (Exception ex){hasError = true;LogTextHelper.Error(ex);}}}string msg = "操作完成";if (hasError){msg += ",导入出现错误。具体可以查看log.txt日志记录。";}e.Result = msg;}

和上面的单个文件导入一样,我们这里使用了一个封装类ImportCustomerDataHelper,用来对数据进行转换实体类,然后保存到数据库的操作过程,下面我们来简单看看里面的处理代码

    /// <summary>/// 客户数据的批量导入和普通导入的操作逻辑代码/// </summary>public class ImportCustomerDataHelper{/// <summary>/// 登陆用户信息/// </summary>public LoginUserInfo LoginUserInfo { get; set; }/// <summary>/// 写入或更新客户数据,如果成功更新返回ID值/// </summary>/// <param name="dataTable">客户数据表</param>/// <returns></returns>public string UpdateCustomer(DataTable dataTable){bool success = false;bool converted = false;DateTime dtDefault = Convert.ToDateTime("1900-01-01");DateTime dt;string result = "";DataRow dr = dataTable.Rows[0];if (dr != null){string customerName = dr["客户名称"].ToString();CustomerInfo info = CallerFactory<ICustomerService>.Instance.FindByName(customerName);bool isNew = false;if (info == null){info = new CustomerInfo();isNew = true;}info.Name = customerName;info.HandNo = dr["客户编号"].ToString();info.SimpleName = dr["客户简称"].ToString();..........................info.IsPublic = dr["公开与否"].ToString().ToBoolean();info.Satisfaction = dr["客户满意度"].ToString().ToInt32();info.TransactionCount = dr["交易次数"].ToString().ToInt32();info.TransactionTotal = dr["交易金额"].ToString().ToDecimal();info.Creator = dr["客户所属人员"].ToString();converted = DateTime.TryParse(dr["创建时间"].ToString(), out dt);if (converted && dt > dtDefault){info.CreateTime = dt;}info.Editor = LoginUserInfo.ID.ToString();info.EditTime = DateTime.Now;if (isNew){info.Dept_ID = LoginUserInfo.DeptId;info.Company_ID = LoginUserInfo.CompanyId;success = CallerFactory<ICustomerService>.Instance.Insert(info);}else{success = CallerFactory<ICustomerService>.Instance.Update(info, info.ID);}if (success){result = info.ID;}}return result;}

...........................

4、数据的导出操作

导出操作,我们根据用户的选择,可以一次性导出多个Excel文件,每个Excel文件包含客户的基础信息,也包含相关数据,它们的格式和导入的格式保持一致即可,这样方便数据的交换处理。

导出操作,我们需要把客户的选择信息转换为需要导出的对象列表数据,然后绑定到Excel里面即可,因此我们的Excel里面,可以通过自定义模板,指定列的数据属性就可以绑定好数据了。

获取选择的客户信息的代码如下所示。

                List<CustomerInfo> list = new List<CustomerInfo>();foreach (int iRow in rowSelected){string ID = this.winGridViewPager1.GridView1.GetRowCellDisplayText(iRow, "ID");CustomerInfo info = CallerFactory<ICustomerService>.Instance.FindByID(ID);if (info != null){list.Add(info);}}

前面介绍了,我们将使用自定义模板,在模板文件里面的对应字段下面,绑定一个参数属性就可以了,通过Aspose.Cell的操作处理,我们就很方便把数据导出到Excel里面了,而里面的字段还可以很方便实现自由的裁剪操作。

自定义模板文件效果如下所示。

导出客户以及相关信息的主要核心代码如下所示。

                            #region 导出操作//依次每个客户数据导出一个文件string ownerUserName = CallerFactory<IUserService>.Instance.GetFullNameByID(customerInfo.Creator.ToInt32());string filePath = Path.Combine(selectPath, ownerUserName);DirectoryUtil.AssertDirExist(filePath);Dictionary<string, object> dict = new Dictionary<string, object>();dict.Add("Customer", new List<CustomerInfo>() { customerInfo });//需要构造一个列表绑定
List<FollowInfo> followList = CallerFactory<IFollowService>.Instance.Find(string.Format("Customer_ID ='{0}' ", customerInfo.ID));dict.Add("Follow", followList);List<ContactInfo> contactList = CallerFactory<IContactService>.Instance.FindByCustomer(customerInfo.ID); dict.Add("Contact", contactList);PagerInfo pagerInfo = null;List<SupplierInfo> supplierList = CallerFactory<ISupplierService>.Instance.FindByCustomer(customerInfo.ID, "", ref pagerInfo);dict.Add("Supplier", supplierList);string templateFile = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "客户综合资料-导出模板.xls");if (!File.Exists(templateFile)){throw new ArgumentException(templateFile, string.Format("{0} 文件不存在,", Path.GetFileName(templateFile)));}string saveFileName = string.Format("{0}.xls", customerInfo.Name);string saveFilePath = Path.Combine(filePath, saveFileName);                            WorkbookDesigner designer = new WorkbookDesigner();designer.Workbook = new Workbook(templateFile);foreach (string key in dict.Keys){designer.SetDataSource(key, dict[key]);}designer.Process();designer.Workbook.Save(saveFilePath, SaveFormat.Excel97To2003);   #endregion

这样利用Aspose.Cell的处理操作,通过绑定相关的数据对象,我们就很容易实现数据导出到符合我们预期格式的Excel里面去了,这样操作高效、代码干净,Excel格式也非常符合我们的要求。

以上就是在客户关系管理系统里面碰到特殊的数据导入导出需求的介绍和实现,希望大家相互交流,共同把软件开发过程中,数据导入导出操作的使用体验做到最好,更符合我们客户使用的习惯和需求。

转载于:https://www.cnblogs.com/wuhuacong/p/3936963.html

客户关系管理系统中对客户及相关数据的导入导出分析处理相关推荐

  1. 客户关系管理系统中实现对客户信息标记颜色的处理

    在一些场合里面,我们需要对一些记录进行颜色标注处理,以标记记录的信息重要性或者进行类别区分,如在客户关系管理系统里面,我们需要对客户信息进行不同颜色的标注,方便对不同类别的管理,毕竟颜色区分还是比较直 ...

  2. MATLAB中文件的读写和数据的导入导出

    http://blog.163.com/tawney_daylily/blog/static/13614643620111117853933/ 在编写一个程序时,经常需要从外部读入数据,或者将程序运行 ...

  3. CRM客户关系管理系统开发第十七讲——实现客户拜访记录管理模块中分页查询客户拜访记录列表的功能

    在CRM客户关系管理系统中,客户的拜访是很重要的一个环节,由业务员面见客户并介绍公司的相关的业务,在业务员回到公司以后,需要对此次的拜访的整个过程记录下来,记录中需要包含拜访的客户的姓名,拜访的时间以 ...

  4. CRM客户关系管理系统让企业在竞争中脱颖而出

    在疫情的催化下,CRM客户关系管理系统被推到了企业风口.面临巨大的生存压力导致企业转型和数字化迫在眉睫.CRM客户关系管理系统作为一种专业的客户关系管理工具,再次受到青睐. CRM客户关系管理系统具有 ...

  5. 【Java项目实战】CRM客户关系管理系统

    客户关系管理系统,是指利用软件.硬件和网络技术,为企业建立一个客户信息收集.管理.分析和利用的信息系统.以客户数据的管理为核心,记录企业在市场营销和销售过程中和客户发生的各种交互行为,以及各类有关活动 ...

  6. 客户关系管理系统类毕业论文文献包含哪些?

    本文是为大家整理的客户关系管理系统主题相关的10篇毕业论文文献,包括5篇期刊论文和5篇学位论文,为客户关系管理系统选题相关人员撰写毕业论文提供参考. 1.[期刊论文]基于JavaEE的客户关系管理系统 ...

  7. 开发CRM客户关系管理系统需要多少钱

    现阶段各个领域都少不了和客户相处,所以也必须对住户关联进行监管,跟踪业务流程进度情况,促使协作.伴随着现代科技的高速发展,及其管理模式的兴起,CRM客户关系管理系统开发逐步完善,而且在销售工作普及化. ...

  8. 科研实习生 数据挖掘在陶瓷行业客户关系管理中的应用

    1.数据挖掘的概念 各种研究机构由于观点和背景的不同,对数据挖掘都有不同的定义.可以从技术角度进行定义,也可以从商业角度进行定义. 1).技术上的定义 数据挖掘(DataMninig)就是从大量的.不 ...

  9. CRM客户关系管理系统开发第一讲——搭建开发环境

    这个小项目是我们学习完Spring,Hibernate,Struts2这三个框架后,为了加深对它们的理解所做的SSH项目,为CRM客户关系管理系统. CRM客户关系管理系统的概述 什么是CRM客户关系 ...

  10. crm客户管理系统源码_公司crm客户关系管理系统的功能

    企业的最终目标是服务好客户,赢得客户的青睐.为了实现这一目标,除了扎实的产品和优秀的团队,我们还必须选择科学的管理体系来帮助企业实现这一最终目标.这个系统就是公司crm客户关系管理系统,点镜SCRM公 ...

最新文章

  1. linux内核第一个函数,通过内核源码看函数调用之前世今生 - 极光 - CSDN博客
  2. [SD2.0大会]王坚:Data–centric Computing
  3. python与数学的故事_我与数学的故事作文800字
  4. 物联网管理软件的设计
  5. 【codeforces 742A】Arpa’s hard exam and Mehrdad’s naive cheat
  6. $git学习总结系列(4)——gitignore文件
  7. C++实现字符串分割函数split()
  8. oracle 列级外键,Oracle 中的外键与锁
  9. 【小记】-006--关于高度塌陷的问题
  10. 昨天购入mac mini一台,4688元港币
  11. ad19电气规则检查_铁路机车操作规则(铁运2012281号)
  12. 已知六条边的边长,求四面体体积
  13. 第七届山东理工大学ACM趣味编程循环赛 Round#1 sdut4109 玄黄的字符串
  14. excel同一单元格怎么换行_自动换行还是强制换行?还有一键批量换行等着你
  15. 【THUSC2016】蒟蒻的酱油记
  16. android动态显示表格数据,android中水平显示表格数据
  17. 磊科nw362 linux驱动下载,磊科nw362无线网卡驱动
  18. JAVASE面向对象基础
  19. MySQL面试:为什么用自增列作为主键
  20. C#文本型数值转换为数值类型

热门文章

  1. BIO,NIO,AIO总结
  2. oracle 误删除数据,回退表数据
  3. 9 线性表-队列-链式存储
  4. 带你玩转Visual Studio——带你高效开发
  5. .AsEnumerable() 和 .ToList() 的区别:
  6. 使用maven给spring项目打可直接运行的jar包(配置文件内置外置的打法)
  7. 关于HTTP协议的学习
  8. 思考致富 成功法则(二):确定的目的
  9. Acticles about Interface!
  10. net core 通过js打印集合(创建树)