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

2021-08-19 15:55:52 浏览数 (1)

在Excel催化剂推出的这一年多时间里,经常性听到一种声音,大概意思是真正会写代码的人,都不会看上Excel催化剂写出来的功能,自己造一个更舒服贴心,仿佛会一点VBA就可以天下无敌一般,也好像Excel催化剂出的所有的功能,在他们眼中都是幼儿园级别,过家家玩玩而已。 这里不对此看法置评,只用事实说话,看看会一点VBA的人,能否造出以下的超强性能保障的代码功能来。

遍历单元格性能问题

学过VBA的群体,都知道遍历单元格是一个很慢的过程,最好将其放进数组中再遍历。

为何会慢这个问题,可能就没有深入研究过,而笔者用自己不专业的语言表达下原因,是因为VBA或VSTO等代码与Excel交互是用的是COM的通信,这个COM通信非常臃肿,遍历过程中,不断地来回通信,产生了十分低效的性能。

而数据在数组里,即放到内存里访问了,无需再频繁和COM接口通信,所以可以快起来。

除了COM接口访问还有其他访问方式

对于VBA、VB的开发来说,也只能用COM接口访问了,没有专业程序员世界给他们造一些好用的轮子可以直接访问xls或xlsx文件。

但在VSTO的.Net世界中,这个需求非常刚需,特别是服务器级别的应用,不可能再用COM接口来通信应付高并发性需求。所以出现了大量优秀的第3方访问类库轮子,在.Net的世界比较出名的有NPOI和EPPLUS。

因Excel催化剂并且为了满足所有用户需求而存在,对仍然使用低版本OFFICE2003版本是不支持的,所以就有所取舍,大量的场景会使用EPPLUS这个只支持OFFICE2007及以上的格式的类库轮子。

在普通遍历上可以用数组或原生的查找方法,但在需要查找替换旧数据,并且需要使用正则表达式来匹配的场景中,用以上两种方法就显得非常笨拙。

EPPLUS遍历单元格方式

以下应用的功能原始出处为:第75波-标签式报表转标准数据源https://www.jianshu.com/p/a876134c9e8f

遍历单元格在EPPLUS上非常简单,和直接在VBA对象模型上操作差不多(用NPOI就差异性较大,所以不喜欢用它)。

直接上代码 此段代码是第75波核心代码,用于将查找到的结果存储为新的表格内容,最终返回给用户一个结构化的数据源。

代码语言:javascript复制
 private static void AddMatchDataToDataTable(bool isActWkb, string filePath, DataTable settingTable, ref DataTable resultTable)
        {
            using (var package = new ExcelPackage(new FileInfo(filePath)))
            {
                ExcelWorkbook wkb = package.Workbook;

                foreach (var itemSht in wkb.Worksheets)
                {
                    string itemShtName = itemSht.Name;
                    if (itemShtName != settingShtName && itemShtName != resultShtName)
                    {
                        foreach (var cell in itemSht.Cells)
                        {
                            if (cell.Value != null)
                            {
                                bool isMatch = IsMatchPattern(pattern, matchType, isIgnoreCase, lookin, isRegexMatch, cell);
                                if (isMatch)
                                {
                                    DataRow dr = resultTable.NewRow();
                                    dr["工作薄路径"] = package.File;
                                    dr["工作表名称"] = itemShtName;

                                    int iStart = 2;
                                    foreach (DataRow row in settingTable.Rows)
                                    {
                                        //todo
                                        dr[iStart] = GetCellInfo(cell.Offset(Convert.ToInt32(row[1]), Convert.ToInt32(row[2])));
                                        iStart  ;
                                    }
                                    resultTable.Rows.Add(dr);
                                }

                            }
                        }
                    }

                    if (isActWkb)
                    {
                        AddDataToResultSht(resultTable, wkb);
                        package.Save();
                    }// if (isActWkb)
                }//foreach (var itemSht in wkb.Worksheets)
            }

        }

结语

在VSTO的世界中,可以调用一切专业程序员所写给我们的轮子库,相对VBA的开发来说,有天然的优势,有追求的群体,不妨再走一步,走出VBA的舒适区,拥抱VSTO的开发,会是一片更广阔的天空。

0 人点赞