平时我们经常用到需要根据一定的需求在数据中把符合需求的数据提取出来,那我们看下在Power Query中是如何进行操作的。
我们知道,在Power Query中数据是有多种类型的,那提取的方式也是各不一样。
以下是一张整体的有关数据提取可能涉及到的函数集。可以点击查看大图
我们今天来主要看下文本中的数据提取。
我们知道在Power Query中对于数据类型规定的比较严格,所以我们在使用函数的时候也要时刻注意着数据类型,包括函数参数的类型,函数生成的最终类型。
在Power Query菜单中也可以进行部分操作。
从头开始提取(首字符)
Text.Start(string asnullable text, count asnumber) asnullable text
此函数有2个参数,第1个参数是可为空的文本字符串,第2个参数是整数数字,最终生成的是可为空的文本格式。
这个函数类似Excel中的Left函数,从左边开始提取指定位数的字符。
例:
Text.Start("abc",1)=a
Text.Start("123",2)="12"
从尾开始提取(结尾字符)
Text.End(string asnullable text, numChars asnumber) asnullable text
此函数和Text.Start类似,相当于Excel中的Right函数,从右边开始提取指定位数的字符。
例:
Text.End("abc",1)=c
Text.End("123",2)="23"
从指定位置开始提取(范围)
Text.Range(text asnullable text, offset asnumber,optionalcount asnullable number) asnullabel text
一共有3个参数,第3参数为可选项。
这个函数类似Excel中的Mid,但是有几个地方需需要注意。
参数从0开始,而不是从1开始。
(第2参数+第3参数)<=文本字符数
例:
Text.Range("abc",0)=abc
Text.Range("abc",1)=bc
Text.Range("abc",0,1)=a
Text.Range("abc",1,2)=bc
Text.Range("abc",4)/ Text.Range("abc",1,3)=Error
Text.Middle(text asnullable text, start asnumber,optionalcount asnullable number) asnullable text
和Text.Range相比,优点是不需要考虑(第2参数+第3参数)<=文本字符数这个条件。
Text.BeforeDelimiter(text asnullable text, delimiteras text,optionalindex asany) asany
(分隔符之前的文本)提取指定文本之前的数据。
例:
Text.BeforeDelimiter("abc123abc","b")=a
Text.BeforeDelimiter("abc123abc","c",1)=abc123ab
Text.BeforeDelimiter("abc123abcabc","b",{2,1})=a
解释:从文本中,根据字符"b",从最后开始查找,并跳过2次找到的位置再提取之前的文本。{}列表里面,第一个2代表跳过的次数,第二个1代表的是从后往前数,如果是从前往后数则是0。
Text.AfterDelimiter(text asnullable text, delimiteras text,optionalindex asany) asany
(分隔符之后的文本提取)指定文本之后的数据。
Text.BetweenDelimiters(text asnullable text, startDelimiter astext, endDelimiters astext,optionalstartIndex asany,optioanlendIndex asany) asany
(分隔符之间的文本)提取指定文本之间的数据。
根据条件提取
Text.Remove(text asnullable text, removeChars asany) asnullabel text
我们注意到,在这个函数里面,第2参数是any,那就代表可以是其他类型,例如list等。我们可以通过这个特性,批量从文本中删除指定数据并提取剩余数据。
例如:
Text.Remove("abc123", "123")=abc
Text.Remove("abc123",{"a","b","c"})="123"
我们之前了解到list的生成可以通过Unicode代码,可以参考此文章(如何理解Power Query中的“#”转义字符?)。
例如我们需要删除文本中所有的数字就可以使用列表{0..9},如果删除所有的小写字母{"a".."z"}
删除全小写字母=Text.Remove("abc123",{"a".."z"})="123"
如果要全部去掉数字,则还需添加一步转换,因为{0..9}生成的是数字格式,但是我们要删除的是文本格式,所以需要用到List.Transform函数进行转换。
删除全部数字=Text.Remove("abc123", List.Transform({0..9}, Text.From))="abc"
Text.RemoveRange(text asnullable text, offset asnumber,optionalcount asnullable number) asnullable text
和Text.Remove比,虽然都是删除,但是性质完全不一样。可以参考Text.Range,只不过一个是提取,一个是删除。
另外请注意,其参数是number,不是any。
例:
Text.RemoveRange("abc123",1)="ac123"
Text.RemoveRange("abc123",0,2)="c123"
那会问,如果想要在指定位置内批量删除字符要如何处理呢?
思路都是一样的,我们先通过提取,然后再通过批量删除即可。
例:
Text.Remove(Text.Range("abc123abc",5,4),{"a".."z"})=3
再延伸下思路,我们注意到很多在提取的时候都需要用到Number的数字进行定位,那我们如何进行定位又是一个课题了。
例如涉及到定位的函数,Text.Length,Text.PositionOf等函数进行定位,甚至List.Sum,List.Count这类函数作为值也可以进行定位,具体要看实例灵活应用。
Text.Select(text as nullable text, selectChars as any) as nullable text
根据指定条件提取文本。使用方法可以参考Text.Remove,只不过一个是提取,一个是删除。