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-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,没有问题,但是我还没有测试过一种先单仓做平均,然后再多仓做平均的数据。这种数据肯定会有,但是今年的前几个月未必一定发生过。

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

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