Excel对大数据分析处理的缺陷是天生的,所以微软后期引入了Power query、Access、SQL Server等,但我们又无法抛弃Excel,那便只好面对,对于中小型数据量,有以下方案,加速运算。
电脑配置
CPU:Intel的多核处理器,服务器平台的超多核为最佳。 内存:4G内存可以退出舞台,专业搞Excel,8G内存是底线,16G较合适。 硬盘:M.2接口,NVME协议的固态硬盘,256G是底线,512G较合适。
之所以不选AMD的CPU,是因为其对Excel的多线程计算支持太差,这个现象持续好几年了,不知是AMD的问题还是我的问题,虽然我一如既往的推崇AMD,但还是衷心建议大家,如果主要工作是处理Excel,尽量买Intel的CPU,如果是大数据量,尽量买Intel的服务器CPU,如E5系列,新版Excel已经不会出现一核有难八核围观的现象。
家用台式机CPU天梯图(选购左上部分带酷睿的即可): https://www.mydrivers.com/zhuanti/tianti/cpu/ 家用笔记本CPU天梯图(选购左上部分带酷睿的即可): https://www.mydrivers.com/zhuanti/tianti/cpum/
买电脑技巧:在京东,搜索CPU天梯图中的高端Intel型号+“台式机”三个字,然后筛选内存为16G及以上,固态512G及以上,搜出来的电脑,就看价格和喜好了。
插件和其他软件都要少开,保留硬件资源
尽量打开较少的工作簿,文件一旦多会导致抢运算资源; 尽量少开Excel插件,尤其是在大数据量进行计算的时候; 尽量少开其他占用电脑的程序,给Excel预留充足的计算能力。
从Excel的XLSB格式说起
大数据量或者说超过10M体积的的工作簿,应另存为xlsb格式。 Excel2007版(2006-2017)开始,在xls格式的基础上增加了xlsx格式和xlsb格式,其中: xls_x最后的x指xml格式,译为指可扩展标记语言(Extensible Markup Language); xls_b最后的b指binary格式,译为二进制。
Excel数据工作原理是这样的,在硬盘上它使用xml这样的人类可读语言储存信息,比如写作【】这样,在工作时要先转化为机器的二进制语言01010101到内存里喂给电脑。计算从XML语言到机器的二进制01定费时间,而xlsb格式就直接在硬盘上储存010101。两种格式功能上对Excel来说完全没有任何区别,只是形式上的不同而已,相当于替Excel省了一步。
对于同样的工作簿,xlsx格式是用一组xml存储成zip包,目的是保证文件的开放性,其他软件通过一套标准而不用excel的程序就能读取xlsx文件,而xlsb格式则把数据直接写成二进制格式,免去了在读写时对xml的parse过程,但是牺牲了文件的开放性,
所以xlsb格式针对大数据有显著优势:
- 运行速度快
- 储存空间小
话说回来,为什么Excel默认保存是xlsx,而不是xlsb呢?主要的原因是: Excel要协作。微软打造的是一个平台,一个全生态,Excel出来的结果不是Office自己用,SAP也会用,Oracle也会用,IOS平台会有,Android平台也会有,一个包容的格式才是好格式,兼容并包是个伟大梦想。
有人做了一个简单的测试:文件内容是10000行X1000列的单元格,每个单元格都是一个=+1的公式。对这个文件而言,xlsb文件的打开速度是xlsx文件的四倍,保存速度快一倍,文件小三分之一
减少跨文件的引用
合理设计数据的布局,是计算效率得到保障的前提。如果有其他文件引用尽量放在同一个工作簿里,减少工作簿之外的文件引用,比如可以放入其他工作表。这样做也可以避免文件删除引起的各种错乱,也方便后面的修改。(当然,如果有一张表的运算非常慢,那可能更适合独立出去,这是特殊情况)
由于Excel引用访问本工作表、不同工作簿或工作表数据的速度是有区别的,通常计算指向其他工作表的引用比计算工作表内的引用速度要慢。当数据计算量较大时,就必须考虑数据的整体布局:数据是分工作簿保存、分工作表保存,还是保存在同一工作表。
基于整体性原则,如果是清单型数据表格,可能的话,尽量将数据整合同一工作表,至少尽量在同一工作簿。如果不能整合在同一工作簿,宁愿使用少量的大型工作簿,也不要使用数量较多的小型工作簿。尽可能地避免工作簿间的链接,对外部工作簿进行链接,既影响表格的打开速度,并且当工作簿移动或删除时,还容易出现断链,不易于查找和修复。
不可避免引用其他工作簿时的提速技巧:
对关闭的工作簿尽量使用简单的直接单元格引用。这样做可以避免在重新计算任何工作簿时重新计算所有链接的工作簿。
如果不能避免使用链接的工作簿,最好将它们全部打开而不是关闭,并且表格打开顺序也有讲究,要首先打开要链接到的工作簿,然后再打开包含链接的工作簿。一般来说,从打开的工作簿比从关闭的工作簿中读取链接的速度要快。
原始数据要规范
如果原始数据不规范,则还要使用函数公式清洗,徒增中间环节,自然影响计算速度。有些系统导出的数据可能并不规范,比如数字是文本格式、数字后有空格、不可见字符,这些数据就没法直接参与运算,如果不手工整理成规范数据,还得用函数公式进行规避,这就大大影响计算速度。
如果数据来源不规范,要么沟通系统开发小哥进行修改,要么,磨刀不误砍柴工,第一步先规范数据,清洗完后保存为正确的值。
另外再次重申,清洗后的数据,最好创建为超级表,插入->表格,快捷键【Ctrl+T】,对提高运算速度非常有效,特别是大规模的数据。当然,超级表也会导致一些公式的引用发生变化,要学习理解这种变化,人不可能一辈子不接受这些新事物。
关闭公式自动计算
在公式选项卡的右侧,将含有大量数据及公式的工作簿调成手动计算,只要思路清晰,最后一步计算,避免写一个公式计算一次,时间也节约很多。
在手动计算模式下,可以通过按 【F9】触发智能重新计算。使用【Shift+F9】 仅重新计算所选工作表,按【Ctrl+Alt+F9】强制对所有公式执行完整计算,也可以通过按【Ctrl+Shift+ Alt+F9】 强制彻底重新构建依赖项和执行完整计算。
换个说法: F9计算所有打开的工作簿中的所有工作表。 按 Shift+F9 可计算活动工作表。 按 Ctrl+Alt+F9 可计算所有打开的工作簿中的所有工作表,不管是否已更改。 按Ctrl+Alt+Shift+F9,则会重新检查相关公式,然后计算所有打开的工作簿中的所有单元格,其中包括未标记为需要计算的单元格。
优化公式
公式优化技巧1 在大表上添加多个 SUMIFS 表达式的计算成本可能很高,因为它会多次遍历表。如果 SUMIFS 表达式共享相似的结构,则可以以 SUM+SUMIFS 的方式重写公式。它更有效,因为它只遍历表一次。 优化前:=SUMIFS(N1:N9,L1:L9,C1,M1:M9,"H1")+SUMIFS(N1:N9,L1:L9,C1,M1:M9,"H2") 优化后:=SUM(SUMIFS(N1:N9,L1:L9,C1,M1:M9,{"H1","H2"}))
公式优化技巧2 VLOOKUP 公式对于工作表的结构变化可能很脆弱。当用户在表中插入一列时,VLOOKUP 中引用列号的第三个参数不会自动改变,而且,VLOOKUP的速度太慢了。建议用INDEX+MATCH 公式实现匹配查找,不管工作表的结构如何变化,将始终引用初始列,而且计算速度也更快。 优化前:= VLOOKUP ( A1 , C2 : G9 , 2 , 0 ) 优化后:= INDEX (D2 :D9 ,MATCH (A1 ,C2 :G9 ,0 ))
关于公式优化,更多的是一点一滴的积累,可以去逛论坛,可以看微软Excel全球大赛的作品讲解,都会让你有很大的提高。另外就是,谨慎使用数组公式。数组公式确实非常绚丽,很有高人风范,但是它也非常吃CPU,没有什么问题是一个“好的数据结构”+“简单公式”解决不了的,如果有,一定是甲方想不通。
善用辅助列
某些问题,使用辅助列会大大提高计算效率。尽量不要用过于复杂的公式,宁可多加一列作为中转数据处理列。过于复杂的公式,一则容易出错,二则不方便其他人观阅,三则运算起来慢。
常见的有2种情况:
1、例如多条件引用,如果使用辅助列将条件合并,就可以避免使用数组公式,否则,数据量一大,没有辅助列而去用数组合并条件,会成倍的增加计算量,想不卡都难。
2、例如多次使用的结果,建议用辅助列完成。假设说要计算均重,而且后续还有很多公式要用到这个均重,那么建议均重成为一个辅助列,说白了就是,公式越简单越好。
减少易失函数的使用
什么是易失函数?你有没有发现这样一个情况,有时候只是打开表格,什么都没做,直接关闭就会提示是否保存。如果你没遇到过,可以新建一个工作簿,任意单元格里输入公式:=now(),保存后关闭,然后再打开这个文件,直接关闭就会有提示。
now这个函数就是一个易失函数,这种函数的特点就是,每次打开表格都会计算,任何一个操作也会计算。RAND、NOW、TODAY、OFFSET、CELL、INDIRECT和 INFO,都是这样特性的函数。
当然,并不是说这样的函数用了就一定卡,只是这样的函数大量存在可能就会卡。多大的量才叫大,根据你的电脑配置和你的自己感觉来确定吧。
常见案例:使用offset和counta做动态区域,对于数据量少的文件,这样的做法体会不到卡的感觉,如果上万行数据,再去用动态区域,反正我是不愿尝试的。 状态栏经常会看到多少个cpu在计算,计算完成的进度这样的提示,一点鼠标动不动就白屏,无响应等等状况齐至。
对于数量量大的文件,还要用到动态区域,那么强烈推荐使用Excel的超级表格功能,快捷键【Ctrl+T】。
使用第三方工具检测和优化Excel的计算瓶颈 可以用一些工具自动检测你的文件是因为哪里慢,还可以把慢的公式自动优化变成快的。可以试试10 Studio里的"bottleneck detector"和"spreadsheet optimizer":https://www.10studio.tech/docs/introduction/
公式范围尽量准确
对于某些函数,例如:Vlookup、Sumproduct等等,在使用时尽量避免整列引用范围,因为这些函数会对范围内的每一个值都进行计算,并不会考虑范围内是否有数据,所以精确使用范围会提高速度。
当然,vlookup的模糊匹配方式不会卡,因为精确匹配使用的是遍历法查找,模糊匹配是二分法查找,原理不同,具体是什么原理,可以参阅:Excel中的精确匹配和大致匹配究竟是什么意思?
对于另一些函数,例如,countif、sumif、lookup等等,使用整列则对速度没有明显影响,这是由函数的计算方式决定的。
当然,如果你分不清哪些函数可以整列使用范围,哪些不能整列使用范围,也没关系,感觉到卡的时候去修改范围就好了,只是在修改范围的时候,要修改完整,也就是对于的范围同时修改,否则会出错,比如数据有5000行,你为了预留一些空间,可以将范围指定到6000,,哪怕指定到100000,也比整列要快很多。说白了就是请将要扫描的单元格区域限制在最小范围内,最简单的办法就是使用超级表功能,而不是引用大量行或列。
Excel中的“断舍离”大法:
断:数据量大的表格,应将已经计算出结果且不会再更新的单元格的公式计算结果采用选择性粘贴方式转化为数值,以减少计算量;
舍:尽量不要大范围使用计算量大的功能或公式。比如:尽管条件格式和数据有效性的功能非常强大,数组公式运算功能也非常强大,但是,大量使用它们会明显降低计算速度,除非你愿意忍受蜗牛般的运算速度,否则,不要大范围使用数据有效性、条件格式和数组公式;
离:如果某张工作表需要进行大量运算,且其他工作表对它的引用较少,可考虑将其移出本工作簿。以免每次重新计算时,影响工作簿的整体计算速度。
非必要的情况下不使用会触发重新计算的操作
以下操作会触发重新计算:
- 在自动模式下单:双击行或列的分隔符。
- 在工作表中插入或删除行、列或单元格。
- 添加、更改或删除已定义名称。
- 在自动模式下重命名工作表或更改工作表位置。
- 在表格中使用筛选、隐藏或取消隐藏行。
- 在自动模式下打开工作簿。如果工作簿上次由不同版本的 Excel 计算,则打开工作簿通常导致完整计算。
- 选中了“保存前自动重算”选项的情况下在手动模式下保存工作簿。
谨慎使用照相机(链接图片)功能
虽然我很喜欢用这个功能,但确实,它比较能拖累你电脑速度,如果数据量非常大,本身就很卡的情况下,非必要,别用这个功能,那我非得用动态截图功能怎么办?这么高端的功能还要用在大数据表格下,可以研究下VBA,这个功能相对好写。
选择性粘贴为公式替代双击下拉公式
选择性粘贴为公式比双击鼠标往下拉公式快很多,这样操作熟练后很方便,再也不需要鼠标往下拖。其次可以避免遇到空格,拖公式停下来的情况。
冗杂的格式导致运算慢
有些时候,表格卡可能是由于有大量误操作产生的文本框,可以用定位对象【Ctrl+G】来删除;或者是无用的格式,例如整行整列大面积的填充背景、复杂的条件格式等等,都会导致Excel卡的欲死欲活,需要针对具体问题去找到原因。
多线程运算
关于Excel中多线程的原理:https://docs.microsoft.com/zh-cn/office/client-developer/excel/multithreaded-recalculation-in-excel,强烈推荐打开设置-高级-公式中的多线程运算,当然,软件默认就是打开的。
但要注意,excel中凡是鼠标操作的事件,大多是只能单线程运算,比如筛选,透视,查找等,CPU有100核也没用。而公式及数组多是多线程。如果平时只做这些单线程操作,建议用WPS,WPS在多线程处理这一块很强,运行速度比excel优化了很多,WPS号称全中国最复杂最强悍的C++项目绝非是浪得虚名。
数据透视表和Power query真的非常非常好用
Excel的神技能,给再多的夸赞也不为过,Powerquery跑200万行的数据还是相对轻松的。我以前讲过半套的透视表,不听的话我也没有录屏了,可以看王佩丰老师的透视表教学,印象中有十几节课,两晚上能看完,讲的很到位,建议买正版课程。PQ的话,建议B站找孙兴华老师,讲的很透彻,从基础到M函数,一应俱全。不过M函数很让人头大,我也不怎么会,建议别学M函数,学完PQ基础后,直接转SQL。
使用第三方插件和自定义函数
Excel插件学过很多了,很多功能的实现算法都是千锤百炼的结果,说是人类智慧的结晶也不为过,可以尝试用插件功能代替部分函数运算,另外就是自定义函数,很多都比Excel自带的函数具有更高的运算效率和更多的功能,其中的佼佼者如 Excel催化剂。
使用VBA
如果是需要反复使用的表格,能用VBA实现的,则尽量避开在表格内使用公式。例如,你做了一个界面,显示某个表格的第N列的数据,N由用户决定。有的人在输出区域直接写上公式。一般是做个按钮,点完以后通过VBA把用户要的结果抄过来。这样不仅块,而且可控,不会出现公式被人不小心删了之类的鬼故事。 若长期坚持用表格内公式而避开VBA容易走上邪路,Excel再怎么优化,如果写表格内公式动不动就要5、6行,各种INDEX MATCH 叠在一起,那只会让别人感觉在看天书,而且自己写起来一时爽,改起来就是火葬场。
VBA代码反复读取数据问题
有些入门级的VBA教材害人不浅。最常见的案例是,要处理一个表格,比如把每个行加起来,写VBA代码时,算完一行输出一行,再读取下一行的数据,一定要记住,表格与VBA之间的沟通非常非常非慢,VBA内自己的数据读取调整非常非常快,因此若干要处理一个表格,一定要先把整个表格读进去,在里面处理完了一次性输出。
VBA实现多线程问题
所有的VBA教程都告诉你说,VBA不能支持多线程,想加速运算,需要用到数组和字典,这句话本身没错,但只要思想不滑坡,办法总比困难多,有几个方法也可以为VBA实现多线程:
1 利用VBScript加Application
将含有宏的工作簿另存n份,生成n个VBScript脚本文件,每个脚本用Excel.Application对象打开一个工作簿,运行每个工作簿里的VBA爬虫,将爬到的结果统一写回主Excel里。这种方式有两个好处:一是用字符串的VBScript代码比较简洁,二是每个线程都可以利用Webbrowser控件方便地登录。缺点就是打开一批Excel导致系统负担较重。
2 只用VBScript实现多线程
比起上一种VBScript加Application的方法,只用VBScript拼字符串写起来更麻烦,但程序执行起来非常轻量级,如果不怕代码麻烦,那么可以考虑用VBScript。示例可以在这里找到,代码相当乱而且长:Multi-threaded VBA
3 使用ActiveX EXE实现多线程 这个有前人写过,优点是资源消耗适中,缺点是需要有Visual Basic环境,实现起来也更复杂。参见:VBA异步多线程网抓教程-excelhome
我个人(作者wolfccb)推荐VBScript加Application的多线程方案,通用性更强,而且现在的电脑已经不太在乎多占些内存了。比起所谓使用XMLhttp批量异步发送的方法,VBS+Application的方案创建8个线程可以提速5倍左右,效率很高。测试电脑是4核心8线程的i7台式机,8G内存。爬虫网抓时,每个WPS ET线程大概占用不到100M内存,机器完全可以承受。
考虑从Excel转型
对于SQL语言需要一分钟的工作量,使用VB可能是几个小时的工作量,使用工作表函数可能是几天的工作量,使用纯手工录入可能是你半辈子的工作量……
假舟楫者,非能水也,而绝江河。君子生非异也,善假于物也。 常规的路径是 Excel函数→Excel透视表→Excel插件→Excel PowerQuery→Excel VBA→ Office Access→MySQL→报表/BI平台(如帆软),至于大家最爱争论的 Excel、VBA、SQL、到底哪家强,我建议是,搁置争议,共同开发。
最后提一点,所谓的数据分析工作,并不是会个Excel或者SQL就完事的,概率、统计、时序、随机过程、高等代数、数学分析,这些都是必要的基础,如果有必要,还要学习 实变、复变、泛函、偏微分等(后面这些我也不会,所以我工资低……)
其他
Excel和PS一样,零零散散的小技巧,加起来也有几万个,结合以前网络资源的整理积累,暂攒出这么一份加速运算的分享报告,不够全面和严谨,仅供参考,未免被打,最后还是要引用当初写PS教程时的两段话:
很多问题是深入且混乱的,多数时候是仁者见仁智者见智。希望大家能明白我为方便理解和保持条理做出的妥协。要知道,生活中就是有很多概念,从高阶向低阶看去是不够严谨甚至有些错误的。
很多概念太过复杂,单独拉出来可能就是一个研究方向。我明知水深,却也偏偏趟了这浑水,自知水平不够,所以也坦言说,我能提供的只有一块敲门砖,欢迎大家往更深层次探索,即便回头看我是错的。