在简书上看到这么一个例子:

列1
20G优惠58元超值套餐
128元50G高速上网套餐
话费9元免费送

要求是提取出金额(也就是“元”前面紧挨着的数字)。
原贴见:《如何从中文和数字混合的文本中,提取部分数字?》
作者借助辅助列,用Excel解决了这个问题。但她这个例子有一个小缺陷——就是金额数字最大只能在三位整数以内。

我好奇的是,用PowerQuery来寻找这各问题的通用解决办法——也就是不管金额是不是整数,也不管有多少位数字,甚至金额是小数,都能正常提取出来。

分析

任何一种批量提取,都需要寻找一个共同的规律,在这个例子中,规律就是【元】前面紧挨着它的数字。如果不满足这个条件,就无法提取。
当然,如果在整个条件上增加其他条件,会更便于提取,比如在所有金额数字前加货币符号,就会极大地简化提取过程。

在这个例子中,难点在于,除了金额数字,还有其他干扰数字要处理;除了中文,还有英文(字母【G】)。

第一步,我们要把包含金额的部分单独提取出来,这就是用【元】来分列。这样把包含金额的部分和其他部分区别开来。这样我们得到的是以金额数字结尾的字符串。
第二步,我们要对包含金额的字符串进行处理(剔除其中的中文和英文)。这里又要分两步:先去掉中文,然后再剔除英文。去掉中文可以直接用Text.Remove()函数,但是剔除英文不能这么干(因为有干扰数字),我们要用英文所在的位置来分列——在最后一个英文字母之后的数字才是金额。

代码

最后形成的PowerQuery代码如下:

  1. let
  2. = Excel.CurrentWorkbook(){[Name="表1"]}[Content],
  3. 更改的类型 = Table.TransformColumnTypes(源,{{"列1", type text}}),
  4. 已添加自定义 = Table.AddColumn(更改的类型, "自定义", each Text.PositionOf([列1],"元")),
  5. 已添加自定义1 = Table.AddColumn(已添加自定义, "自定义.1", each Text.Start([列1],[自定义])),
  6. 已添加自定义2 = Table.AddColumn(已添加自定义1, "自定义.2", each Text.Remove([自定义.1],{"一".."龥"})),
  7. 已添加自定义3 = Table.AddColumn(已添加自定义2, "自定义.3", each Text.PositionOfAny([自定义.2],{"A".."z"},Occurrence.Last)),
  8. 更改的类型1 = Table.TransformColumnTypes(已添加自定义3,{{"自定义.3", Int64.Type}}),
  9. 已添加自定义4 = Table.AddColumn(更改的类型1, "结果", each if [自定义.3] > 0 then Text.End([自定义.2],Text.Length([自定义.2])-[自定义.3]-1) else [自定义.2]),
  10. 删除的其他列 = Table.SelectColumns(已添加自定义4,{"列1", "结果"})
  11. in
  12. 删除的其他列

第4行就是上面的第一步,第5,6,7三行就是上面的第二步,其余步骤都是辅助的。
最后的结果如下:
image.png
提供一个附件供参考:链接: https://pan.baidu.com/s/19L0I9ebe4rnI5QwzCC-NNg 提取码: 5775