Excel催化剂开源第16波-VSTO开发之脱离传统COM交互以提升性能

在VSTO开发或其他COM技术开发过程中,甚至VBA也是,在和Excel交互中,难免会遇到性能瓶颈问题,COM技术的交互实在太慢,对大量数据读写等操作,耗时太长,容易卡用户界面以为是程序死机等等。

在专业程序猿开发群体,极少直接用COM的方式来访问Excel文件,都是以其他的非COM如最为流行的NPOI和EPPLUS类库的方式访问,并且是免费的可用于商业项目的。

在VSTO中调用NPOI和EPPLUS,又是怎样一翻境界呢?因Excel催化剂主要是为数据分析群体服务,其中大量的场景是面积大数据量的,它大量使用了此两大累库,实现一些数据读取和数据导出的功能以提升程序性能。

为何要同时使用两大开源类库?

两大类库,各有特色,NPOI支持xls和xlsx两种格式文档,但其API接口稍难用,和日常VBA接口方法很大差异,且调用时麻烦。而EPPLUS的话,只能用于xml结构的xlsx文档,因此实现的接口好用,若只针对xlsx版格式的文档读写,首选EPPLUS。

既然是插件,不能限制用户使用文档的格式,兼容于低版本格式文件时,只能同时用两大类库,在不损失开发效率上,同时兼顾对用户的文档多样性场景需求。最终牺牲了一些程序大小问题,但Excel催化剂已在前述文章中提及,将引用dll文件分离将不影响我们后续的升级功能时的升级性能,总体来说,还是可以取得很好的平衡性。

在Excel催化剂上的使用场景

数据导出场景

在前一波中提到,DataTable的数据导出Excel单元格区域上,我们已经提及到若数据量大,改用EPPLUS来导出,在EPPLUS上将数据导出到工作表,只需一个现成的已封装好的方法。具体代码如下:

            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的Com方法对工作薄进行打开,关闭,其性能极其低下,若用NPOI或EPPLUS 类库,速度就快出好几十倍,在多文件下有必要转换成此两种类库访问。在Excel催化剂的合并工作表/薄,拆分工作表/薄的场景中大量使用。

遍历单元格属性

同样的,若不是仅仅获取单元格上的数据,而是需要获取单元格的其他属性如字体颜色、填充颜色、字号、字体名称、样式等信息时,用COM访问的方式,也是有十分大的性能瓶颈问题。

在Excel单元格管理相关功能上,大量使用了EPPLUS类库作这些的遍历访问,性能十分优秀。
具体代码发以下:

 private static void FillCellInfosToNewSht(StyleActivateScope styleScope, string shtName, string selRangeAddress, FileInfo fileInfo, DataTable resultTable, Func<ExcelRangeBase, bool> isMatchCell)
        {
            using (ExcelPackage package = new ExcelPackage(fileInfo))
            {
                ExcelWorkbook wkb = package.Workbook;
                //先删除结果表
                if (wkb.Worksheets.Any(s => s.Name == newShtName))
                {
                    wkb.Worksheets.Delete(wkb.Worksheets[newShtName]);
                }

                if (styleScope == StyleActivateScope.StyleWkb)
                {
                    foreach (var sht in wkb.Worksheets)
                    {
                        foreach (var cell in sht.Cells[sht.Dimension.Address])
                        {
                            if (isMatchCell(cell))
                            {
                                AddRowToTable(resultTable, sht.Name, cell);
                            }

                        }
                    }
                }
                else if (styleScope == StyleActivateScope.StyleSht)
                {
                    var sht = wkb.Worksheets[shtName];
                    foreach (var cell in sht.Cells[sht.Dimension.Address])
                    {
                        if (isMatchCell(cell))
                        {
                            AddRowToTable(resultTable, sht.Name, cell);
                        }
                    }
                }
                else
                {
                    var sht = wkb.Worksheets[shtName];
                    foreach (var cell in sht.Cells[selRangeAddress])
                    {
                        if (isMatchCell(cell))
                        {
                            AddRowToTable(resultTable, sht.Name, cell);
                        }
                    }
                }

                var newSht = wkb.Worksheets.Add(newShtName);
                newSht.Cells["A1"].LoadFromDataTable(resultTable, true, OfficeOpenXml.Table.TableStyles.Light1);
                package.Save();
            }
        }

        private static void AddRowToTable(DataTable resultTable, string shtName, ExcelRangeBase cell)
        {
            DataRow dr = resultTable.NewRow();
            dr[0] = shtName;

            string cellAddress = cell.Address;
            dr[1] = cellAddress;
            dr[2] = Regex.Match(cellAddress, @"\d+").Value;
            dr[3] = Regex.Match(cellAddress, @"[A-Za-z]+").Value;

            var cellValue = cell.Value;
            dr[4] = cellValue;
            dr[5] = cellValue is string ? "文本" : "数字";

            string cellFormula = cell.Formula;
            dr[6] = cellFormula;
            dr[7] = cellFormula.Contains("!") ? true : false;
            dr[8] = cell.StyleName;

            resultTable.Rows.Add(dr);
        }

