zoukankan      html  css  js  c++  java
  • Excel催化剂开源第15波-VSTO开发之DataTable数据导出至单元格区域

    上篇提到如何从Excel界面上拿到用户的数据,另外反方向的怎样输出给用户数据,也是关键之处。

    VSTO最大的优势是,这双向的过程中,全程有用户的交互操作。

    而一般IT型的程序,都是脱离用户的操作,只能让用户准备好数据,离开Excel,或生成数据,要重新打开某文件才能获取到数据结果。

    在VSTO中,用户随时在Excel最强UI前端中生产数据,同时也在获得数据结果后,无缝地利用Excel强大的数据处理能力进行数据的再次加工如Vlookup一些其他信息进来,做个图表展示等等。

    VSTO程序在用户全程数据链条中,都无缝地参与了,只在用户无法解决的复杂数据转换时,才使用二次开发进行处理,处理完,立即可进行下游的其他操作,用户体验绝对是一流。

    言归正传,如何DataTable数据导出至单元格区域

    在传统的VBA方法中,有ADO的某个方法CopyToRange,直接将DataRecordset的数据输出至单元格区域。

    许多VSTO用户还在抱怨着ADO.Net没有相应的方法而郁闷万方,看完此篇内容,会彻底改观,并且可以彻底放弃ADO这样的落后的技术,拥抱ADO.Net这样与时俱进的专业程序猿使用的技术。

    DataTable当然可以很轻松地转换为二维数组,再用Range.Resize的方式将二维数组返回给单元格区域,这不失为一个方法,但此处再次强调,这不是最优的方法。

    在VSTO中,提供了ListObject的数据对象,区别于传统VBA中能够使用的ListObject。它是在Microsoft.Office.Tools.Excel命名空间内,是VSTO的宿主项,较传统的ListObject,其命名空间为Microsoft.Office.Interop.Excel,新的ListObject得到很大的增强,其中最明显的是可以绑定数据,类似DataGridView一样。

    具体代码实现
    先创建一个Microsoft.Office.Tools.Excel命名空间内下的ListObject

    public static ListObject CreateNewVSTOListObject(string outputSheetName, bool isRetainExistingTable)
            {
                Excel.Worksheet sht;
                if (isRetainExistingTable)
                {
                    sht = Common.ExcelApp.ActiveWorkbook.Worksheets.Add();
                    try
                    {
                        sht.Name = outputSheetName;
                    }
                    catch (Exception)
                    {
                        outputSheetName = outputSheetName + DateTime.Now.ToString("yyyyMMddhhmmss");
                        sht.Name = outputSheetName;
                    }
                }
                else
                {
                    try
                    {
                        sht = Common.ExcelApp.ActiveWorkbook.Worksheets[outputSheetName];
                        var displayAlertsStatus = Common.ExcelApp.DisplayAlerts;
    
                        if (displayAlertsStatus == true)
                        {
                            Common.ExcelApp.DisplayAlerts = false;
                            sht.Delete();
                            Common.ExcelApp.DisplayAlerts = true;
                        }
                    }
                    catch (Exception)
                    {
                    }
                    sht = Common.ExcelApp.ActiveWorkbook.Worksheets.Add();
                    sht.Name = outputSheetName;
                }
    
                Worksheet vstoSht = Globals.Factory.GetVstoObject(sht);
                ListObject listObject = vstoSht.Controls.AddListObject(sht.Range["A1"], outputSheetName);
                return listObject;
            }
    

    再将DataTable绑定到ListObject的Datasource上,整个过程结束。

    public static void OutputDataToListObject(ListObject listObject, DataTable outputTable, bool isTransDataType=false,string[] mapCols=null)
    {
    ////先提取listDstTable原有公式
    Dictionary<string, string> dicListObjectCalColumns = GetCalColumnsOfListObject(listObject);
    //激活工作表
    Excel.Worksheet actSht = (Excel.Worksheet)listObject.Parent;
    actSht.Activate();

            listObject.AutoSetDataBoundColumnHeaders = true;
            listObject.ShowHeaders = true;
    
            if (mapCols!=null)
            {
                listObject.MappedColumns = mapCols;
            }
           
            //转换列数据格式
            if (isTransDataType)
            {
                ////先绑定没有数据的dtEmpty,用于调整列的数字格式
                DataTable dtEmpty = outputTable.Clone();
                listObject.SetDataBinding(dtEmpty);
                TransDataTypeOfListObject(listObject, dtEmpty);
            }
    
            ////重新绑定数据,用有数据的DataTable
            listObject.SetDataBinding(outputTable);
            listObject.AutoSetDataBoundColumnHeaders = false;
            TransHeaderNameOfListObject(listObject);
            listObject.Disconnect();
            //追加之前用户加入的公式,有可能会报错的,用Try-Catch来处理
            AddCustomCalColumns(listObject, dicListObjectCalColumns);
            ////自动调整列宽
            AutoFitColumnWidth(listObject);
    
        }
    

    大数据下的数据导出

    对于数据量较大的数据导出需求时,用ListObject的数据绑定方式导出,有性能瓶颈,可考虑用EPPLUS的方式读写Excel文件。

     public static void OutputDataByEpplus(ListObject listObject, DataTable outputTable, bool isTransDataType)
            {
    
                var actSht = (Excel.Worksheet)listObject.Parent;
                Excel.Workbook actWkb = actSht.Parent;
    
                string shtName = actSht.Name;
                string tableName = listObject.Name;
    
                ////先提取listDstTable原有公式
                Dictionary<string, string> dicListObjectCalColumns = GetCalColumnsOfListObject(listObject);
    
                listObject.Delete();
    
                string filePath = actWkb.FullName;
    
                var listCustomStyleIncludeInfos = StyleSetting.GetCustomStyleIncludeInfos(actWkb);
                actWkb.Close(SaveChanges: true);
    
                var fi = new FileInfo(filePath);
                using (var p = new ExcelPackage(fi))
                {
                    ExcelWorksheet sht = p.Workbook.Worksheets[shtName];
                    sht.Cells[1, 1].LoadFromDataTable(outputTable, true, OfficeOpenXml.Table.TableStyles.Light19);
                    sht.Tables[0].Name = tableName;
                    p.Save();
                };
                Excel.Workbook workbook = Common.ExcelApp.Workbooks.Open(filePath);
                StyleSetting.SetCustomeStyleIncludInfos(actWkb, listCustomStyleIncludeInfos);
    
                Excel.Worksheet dstSht = workbook.Worksheets[shtName];
                dstSht.Activate();
                var vstoListObject = Globals.Factory.GetVstoObject(dstSht.ListObjects[tableName]);
                //转换格式
                if (isTransDataType)
                {
                    TransDataTypeOfListObject(vstoListObject, outputTable);
                }
                //修改列名
                TransHeaderNameOfListObject(vstoListObject);
                //追加之前用户加入的公式,有可能会报错的,用Try-Catch来处理
                AddCustomCalColumns(vstoListObject, dicListObjectCalColumns);
                ////自动调整列宽
                AutoFitColumnWidth(vstoListObject);
    
            }
    

    结语

    通过此篇介绍,给广大开发者特别是VBA转移过来的VSTO开发者带来一些新的方式,不止于只是语法上的更新层面,在.Net环境下开发OFFICE程序时,可以用到许多新的技术和功能,并且较VBA时代的更好用、更易用。

    同样最后一句话总结,可以让大家更聚焦在业务逻辑的实现上,通用性的功能,只需找相应的现成轮子帮助即可。

    技术交流QQ群

    QQ群名:Excel催化剂开源讨论群, QQ群号:788145319

     
    Excel催化剂开源讨论群二维码

    关于Excel催化剂

    Excel催化剂先是一微信公众号的名称,后来顺其名称,正式推出了Excel插件,插件将持续性地更新,更新的周期视本人的时间而定争取一周能够上线一个大功能模块。Excel催化剂插件承诺个人用户永久性免费使用!

    Excel催化剂插件使用最新的布署技术,实现一次安装,日后所有更新自动更新完成,无需重复关注更新动态,手动下载安装包重新安装,只需一次安装即可随时保持最新版本!

    Excel催化剂插件下载链接:https://pan.baidu.com/s/1Iz2_NZJ8v7C9eqhNjdnP3Q

     
    联系作者
     
    公众号

    取名催化剂,因Excel本身的强大,并非所有人能够立马享受到,大部分人还是在被Excel软件所虐的阶段,就是头脑里很清晰想达到的效果,而且高手们也已经实现出来,就是自己怎么弄都弄不出来,或者更糟的是还不知道Excel能够做什么而停留在不断地重复、机械、手工地在做着数据,耗费着无数的青春年华岁月。所以催生了是否可以作为一种媒介,让广大的Excel用户们可以瞬间点燃Excel的爆点,无需苦苦地挣扎地没日没夜的技巧学习、高级复杂函数的烧脑,最终走向了从入门到放弃的道路。

    最后Excel功能强大,其实还需树立一个观点,不是所有事情都要交给Excel去完成,也不是所有事情Excel都是十分胜任的,外面的世界仍然是一个广阔的世界,Excel只是其中一枚耀眼的明星,还有其他更多同样精彩强大的技术、工具等。*Excel催化剂也将借力这些其他技术,让Excel能够发挥更强大的爆发!

    关于Excel催化剂作者

    姓名:李伟坚,从事数据分析工作多年(BI方向),一名同样在路上的学习者。
    服务过行业:零售特别是鞋服类的零售行业,电商(淘宝、天猫、京东、唯品会)

    技术路线从一名普通用户,通过Excel软件的学习,从此走向数据世界,非科班IT专业人士。
    历经重重难关,终于在数据的道路上达到技术平原期,学习众多的知识不再太吃力,同时也形成了自己的一套数据解决方案(数据采集、数据加工清洗、数据多维建模、数据报表展示等)。

    擅长技术领域:Excel等Office家族软件、VBA&VSTO的二次开发、Sqlserver数据库技术、Sqlserver的商业智能BI技术、Powerbi技术、云服务器布署技术等等。

    2018年开始职业生涯作了重大调整,从原来的正职工作,转为自由职业者,暂无固定收入,暂对前面道路不太明朗,苦重新回到正职工作,对Excel催化剂的运营和开发必定受到很大的影响(正职工作时间内不可能维护也不可能随便把工作时间内的成果公布于外,工作外的时间也十分有限,因已而立之年,家庭责任重大)。

    和广大拥护者一同期盼:Excel催化剂一直能运行下去,我所惠及的群体们能够给予支持(多留言鼓励下、转发下朋友圈推荐、小额打赏下和最重点的可以和所在公司及同行推荐推荐,让我的技术可以在贵司发挥价值,实现双赢(初步设想可以数据顾问的方式或一些小型项目开发的方式合作)。

    技术交流QQ群

    QQ群名:Excel催化剂开源讨论群, QQ群号:788145319

     
    Excel催化剂开源讨论群二维码

    关于Excel催化剂

    Excel催化剂先是一微信公众号的名称,后来顺其名称,正式推出了Excel插件,插件将持续性地更新,更新的周期视本人的时间而定争取一周能够上线一个大功能模块。Excel催化剂插件承诺个人用户永久性免费使用!

    Excel催化剂插件使用最新的布署技术,实现一次安装,日后所有更新自动更新完成,无需重复关注更新动态,手动下载安装包重新安装,只需一次安装即可随时保持最新版本!

    Excel催化剂插件下载链接:https://pan.baidu.com/s/1Iz2_NZJ8v7C9eqhNjdnP3Q

     
    联系作者
     
    公众号

    取名催化剂,因Excel本身的强大,并非所有人能够立马享受到,大部分人还是在被Excel软件所虐的阶段,就是头脑里很清晰想达到的效果,而且高手们也已经实现出来,就是自己怎么弄都弄不出来,或者更糟的是还不知道Excel能够做什么而停留在不断地重复、机械、手工地在做着数据,耗费着无数的青春年华岁月。所以催生了是否可以作为一种媒介,让广大的Excel用户们可以瞬间点燃Excel的爆点,无需苦苦地挣扎地没日没夜的技巧学习、高级复杂函数的烧脑,最终走向了从入门到放弃的道路。

    最后Excel功能强大,其实还需树立一个观点,不是所有事情都要交给Excel去完成,也不是所有事情Excel都是十分胜任的,外面的世界仍然是一个广阔的世界,Excel只是其中一枚耀眼的明星,还有其他更多同样精彩强大的技术、工具等。*Excel催化剂也将借力这些其他技术,让Excel能够发挥更强大的爆发!

    关于Excel催化剂作者

    姓名:李伟坚,从事数据分析工作多年(BI方向),一名同样在路上的学习者。
    服务过行业:零售特别是鞋服类的零售行业,电商(淘宝、天猫、京东、唯品会)

    技术路线从一名普通用户,通过Excel软件的学习,从此走向数据世界,非科班IT专业人士。
    历经重重难关,终于在数据的道路上达到技术平原期,学习众多的知识不再太吃力,同时也形成了自己的一套数据解决方案(数据采集、数据加工清洗、数据多维建模、数据报表展示等)。

    擅长技术领域:Excel等Office家族软件、VBA&VSTO的二次开发、Sqlserver数据库技术、Sqlserver的商业智能BI技术、Powerbi技术、云服务器布署技术等等。

    2018年开始职业生涯作了重大调整,从原来的正职工作,转为自由职业者,暂无固定收入,暂对前面道路不太明朗,苦重新回到正职工作,对Excel催化剂的运营和开发必定受到很大的影响(正职工作时间内不可能维护也不可能随便把工作时间内的成果公布于外,工作外的时间也十分有限,因已而立之年,家庭责任重大)。

    和广大拥护者一同期盼:Excel催化剂一直能运行下去,我所惠及的群体们能够给予支持(多留言鼓励下、转发下朋友圈推荐、小额打赏下和最重点的可以和所在公司及同行推荐推荐,让我的技术可以在贵司发挥价值,实现双赢(初步设想可以数据顾问的方式或一些小型项目开发的方式合作)。

    姓名:李伟坚 从事数据分析工作多年(BI方向),一名同样在路上的学习者。 技术路线从一名普通用户,通过Excel软件的学习,从此走向数据世界,非科班IT专业人士。 历经重重难关,终于在数据的道路上达到技术平原期,学习众多的知识不再太吃力,同时也形成了自己的一套数据解决方案(数据采集、数据加工清洗、数据多维建模、数据报表展示等)。 擅长技术领域:Excel等Office家族软件、VBAVSTO的二次开发、Sqlserver数据库技术、Sqlserver的商业智能BI技术、Powerbi技术、云服务器布署技术等等。 2018年起成为自由职业工作者,期待Excel催化剂可以一直能运行下去,我所惠及的群体们能够给予支持(多留言鼓励下、转发下朋友圈推荐、小额打赏下和最重点的可以和所在公司及同行推荐推荐,让我的技术可以在贵司发挥价值,实现双赢,初步设想可以数据顾问的方式或一些小型项目开发的方式合作。
  • 相关阅读:
    如何建一个SAM
    3.Telegraf自定义脚本模块
    2.Influxdb函数
    1.自动化运维监控
    7.mysql8.0版本MGR搭建
    6.mysql存储过程
    5.innodb B+tree索引
    4.mysql profile的使用方法
    3.mysql小表驱动大表的4种表连接算法
    2.mysql explain命令详解
  • 原文地址:https://www.cnblogs.com/ExcelCuiHuaJi/p/10579027.html
Copyright © 2011-2022 走看看