2024-08
24

office系的SQL为啥不能文本拼接?!

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

花了几乎一天的时间去研究什么把Access VBA里的自定义函数移植到Excel的VBA里面。大家都是VBA,大家都是 office家庭的,听上去好像没什么难度,但实际上前人已经碰壁阵亡,确定这是不可能的,我只是在做垂死的挣扎。经过这么多年office的发展,在数据格结构上,会不会只有那么一点改进呢?毕竟即便是在Excel里,如果我用的是VBA+ADO+SQL,实际上我是把数据以数据库形态进行SQL的加工。于是我就想,万一他们的数据格式是一样的,万一Excel已经进化了那么一点点呢。但现实告诉我,虽然都是VBA,虽然都是自定义函数,但是因为他们操作的是SQL,所以出来的效果完全不一样。

SQL的语法结构非常类似,无论你用的是什么类型的数据库,但在一些细节上,大家的处理是有区别的,我觉得Excel里面和Access里SQL最大区别在于因为我在Excel里面SQL用的是ADO的方式,所以这就意味着虽然我写的是SQL的语法,但实际上那是以字符串的名义存在的东西。在Excel VBA的数据格式里,我写的结构化语言全部都是字符串,但是在Access里,在SQL的查询界面里,那个东西不是字符串。我没有认真看某些单词有没有高亮,因为那是特殊字段又或者是保留字段。当我直接把Access VBA里的那个自定义模块挪到Excel VBA里,发现打开记录集的方式根本不一样,语法不一样。因为在Access里本来就是一个数据库,但在Excel VBA的ADO里是通过一些特殊的语句打开那个记录集的。

回到一开始,为什么我得这么折腾呢?因为一直以来我都发现,从来没有一个人能在Excel VBA+ADO+SQL的模式之下在分组聚合的时候把文本以某些字符去重连接成字符串。要实现这个功能,只能最后把结果输出,然后在VBA里通过字典的处理,再把那些合并好的东西与其它东西结合在一起形成一个新的数组,最后往单元格里面输出,而不能像其它SQL查询结果那样直接就在单元格里全部输出。先输出到字典,然后再用字典合数组合并的难易程度跟那个数据最终的查询结果复杂程度有关。在高端的数据库里,文本聚合连接有直接的函数可以做到,比如在MySQL里面直接group_concat就可以做到,在其它专业数据库里,那个函数的名字各有不同,但都能实现同一个效果,就是把字符聚合拼接。在Power Query里,他们没办法在窗口界面让你实现这个,但可以在高级编辑器里面通过text.combine的方式实现这种功能。在Power Pivot里,concatenatex也能实现这种文本的拼接。让人觉得非常无语的是,都到了Microsoft 365时代,Access这个东西依然是office大家族的一部分,但这种肯定有需求的东西居然没有一个官方函数实现,但你又可以通过在模块里用自定义函数的方式达成。Excel的VBA里不能秒生成这种东西,但在函数层面textjoin+unique+filter可以。为什么就不能在Excel VBA支持的SQL里面出现这个文本拼接的官方函数呢?如果他们真觉得没有必要的话,为什么Power Bi的软件就可以实现呢?我不知道Power Bi软件是一开始就能实现,还是后面慢慢进化出来实现的,反正我第1次看到Power Bi相关软件的时候,他们已经能实现了。

一整天的挣扎下来好像没什么进展,但我在这些问题上又仔细思考了一番。

2024-08
23

我还是比较喜欢VBA+ADO+SQL

By xrspook @ 8:39:59 归类于: 烂日记

我觉得编程会让人上瘾,尤其是当你实现了自己的目标以后,你就会有很多想法,比如之前我已经做过,而且已经实现了东西,能不能更进一步,再改进一些,让程序跑得更快一点?一开始的时候,只要能实现某个功能就可以了,无论用的是什么方法。在这个初级阶段,我是不会考虑别人到底行不行的,反正我行就可以,但是当自己包里面的工具越来越多以后。到底要选择什么工具,也会变成我一个纠结的地方,虽然有些工具已经很成熟了,肯定能实现我的效果,但是我还会想有没有更快捷的方式呢?

