2025-11
19

随机应变,见招拆招

By xrspook @ 8:37:52 归类于: 烂日记

业务系统由从一期变成二期,摆在面前是两个格式化操作。当我做完第1个以后,我心里就很有底了,我知道第2个大概应该怎么做,也想清楚了输出的那些数据到底要放在哪里。一期的时候,我的原始数据从同事的Excel查询文件里获取,现在我需要做的就是多一步。首先得把数据从系统里导出,然后再执行我的VBA。

数据从系统导出,供VBA使用这里其实也是有个窍门的,一开始我也没想好,但是用了几天以后,我大概明白了。首先我得保证VBA跟源文件在同一个文件夹,这是我在脚本里写死的。其次,VBA文件只能是那个名字,只能是那个后缀,有一点不合适程序就会判定找不到那个文件,然后就会在那个文件夹里面建一个9KB大小的文件,名字是我需求的那个,实际上那个东西是打不开的,所以对新新手来说有迷惑性,但是当我一次又一次的遇到这个以后,我就习以为常了,看到那个9KB的东西我知道肯定因为我导出来的文件有些不对。

以前的浪潮系统我已经默认了只能用360极速打开,因为一期的时候他们只支持IE,而我用的浏览器是Firefox。不知道二期到底支持什么浏览器,反正我基本已经把360极速作为业务系统和OA系统的默认打开方式,其它东西基本不会通过那个打开。

因为导出的文件都是同样的名字,所以如果在某个文件夹里面不断保存,浏览器会很聪明地给第2个文件加个1,第3个文件加个2。我本想把那个文件覆盖掉,但360就是不让。因为我的电脑是默认显示文件后缀的,当我把那些有括号的1和2删除掉的时候,非常有可能就会删漏个空格,于是这就会导致VBA文件要读取源数据,实际上却找不到,接着就生成了那个9KB的玩意。怎么避免这个问题呢?这需要两个文件目录,我把浏览器下载的那个文件放在目录A。VBA文件放在目录B,目录B实际上也有一个以前的导出文件。把文件导出到目录A,然后再把目录A这个文件剪切到目录B。这种情况之下,windows允许我替换掉文件。那么我就能保证VBA能够找到适合的源,因为目录A已经没有了那个导出的文件,所以下一次下载的时候浏览器也不会给我自动添加后缀。虽然多了一个剪切粘贴的操作,但是整套流程下来非常顺畅,不会出现幺蛾子。在这种情况下,我的VBA依然无法正常运行,基本就意味着浪潮可能修改了那个查询,非常有可能是修改了字段名。比如切换系统的第1天,我很早就发现单据编号是错的,但是他们不能在我们作业的时候就上补丁,只能等我们作业完了才能修改,所以那天我只能用错的文件编号先做一波,然后第2天再重新来一次。当我第2天早上重新来的时候,发现又多了一些东西,单据编号改过来了。车船号本来在一列,终于分开了,但是当有车没船号或者有船没车,再或者车船号都没有的时候,没有在数据那写横杠。我还是得自己加工。一开始那里只有品种,补丁上去以后多了个二级品种,二级品种对我来说是毫无用处。最后一个修改的地方就是之前叫仓号的那个字段现在变成了货位。正是因为仓号变成了货位,车船号字段名没了,才让我的VBA读取数据的时候失败。他们每一次升级都不会告诉你,你也不知道他改动了什么,也就只有发现不对劲的时候再去见招拆招。

适应能力不强,还真的没法玩这些东西。

2025-11
18

Excel VBA的一些心得

By xrspook @ 8:28:23 归类于: 烂日记

