PQ-M及函数:将Excel的列标转成数字
小勤:在《单个格式表转换》里提到可以用配置映射表的方式来实现表格数据的提取,比如你以前用VBA程序导数据的那个:
但要在PQ里根据源表内容的位置提取数据的话,得首先知道Excel里表示的位置是那一行那一列啊,也就是说Excel里的列标是“A、B、C……AA、AB……XFD“这样子的,怎么能转成”1……16384“样子的数字呢?
大海:那你的配置表可以设计成直接让用户填哪一行哪一列的。呵呵。
小勤:这倒是可以,不过最好就是能直接让用户按照习惯的单元格表示方式填,然后咱们在PQ里自动转换就更好了。
大海:嗯。的确是这样。那咱们先观察一下Excel的列标有什么规律:首先是1-26个单字母,然后是26个单字母用完后用按顺序用2个字母,然后再用3个字母……
小勤:嗯。规律是比较明显,但怎么能转成数字呢?
大海:其实啊,这是一个26进制……
【已懂进制转换的朋友可略过以下内容】
小勤:26进制……什么鬼?
大海:10进制你懂吧?就是从0到9的10个数字组成,逢10进1……
小勤:这个我懂,但26进制……
大海:10进制因为太习惯了跟日常数量的关系,实际上你抽象一下,0到9也只是一个符号而已,现在的A到Z也是符号,跟0到9是一样一样的,你10个符号就逢10进1,我26个字符就逢26进1。
小勤:那接下来呢?怎么变成数字?
大海:接下来我们看看逢10进1是怎么算数的,然后照搬到26进制里面去。首先前面的0到9就是字符(数字)本身,接下来是10、11……,实际上呢就是:
10 = 1*10+0
11 = 1*10+1
12 = 1*10+2
……
123 = 12*10+3
= (1*10+2)*10+3
小勤:10进制这个还好理解。
大海:那么咱们来看26进制的,如果A代表1,B代表2……Z代表26,然后咱们来试一下:
AA = A*26+A = 1*26+1 =27
AB = A*26+B = 1*26+2 = 28
……
AAA = AA*26+A
=(A*26+A)*26+A
=(1*26+1)*26+1 = 703
……
XFD =(X*26+F)*26+D
小勤:这就像是从第一个字符开始,乘以进制数,再加上第二个字符,然后再乘以进制数,然后再加上第三个字符……
大海:对的,这就是进制转换的基本方法。搞清楚这个转换方法后,咱们就可以嗨森地转换了。
【如果看完以上进制转换还不懂的,有兴趣的可以在网上搜一些关于二进制、八进制转换的内容来学习,应该会比我写得好。如果没兴趣的,也可以先大概了解,学会后面的代码怎么用即可,毕竟实际工作中需要用到的时候不太多。】
小勤:那首先得将列标分成A-Z的字符内容,然后将A-Z转为1-26个数字,再通过计算得到编号?
大海:对,基本就是这个过程,咱们一步步来,通过操作自己掌握每一步需要用到的函数和方法。
Step-01:数据获取到PQ里后,先将列标里的字符分开,用Text.ToList函数转成List:
=Text.ToList([列标])
Step-02:通过List.Transform函数,将列标所包含的字母的List转为对应的数字List(其中每个字母可通过函数Character.ToNumber转换为对应的编码值,及A-Z对应65-90,用该编码值减去64即可得到A-Z和1-26的对应关系)
= List.Transform(
[拆分列标字符],
each Character.ToNumber(_ ) - 64
)
Step-03:用List.Accumulate函数实现累积(迭代)计算
=List.Accumulate(
[数字转换],
0,
(x,y) => x*26+y
)
结果就出来了,你检查一下对不对?
小勤:结果是对的,不过List.Transform和List.Accumulate两个函数感觉挺难理解的。
大海:嗯。这两个函数的确是有点儿难的,不过,不要急,后续我会继续专门就这2个函数给你举例子,让你学好它们。
小勤:好的,那我先试试将你分步的公式合成一个并且看看能不能理解。
大海:嗯。合成一步有利于后续转成自定义函数。先试试,有问题咱们再解决问题。