我已经不记得我是什么时候开始认识Power Query了,大概是在office2016的时候吧。那个时候我觉得那个东西可以做文本拼接太厉害了,而且厉害之处就像是跟数据透视表一样,当你的原数据发生了变动,刷新一下结果就出来了,但实际上那只是教程的效果,你完全按照教程这么干,的确能出结果。还记得几年前当我要算某些库存的时候,我用了一些很笨的方法。为了要实现区间日期里面的累计库存我用了一些非常耗费电脑的步骤。本来数据的量就不小,又外加要实现这样的效果,所以真的得算上很长时间才终于得到结果。那个很长时间意味着可能要等5分钟以上,在等待的过程中,我都怀疑自己的电脑是不是死机了。后来我也有算累计库存,但大概我已经不用一开始的那些方法了。我也有试过在VBA里计算累计库存。如果是在其它软件下的SQL里,计算累计数可以有很直接的方法,因为他们有现成的函数可以套用,但是在VBA里面的SQL,貌似至今为止,我尝试成功的也就只能硬着头皮做一个笛卡尔积。如果数据量比较大,那将是一个噩梦。噩梦归噩梦,数据还是能算出来的,如果我只是算一个月的库存,顶多就是几秒钟的事,通常情况下如果业务量不大,一秒就差不多了,但是如果要算一年的数据,那就要跑上几十秒。在VBA层面需要跑几十秒,而如果在PQ里我简直不敢想象得多久。

试过VBA,试过PQ,在PQ里我知道我要什么,它的透视和逆透视功能让我省掉很多麻烦,但这两个便捷功能也会默认带出一些意想不到的反效果,比如默认透视的是来源去向,万一筛选区间只有入没有出,但后续处理又默认有出入,这就会卡住。Excel 的SQL里,透视就是最后一步,所以如果中途要实现这种功能只能通过添加条件字段,手动添加字段的好处是不会有PQ透视法的那种透视不出来后面没法干。就可控程度来说,VBA更容易,能把多个操作在一步里秒杀实现,比如修改某个字段的数据和增加某个字段,我就可以把它们在一步里实现,外加同时搞个什么排序。这些步骤在PQ里面,如果不是高级玩家用嵌套的方式,也就只能一步一步慢慢来。我不知道,PQ里面嵌套一步到位跟一步一步慢慢来到底效率差了多少。估计这会有运行时间的差别,但到底差别了多少,这个我没有研究过,因为我还没到的那种可以混搭在一起,一步到位的水平。处理同样的数据,使用类似的步骤,PQ就是比VBA要慢,我也不知道到底慢在哪里,为什么会那么慢?其实数据量不大,但关键是PQ载入的时候很容易出错,但那个出错到底是什么,没人说得清,因为上一次刷新不行,下一次刷新可能又可以了。在VBA里,除了去年年末的某段时间,我经常出现这样那样的奇怪现象,其它时候基本上行就行,不行就是不行。不会出现同一个数据,同一个宏,前一次可以,后一次不行。在PQ里可能得转上半分钟以上的事情,在VBA里非常有可能0.5秒以内就解决了。以前做字幕的时候,我就知道人的反应时间通常是0.3秒,如果一个VBA脚本只需0.3秒就能结束战斗,对普通人来说,那就是眨眼的事而已。

以前我没想过要这么干,以前想着怎么方便怎么来,但是当VBA有点上瘾了以后,我逐渐的把之前用PQ处理的东西全部都用VBA的方式再整了一遍。出来的效果非常好,干净利落快如闪电。让我觉得舒服的是VBE界面是被我调整过的,调整过VBE的布局和颜色,但是在PQ里,那个小得要死的高级编辑器字体实在让我看得很不舒服,但通常某些高端的功能只能在那里敲代码,所以这就很痛苦。

不把某些事完成,心里总会一直念惦记着,把这些事情都干完了,我就可以好好睡觉。

2024-08
16

怎么就null了呢

By xrspook @ 8:54:26 归类于: 烂日记

周三的下午做了一个决定,周三的晚上可以说10点半开始,我觉得整个人都崩溃了。过了12点去睡觉的时候,我感觉整个人毫无睡意,躺在床上,翻来覆去,无论如何睡不着。所以刚刚躺下,我就又重新打开了微信,发出了一段的吐槽,但即便这样还是不解恨。接下来,我甚至都不知道自己是几点睡着的。满脑子都是工作上吐槽的东西,我感觉周三的晚上我就没怎么睡着过,但居然小米手环说我也有接近一个半小时的深睡时间。我不知道那个是怎么算出来的,但估计也睡着了一些时候,因为当我再次翻来覆去的时候,脑子里的东西好像少了一些,也变化了一些内容。我感觉周四一整天肯定会非常糟糕,但实际上却没有想象中的那么难。早上起床的时候不太糟糕,白天的时候也不太糟糕。周四要解决20级消消乐,搞到中午1点30才终于结束,午睡的时候好像也是迷迷糊糊,没怎么睡着,但起码脑子不会有那种大脑缺氧集中不了精神,做不了事的感觉。之所以这样啊,大概是因为周四早上吐槽完以后,我又进行了一番PQ的奋战,把最后的那个记账凭证部分也搞出来了。