结语

表面上大家都一样的插件功能,Excel催化剂内核上可完全地不一样,实现的效果无论是性能上还是用户友好度体验上,都是和其他一般性VBA写出来的插件有很大的差距。就如同样一辆汽车,有吉利的和奔驰的,大家都叫汽车。

希望此篇分享的技术,日后能够带后整体VSTO开发插件的开发者们有技能的提升。

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

原文地址:https://www.cnblogs.com/ExcelCuiHuaJi/p/10579044.html

时间: 2024-08-05 00:49:55

Excel催化剂开源第16波-VSTO开发之脱离传统COM交互以提升性能的相关文章

Excel催化剂开源第14波-VSTO开发之单元格区域转DataTable

在Excel开发过程中,大部分时候是和Range单元格区域打交道,在VBA开发中,大家都知道的一点是,不能动不动就去遍历所有单元格,那性能是非常糟糕的,很多时候,是需要把整个单元格区域装入数组中再作处理的. 在VSTO开发中,难不成还要用VBA这套老掉牙的东西来做吗?VBA的二维数组在.Net的世界中,真的一无是处,太多比它好用的东西存在,其中笔者最喜欢用的是DataTable这样的结构化的数据结构. 从单元格到DataTable,其实也就几句代码的事情,当数据进入到DataTable后,可以使

Excel催化剂开源第15波-VSTO开发之DataTable数据导出至单元格区域

上篇提到如何从Excel界面上拿到用户的数据,另外反方向的怎样输出给用户数据,也是关键之处. VSTO最大的优势是,这双向的过程中,全程有用户的交互操作. 而一般IT型的程序,都是脱离用户的操作,只能让用户准备好数据,离开Excel,或生成数据,要重新打开某文件才能获取到数据结果. 在VSTO中,用户随时在Excel最强UI前端中生产数据,同时也在获得数据结果后,无缝地利用Excel强大的数据处理能力进行数据的再次加工如Vlookup一些其他信息进来,做个图表展示等等. VSTO程序在用户全程数

Excel催化剂开源第17波-VSTO开发之ADO.Net访问Sqlserver

在Excel催化剂中,独树一帜地推出了Excel与数据库交互功能,目前仅实现了对Sqlserver的交互,在通用型插件中仅此一家,别无其他. 为何会出现这样的局面呢,原因大概有以下几大方面: 和数据库交互的使用群体太窄,除非极个别数据分析师会用到这个问题的确存在,在Excel群体中,能够有机会接触到数据库层面的聊聊无几,当属于最上层高级Excel用户才会涉猎,对Excel催化剂来说,本来群体已定位为重度Excel高级用户使用,有此功能才显得插件的饱满性. 开发者本身不懂数据库,更无从开发数据库相

Excel催化剂开源第43波-Excel选择对象Selection在.Net开发中的使用