虽然写Excel VBA已经有好长一段时间,但实际上对一些很基础的知识我还是不扎实的。比如ThisWorkbook和ActiveWorkbook到底是怎么指定的。光说这两样我好像明白,但是当我要使用的时候就感觉老碰钉子。这个东西使用不当,就会经常被弹出错误说某个工作簿里面没有某个工作表,或者说某个工作表已经存在了,不能再新建。不同的写法意味着同样的VBA脚本发起的那个工作簿不一样,有可能要在打开有数据的那个工作簿里发起,又或者直接是在VBA脚本所在的工作簿发起,不需要打开源数据工作簿。除了这个以外,还有就是当刷新数据要放在你已经建立的工作簿的超级表里,该如何删除超级表之前的数据?有两种选项,一种是把数据全部清空,这种情况不改变超级表的格式的,之前已经使用的行会继续存在。这里用的是clear命令,另外一个则是用delete的命令,那样的话原来工作表里面的数据全部删除,只剩下最后一行。二者的差异就在于,如果是用delete命令,如果那个超级表下面还有数据的话,那些东西将会上移,如果你又在那里插入新的数据,可能就会乱成了一团。所以如果在一个工作表里,你安排了很多个超级表,而你又确认那些超级表的格式不会改变,基本上也就那几行,又或者你不确定到底有多少行,但你能确定行数肯定不会超过多少行,这样的话,当你要用VBA把刷新的数据同时写入这些超级表的时候就应该用clear命令,这样的话,刷新的数据就可以指定从哪里开始。如果在这种情况下,尤其是工作表的下面还有一个工作表,你用了delete命令那么当你清空数据再写入数据,下面那个超级表对应的那个区域肯定会乱来。

没人跟我说过这些细节,这是在我摸索的过程之中,经历过一次又一次撞板之后得出的结论,所以如果可以的话,超级表你可以在旁边建超级表,但你不要在超级表的下面建超级表,尤其是那种你根本说不准上一个超级表到底有多少数据的情况下。多建几个工作表,在不同的列起始不同的超级表,一点问题都没有,但在很多人的固有思维里面,Excel就只是一个放表的工具,上下左右都可以放,但是就数据处理的便捷和难易程度来说,超级表的放置其实是得遵循一定规则。

自从知道了ADO+SQL之后,我就经常把这两个东西作为我最大的杀器,把经常使用的Excel表当数据库。但Excel始终不是数据库,最大的差别我觉得是虽然ADO+SQL可以用类似数据库的方式理解Excel表格,但因为Excel表格可以变换不同的格式,所以当在某一列理论上都是数字的那里突然意外有一格被插入了文字,那么ADO+SQL进行转换的时候就会出毛病。刚好你又对那一字段进行了分组汇总,那程序必然进行不下去。通常情况下,人肉很难发现这个问题,因为不知道在哪一行,突然插入一个文字是个意外。一般情况下,调用ADO+SQL把工作表里面的区域读取格式化的时候没有理会超级表的范围。如果有进一步的限定,实际上是可以设定范围的,但一直以来我都没有进行这个行的主动限制。

掌握了SQL以后我觉得Excel自带的那些公式实在太复杂了,参数很多、形式变来变去,有些用乘号,有些用加号,有些用*。

2025-11
17

汇总格式化

By xrspook @ 8:22:18 归类于: 烂日记

摆在我面前的格式化操作,从大的来说是两个格式化,从小的来说其实二者又有点区别。我自己的那个格式化是把明细数据整理好。因为导出的那些信息部分是完全缺失的,所以我需要建立新的字段,数据为空,后续手动录入,另外一些则属于没有直接给我数据,但是我可以根据已有的数据经过一系列的逻辑判断得出我需要的字段。相对来说,我的格式化需求要高一点,要慢慢来,因为字段的判定只要一急就会出错、不全面。另外的一个格式化则属于要做出一个汇总的数据。一开始我并不确定到底他们需要哪些信息,开会的时候我翻桌子了,他们意识到这个问题,也翻桌子了,我大概知道他们的用途是什么,因为好像那个东西我参与过,但具体内容是什么我不清楚。我需要他们给我一个截图,或者把已有的文件发给我,我自己去看到底是什么内容。

在他们把那个版本发给我之前,实际上我已经在琢磨怎么整那个。一开始我想到的是选择某些列得出一个明细,然后根据那个明细自动生成一个透视表,透视表里面的内容肯定足够他们填写相关的信息,但关键是他们想要的不是数据表,因为数据表很难复制粘贴。平时他们需要把那些东西转化为了一段文字贴到群里,数据透视表看上去的确更直观也不会错,但关键是图片这个东西很占空间,如果你几天不保存图片就会失效,所以如果要长期保存数据,还是纯文字比较靠谱。