其实前一天,我已经把另一个部分的记账凭证搞出来了。晚上洗澡又或者说睡觉的时候,我在考虑最后的这部分该怎么操作,所以其实整个思路其实都已经有了,最后就只是如何实施而已。最后的那个部分能实现我想要的效果,但是有一个我想不明白,当我添加某个条件列的时候,为什么在某个条件之下,明明我已经设定了数据,但是当我保存出去刷新的时候却没有数据?那个东西不知道为什么会默认把我设定的数据变成null,于是那里莫名其妙空了。第一次遇到的时候,我觉得是不是我手误,但是当我好几次都遇到,尤其是周四早上已经修正了一次,又遇到的时候我就觉得这大概率不是我的问题。但是为什么其它条件就不会出现这种状况,唯独在损耗这个条件判断上就会出现这种问题呢?但不是每个条件判断损耗的时候都会这样。我当然希望这只是因为我没有保存导致的,但不可能每次都是我没有保存出现这种问题,另外一个我觉得不是我问题的原因是如果条件判断最后出的结果我没有填写的话,那个地方应该是空的,当我发现刷新出来的数据少了一些东西进去看的时候,发现那里填写了null,我不可能在那里填写这种东西。Power Query在这个问题上到底有什么毛病呢?

PQ方案出来了以后我发现几乎没有需要文本合并的部分,所以这个方案完全可以用VBA替代。最大的区别我感觉是再用 PQ的时候,我在添加条件选择的时候会很方便,如果要在VBE里面写一大串的SQL代码,如果要体现回车还挺麻烦,但不会车和退格会造成一些编写和阅读上的困难。如果我是在一个数据库软件里写SQL,而不是在VBA里,以标准格式写SQL,没有这种烦恼,回车退格什么的东西都是很标准化的。但关键是要我在VBE里面写SQL,那个SQL就像变成了纯文本一样。因为在这个转化方案里需要用到大量的条件判断。想清楚那些条件判断,结果就出来了。我在PQ里面进行条件判断编写不需要用自定义模式,直接有一个条件判断的界面,在那里很容易就能实现功能。因为那个界面就像一个多条件的筛选框。以前我从来没试过这样,这一次添加条件列帮了我不少忙。

因为人已经恢复了平静,我也就不想继续吐槽了。

2024-05
10

进一步加权平均

By xrspook @ 10:06:46 归类于: 烂日记

之前说到了Power Query方案不完美,第2天我又更进了一步,真的老老实实做了两层加权平均。效果挺稳定,比之前那个还稳定,因为之前那个方案查询数据是跨表的方式获取,PQ可以跨表查询数据,但在数据转换的时候,可能会遇到一些问题,导致刷新通过不了,于是你得重新刷新,如果你的表格很多,会让你非常的烦恼。我这一次,我采用的方案是用VBA跨表抓取数据,相对于PQ的跨表来说,VBA的跨表更稳定。在不进行文本拼接的前提下,我对VBA里的SQL操作感觉是要比PQ熟练一些。 VBA抓取的数据很快,不会有卡顿的烦恼,除非VBA直接卡死了。VBA卡死的解决方案就是重新拿出之前备份好的那个重新刷。又或者是卡死了之后再弹出Excel,然后你选择把那个东西恢复,这两种通常都能解决问题。如果依然卡死,那么估计你就得重启电脑了,如果重启电脑还是不行,那就换一台电脑吧。前几个月基本上我每天又或者是每隔几天就会遇到VBA卡死,但近段时间又好像没有再遇到,我严重怀疑这跟win10的系统更新有关,尤其是框架的更新。

用VBA抓取数据,然后把那复制到要进行PQ处理的工作簿里,把需要手工填写的东西补上去,然后PQ就可以很快乐地在工作簿内弯曲折叠生成我想要的样式。如果说有什么事让我觉得我非得在PQ里而不想用VBA解决的,大概就只有文本拼接。在PQ、Python又或者真正的SQL里进行文本拼接都是很大路的货色,但是在Excel的SQL里,你就是没有一个很方便的方式实现,你只能把它输出到数组,然后再折腾半天。老领导要求的表格里,总少不了文本拼接。有可能是拼仓号的,有可能是拼品种的,有可能是拼客户的,也有可能是拼各种组合的。如果要拼这么多的东西,我首先想到的就是在PQ里做一个分组。PQ也是一个很神奇的存在,分组的时候就没有办法给我选择文本聚合,其实文本的聚合的方式就是文本拼接。所以每次你都是得随便选一个求和,然后在高级编辑器里面把求和改成文本拼接。