Excel的二次开发有一极大的优势所在,可以结合用户的交互进行程序的运行,大量用户的交互,都是从选择对象开始,用户选择了单元格区域.图形.图表等对象,之后再进行程序代码的加工处理,生成用户所需的最终结果. 所以熟练处理选择对象,尤其关键,而在VBA里的使用方法,来到.Net中特别是C#语言下,就需要另外的代码处理,希望此篇的分享给VBA转VSTO的朋友们带来一些帮助指引. 在VBA中,判断一个Selection对象是什么类型的方法如下: Sub test() Dim sel Set sel =

Excel催化剂开源第51波-Excel催化剂遍历单元格操作性能保障

在Excel催化剂推出的这一年多时间里,经常性听到一种声音,大概意思是真正会写代码的人,都不会看上Excel催化剂写出来的功能,自己造一个更舒服贴心,仿佛会一点VBA就可以天下无敌一般,也好像Excel催化剂出的所有的功能,在他们眼中都是幼儿园级别,过家家玩玩而已. 这里不对此看法置评,只用事实说话,看看会一点VBA的人,能否造出以下的超强性能保障的代码功能来. 遍历单元格性能问题 学过VBA的群体,都知道遍历单元格是一个很慢的过程,最好将其放进数组中再遍历. 为何会慢这个问题,可能就没有深入研

Excel催化剂开源第36波-图片Exif信息提取,速度超快,信息超全

Excel催化剂在文件处理方面,功能做到极致,但其实很大功劳都是引用一些开源社区的轮子库,不敢独占好处,此篇给大家分享下抓取图片的Exif信息的好用的轮子. 此篇对应的Excel催化剂功能实现:第83波-遍历文件夹内文件信息特别是图像.音视频等特有信息 https://www.jianshu.com/p/ad98adc64f0b 当然再次强调,找东西尽量用google,百度是非常低效,找出来的代码,好多也不适用,吐槽下百度最喜欢收录CSDN的文章,只是物以类聚,垃圾对垃圾,广告婊子一个.真要搜索

Excel催化剂开源第47波-Excel与PowerBIDeskTop互通互联之第一篇

当国外都在追求软件开源,并且在GitHub等平台上产生了大量优质的开源代码时,但在国内却在刮着一股收割小白智商税的知识付费热潮,实在可悲. 互联网的精神乃是分享,让分享带来更多人的受益. 在PowerBI领域,出现了十分优秀的DAXStudio和Tabular Editor等开源工具,影响深远.借此,Excel催化剂也决定将最核心的.也是PowerBI群体中热切盼望到功能点进行开源. 但愿从中受益的群体,不要将其视为其有,并且利用信息不对称继续进行收割智商税的延续,并且最好能够在引用时按开源的原

Excel催化剂开源第50波-Excel与PowerBIDeskTop互通互联之第四篇

答应过的全盘分享,也必承诺到底,此篇PowerBI功能分享的最后一篇,讲述如何导出数据模型的元数据,笔者定义其为模型的数据字典. 此篇对应功能实现出自:第6波-导出PowerbiDesktop模型数据字典https://www.jianshu.com/p/bc26a8dcdfce 关系型数据库有数据字典,分析型数据库更加要有数据字典,DAX建模过程中,若模型的关系复杂,引用的表过多,生成的度量值.计算列过多,单单从PowerBIDeskTop去查看模型关系非常低效. 当然最好的查看方式,在全宇宙

Excel催化剂开源第35波-图片压缩及自动旋转等处理

Excel催化剂在图片处理方面,也是做到极致化,一般的Excel插件插入图片是原图插入或不可控制压缩比例地方式插入图片至Excel当中,但Excel催化剂的插入图片,是开发了可调节图片大小的插入方式,让图片在Excel上可以有预期的像素大小和文件大小的平衡. 在图片处理方面,完全可以借助一个非常棒的类库,实现美图秀秀那般日常的图片处理. 此篇对应的Excel催化剂功能实现:第11波-快速批量插入图片并保护纵横比不变 https://www.jianshu.com/p/9a3d9aa7ba7e E