一开始我尝试的是数据透视表,数据透视表很简单,但关键是不同版本的Excel数据透视表出来的默认格式不一样。他们干的这种事需要数据数据透视表不显示分类汇总,同时得重复所有标签。手工操作的话,这个很简单,但是用VBA控制的时候却发现自动生成的那些脚本又长又臭。那些又长又臭的东西到底能不能简化一些呢?VBA这个玩意的确可以通过录制生成,但关键是通过录制生成的那些东西通常都速度很慢,有很多废话,有些时候可能不太精准。所以我折腾了半个晚上,到底怎么把那些自动录屏出来的宏简化一些。虽然已经很努力,但是有个数据透视表不做分类汇总的那个坎好像挺难迈过去。

后来当他们把正在使用的那套查询数据库表发给我以后,发现或许我根本不需要生成透视表,实际上一个SQL的分组合并就能实现他们想要的东西,从那个查询表的内容看来,我的那个同事也是为他们做了这个事情。所以,整个逻辑就很清晰了,首先要看他们需要的那些数据在哪几列,刚好导出的那个大表上面的数据就能满足他们的要求,只是字段名有些不一样而已。这个很简单。所以逻辑就是把数据导出,删除最后一行,因为那个是汇总没有任何效果,然后把有数据的列全部转化为数字格式。因为神经病的浪潮为了他们自己方便所有列都设置为了文本,文本分组合并求和会完全不会起效。思路很简单,首先从原数据那里选取我需要的列,然后进行一些字段的重命名以及一些数字的转化分组合并,最后输出到我想要的地方。

一开始我并没有想好到底要输出到导出那个文件还是我有查询脚本的那个文件。经过一番的纠结和尝试以后,我感觉直接在我查询的文件通过ADO的方式查询那个导出的数据表,然后在查询的那个地方直接输出最便捷。一开始我想到的是要他们把转化好的内容贴到目标的表格,然后刷新一下。后来发现既然我都用了ADO。我根本不需要他们打开导出的原始表格我就能获取数据。

思路清晰以后,接下来的就只是执行。

2025-11
9

又想起了Python

By xrspook @ 8:44:06 归类于: 烂日记

大概两年前,我买了一本叫《超简单 用Python让Excel飞起来》的书。那本书是怎么买的呢?我搜索关于Python跟Excel的书,然后就看到了它。说白了就是教你用Python去处理Excel。前面的部分是一些批处理,后面的那些是利用Excel的数据作图。批处理的部分我看得挺认真,也实际操作过。感觉基本上都是可以实现的,我在VSCode里写Python,然后引用Excel文件,最后把结果输出到Excel。的确,这样干可以批处理一些基本的问题,但关键是我是个完美主义者,所以我对输出格式有一定的要求,实际上这本书教你的东西不怎么包括具体调整格式本身。通常来说做法大概是读取文件,然后通过pandas处理,最后输出。在这里我学得比较认真的部分是批处理文件,无论是把一个工作簿的每个工作表分别另存为单独的工作簿还是把某个文件夹里面的工作簿全部都合并到一个工作簿里。这些翻来覆去的操作其中一个跑不掉的是要进行一定的循环,循环的思路搞清楚了以后一切都好说。学的时候很认真,也都全部尝试过了,但一段时间之后不用还是会全部都忘光光,最后剩下的只是知道一定可以通过批处理实现这些功能。

在电脑里面安装Python,然后通过这种方式的确是可以处理Excel文件,后来我也进一步对那些输出的文件进行了格式控制,但总的来说,还是有些不如人意的地方。就数据处理本身来说,Python没有任何问题,但关键是跟VBA这个原生的东西相比,在处理格式方面还是显得有点有心无力,又或者无法控制。一个很明显的地方就在于跟VBA相比,Python读取文件跟输出文件都得一定时间,可能数据处理本身不需要多少性能,但关键是打开文件关闭文件这都需要时间。后来机缘巧合之下,我知道了在VBA里可以通过ADO的方式用SQL解决数据的问题。ADO的方式意味着我并不需要真的打开文件,这样就节省了很多时间。以至于后来我用VBA取代了Python的功能,因为Python之所以好用是因为把Excel的数据传进去了以后,它对数据进行了一个类似数据库的标准化改造,然后用标准的语言实现某些功能。相比之下我觉得SQL更简单易懂。所以自从迷上了ADO+SQL以后,我基本上就没再用Python处理Excel了。我一直也没有进行太多高端的操作。可以肯定的是,如果我要做的话,实现同样的功能,我可以通过这两种途径分别得出方案。