PQ经常让我绕来绕去绕不出去的还有if的使用。在其它编程语言下,括号逗号解决问题,但是M语言里if这些东西都没有。所以当我用常规的思路去进行我的条件设定的时候怎么都不对,最后我不得不使用自动生成的方式,接着才发现原来自己语法错误。

在PQ里使用加权平均,思路来说很简单,就是数量乘以单价求和后再除以数量之和。如果要分步操作,在分组之前要算出一个总价,分组以后在高级编辑器里面修改公式,用总价除以总数量,但实际上也有不需要分两步的方式,但是需要用到list.zip。其实我对PQ并不算太熟悉,在没有查找加权平均的方案之前,我试过用公式套叠,结果发现不行,在list.sum里面选择两个列,然后相乘实际上是不可以的。list.zip那种方式,让我想起了Python里面的元组操作。要完全搞懂PQ,学习成本非常高,他们的各种玩法套叠简直是到了那种让人眼花缭乱的程度,当然,其实Power Pivot,也就是DAX语言要玩得高深,同样很烧脑。对我这种初级玩家,主要是用来拼接文本的人来说,基本功能能顺利实现也就可以了。最终生成的数据,有一些地方肯定用了加权平均,我手动校核了一下,发现很OK,没有问题,但是我还没有测试过一种先单仓做平均,然后再多仓做平均的数据。这种数据肯定会有,但是今年的前几个月未必一定发生过。

手上的工具多了,用的时候得想想用那个最合适,又或者,联合使用也是个妙招。

2023-11
9

隐藏属性

By xrspook @ 8:30:41 归类于: 烂日记

又是一个下班之后继续干,干到直接忘记写blog。如果不是这么着迷的话,理论上我会先烧水,把麦片泡着,然后打开语记开始口述blog,接着开吃,但如果我过于着迷,泡麦片的时候我会在那里写代码,吃麦片的时候也在那里写代码,吃完麦片以后往杯子里加水,等待水凉的时候继续写代码。可能那杯水我得花好几十分钟才喝完(一边喝一边写代码),也可能等我喝完的时候已经过去了一两个小时,又或者是我根本就不记得喝了。之所以要加一杯水,因为本来吃完麦片就得喝水,如果我不马上洗杯子,东西干在那里很不好洗,如果有水泡着就会容易些。所有习惯,只要遇上着迷于写代码这种事,全部都会变成渣渣,除了显示屏上的东西,身边的一切我都完全没办法放任何的注意力,除非是内急之类。写代码这种事对我来说通常是一发不可收拾的,完全停不下来,所以我没办法预测我得花多少时间,我知道我的目标是什么,但开始的时候通常我不知道具体该怎么做,就更加不好说得耗多久。之所以会这样,因为写代码不是我的强制工作,我不靠那个赚钱,没人要求我必须得那么干,纯粹出于个人喜欢。

光是写出来还不行,当我觉得效率很低的时候我会不断地在那里挣扎,到底有没有其它方法呢?还有没有其它的途径实现这种功能?

遇到问题,光在那里想,是不会有结果的,但只要干,埋头苦干,方法就会自己涌出来。大概是几天前,我不知道在哪里见过意思差不多的话,对我来说,写代码的时候会这样。如果我用的是python,因为我的目标很简单,所以绝大多数情况下都有现成的解决方案,只是那个方案是不是高效,能不能再提高一点而已。但如果我用的VBA+ADO+SQL,情况就很不一样的,因为VBA里的SQL被严重阉割,虽然理论上没什么东西是SQL解决不了,解决不了就输出到VBA的数组继续解决。我第一个接触的代码是CSS,然后是HTML。有段时间我迷恋于花俏的网页特效,有些联合CSS+HTML能实现,但有些不得不用javascript。当年我无数次想开始学习javascript,但一直都没开始。后来,我的大学课程里有C语言,我还考了二级C语言的等级证书。上机是满分通过的,但笔试70不到,所以我那张证书上只是合格而不是优秀。如果能重来,我会做到优秀的。但实际上,优秀不优秀又有什么意义呢,招聘的时候那不过是别人一扫而过的一张纸,甚至不会在别人脑子里留下任何记忆,但为了“优秀”那两个字我就得在上面付出很多,因为考证的考试范围大于大学课程的教学范围。

从我开始接触互联网,我的各种兴趣就没有停止过,写代码这事也一直贯穿其中,CSS、HTML、C语言、php、python、R语言、DAX、M语言、VBA、SQL,其实我也尝试过java,因为那是安卓的基础,或许还有一些我漏了没列出来。或许,码农是我天生的隐藏属性。

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