回到一开始那本书,前面部分说的是一些批处理,后面部分说的是用Python作图,其实那个时候我并不明白为什么要用Python作图,因为Excel本来就可以作图,而且就控制来说Excel是可视化的,Python全部都得写上去,所以后面作图的部分我看得很潦草,直接快速掠过,只是知道能干这种事而已。

直到这一次数据分析需要做箱形图。Excel可以做箱形图,但对箱形图的控制不如人意,我想到了Python,也想到了R语言。我知道这两个东西通过某些包就可以轻松做出我想得到或者想不到的图。

R语言被我放下了太远,以至于我已经基本不知道该如何操作了,所以我选择先用Python探索一下作图。

2025-04
12

使用内部数据就会卡?

By xrspook @ 8:35:34 归类于: 烂日记

昨天说到一个很简单的SQL语句引用的数据库就只有一个字段两行记录,居然需要24秒才能得出结果。这让我觉得非常不可思议。首先可以肯定的是数据量非常少,为什么会出现这种问题呢?那只能是连接方面是不是出了什么故障,也不能说,那是失效的,因为的确还能查询得到想要查询的东西。在我测试的那个宏里面。我引用了两个文件,一个是外部文件,一个是内部文件。外部文件是含有比较多的数据,而内部文件,也就是我一开始说的那个只有两条数据。我感觉如果我的SQL再厉害一些,我对VBA再熟悉一些的话,那个内部文件可能我就不需要引用了,我直接就在VBA里创建一个数据库,然后把两条数据给写进去,用完以后就删掉,但显然现在我还没有很大的把握,一定能完美地做这件事情。把我某个文件里面的数据转化为数据库的数据我又烂熟,所以我采取了现在使用的这种方式。

ADO+SQL的这种方式,因为我们是跨表引用,所以意味着数据肯定来源于多个文件。他们有可能是同一个工作簿的不同工作表,也有可能是在不同的工作簿里。对我来说,只要是在一个工作簿里,那么起码一开始设定指向的时候就得有一个数据源。最经典的方式引用的那个数据源在使用数据的时候,在from后面不需要进行进一步的引用,其它的就得麻烦一些。我的第一个反应是,是不是引用数据的那个语句出现了变动呢?比如说现在我用的是Excel12。在数据源引用方面,我又折腾了一番,发现好像还是那样,没什么进展。会拖慢查询的那个数据源,我甚至把它放到了主数据源里,结果发现还是很慢,于是这就排除了是数据源引用语句变动导致缓慢。

所以这到底是什么原因造成的呢?因为我有很多个跨表引用的查询。有些查询是内部数据外部数据都有,有些只有外部数据,经过测试后我发现好像只有引用了内部数据的查询才会变慢。

为了证明我这个想法,星期三的晚上我编造了一些数据做测试。主要原理就是研究是不是数据源的关系导致这种变慢。一开始我的设计就是一个排列组合的方式,因为我默认的数据引用是要跨表的,所以我把数据源根据内内、内外、外外和外内这4种方式测试,实际上内内和外外是一回事,也就不需要进行两个引用了,所以我又把那两个东西拿了出来,同样进行测试。结果让人有点吃惊,凡是有内部数据参与的查询都会变慢。我测试的数据就只有一个字段几条记录,内内和内外需要12秒,外外需要0.1秒,外内需要24秒。这就能解释为什么我的那些变慢的查询起码都要24秒才能出结果。因为我永远把内部数据放在后面。究其原因是因为我设计那些查询的时候,我后来才想到要在那个查询文件里面搭一个加脚手架,把一些基础的东西加上去,在这种情况下我加得最多的是日期表。

关于这个测试的来龙去脉以及最终的结果,我在ExcelHome里面做了一个详细的帖子,在这里就不再具体阐述了。

折腾了这么一番以后,我发现这个锅还真不是我整出来的。造锅的是微软,不知道更新出了什么状况导致了。

Excel用多了,不知不觉我也居然能挑出微软的毛病。

© 2004 - 2026 我的天 | Theme by xrspook | Power by WordPress