在Excel Power Query中动态插入新列并水平排序列对
我被一个要求难住了,似乎无法通过它(我曾试图搜索互联网,但鉴于我在Power Query方面的有限经验,我自己无法修复它)。我可以使用VBA来完成这项工作,但是需要处理的记录数量少于50万条 下面是手头的简化任务。有两列-“子字符串”和“主字符串”,如下所示[输入]:在Excel Power Query中动态插入新列并水平排序列对,excel,powerquery,Excel,Powerquery,我被一个要求难住了,似乎无法通过它(我曾试图搜索互联网,但鉴于我在Power Query方面的有限经验,我自己无法修复它)。我可以使用VBA来完成这项工作,但是需要处理的记录数量少于50万条 下面是手头的简化任务。有两列-“子字符串”和“主字符串”,如下所示[输入]: Substring Main String AB|CDE ABCDEF ABC|DE|GH ABCDEFGHI A|BC|X|YZ ABCDYZ Substring Main String MSS1
Substring Main String
AB|CDE ABCDEF
ABC|DE|GH ABCDEFGHI
A|BC|X|YZ ABCDYZ
Substring Main String MSS1 ML1 MSS2 ML2 MSS3 ML3 MSS4 ML4
AB|CDE ABCDEF CDE 3 AB 2
ABC|DE|GH ABCDEFGHI ABC 3 DE 2 GH 2
A|BC|X|YZ ABCDYZ BC 2 YZ 2 A 1 X 0
Substring Main String MSS1 MSS2 MSS3 MSS4
AB|CDE ABCDEF AB CDE
ABC|DE|GH ABCDEFGHI ABC DE GH
A|BC|X|YZ ABCDYZ A BC X YZ
子字符串列具有由分隔符(|)分隔的小子字符串。这些迷你子字符串可能在主字符串中找到,也可能在主字符串中找不到。末尾的输出应如下所示[预期输出]:
Substring Main String
AB|CDE ABCDEF
ABC|DE|GH ABCDEFGHI
A|BC|X|YZ ABCDYZ
Substring Main String MSS1 ML1 MSS2 ML2 MSS3 ML3 MSS4 ML4
AB|CDE ABCDEF CDE 3 AB 2
ABC|DE|GH ABCDEFGHI ABC 3 DE 2 GH 2
A|BC|X|YZ ABCDYZ BC 2 YZ 2 A 1 X 0
Substring Main String MSS1 MSS2 MSS3 MSS4
AB|CDE ABCDEF AB CDE
ABC|DE|GH ABCDEFGHI ABC DE GH
A|BC|X|YZ ABCDYZ A BC X YZ
(注:列标题中的MSS和ML分别代表迷你子字符串和匹配长度)
迷你子字符串的数量可能不同,因此具有最大迷你子字符串数量的行将定义MSS和ML列的数量。在本例中,第三行有四个,因此每个行有四个MSS和ML列
不仅如此,这些迷你子字符串的顺序必须确保匹配长度最高的子字符串应该放在最左边的MSS和ML列对上。然后,匹配长度最少的应该放在最右边的MSS和ML列对上。而这两者之间的一切都应该按照这个顺序进行
我一直到当前输出看起来像这样的阶段
Substring Main String
AB|CDE ABCDEF
ABC|DE|GH ABCDEFGHI
A|BC|X|YZ ABCDYZ
Substring Main String MSS1 ML1 MSS2 ML2 MSS3 ML3 MSS4 ML4
AB|CDE ABCDEF CDE 3 AB 2
ABC|DE|GH ABCDEFGHI ABC 3 DE 2 GH 2
A|BC|X|YZ ABCDYZ BC 2 YZ 2 A 1 X 0
Substring Main String MSS1 MSS2 MSS3 MSS4
AB|CDE ABCDEF AB CDE
ABC|DE|GH ABCDEFGHI ABC DE GH
A|BC|X|YZ ABCDYZ A BC X YZ
在各个MSS列之后动态插入ML列是我无法克服的挑战。我确信,根据匹配长度的等级(即在主字符串中找到匹配项的那些迷你子字符串的长度)对它们进行水平排序也是一个挑战。下面是我可以提出的电源查询,它生成了[临时输出]
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Sub String", type text}, {"Main String", type text}}),
#"Duplicated Column" = Table.DuplicateColumn(#"Changed Type", "Sub String", "For Split"),
#"Added Custom" = Table.AddColumn(#"Duplicated Column", "Split Count", each List.Count(Text.Split([Sub String],"|"))),
#"Reordered Columns" = Table.ReorderColumns(#"Added Custom",{"Split Count", "Sub String", "Main String", "For Split"}),
#"Max No Of Splittable Columns" = List.Max(#"Reordered Columns"[Split Count]),
#"List Of MSS Columns" = List.Transform({1..#"Max No Of Splittable Columns"}, each "MSS"&Text.From(_)),
#"Split Columns By Delimiter" = Table.SplitColumn(#"Reordered Columns","For Split",Splitter.SplitTextByDelimiter("|"), #"List Of MSS Columns"),
#"Removed Columns" = Table.RemoveColumns(#"Split Columns By Delimiter",{"Split Count"})
in
#"Removed Columns"
你能带我离开这里吗?你可以很容易地告诉我我是新的权力查询,所以我非常感谢任何帮助,我可以得到。谢谢大家! 此代码应该可以工作:
let
Source = Excel.CurrentWorkbook(){[Name="Table"]}[Content],
temp = Table.AddColumn(Source, "temp", each
[a = List.Select(Text.Split([Substring], "|"), (sub)=>Text.Contains([Main String], sub)),
b = List.Transform(a, each Text.From(Text.Length(_))),
c = Table.AddColumn(Table.AddIndexColumn(Table.FromList(a), "i", 1, 1), "key", each "MSS" & Text.From([i])),
d = Table.AddColumn(Table.AddIndexColumn(Table.FromList(b), "i", 1, 1), "key", each "ML" & Text.From([i])),
e = Table.Sort(Table.Combine({c,d}),{"i"}),
f = Table.Pivot(e[[key],[Column1]], List.Distinct(e[key]), "key", "Column1"),
count = List.Count(a)][[f],[count]]),
expand = Table.ExpandRecordColumn(temp, "temp", {"count", "f"}),
final = Table.ExpandTableColumn(expand, "f", List.Buffer(Table.ColumnNames(Table.Sort(expand,{"count", 1}){0}[f])))
in
final
按长度递减顺序:
let
Source = Excel.CurrentWorkbook(){[Name="Table"]}[Content],
temp = Table.AddColumn(Source, "temp", each
[a = List.Select(Text.Split([Substring], "|"), (sub)=>Text.Contains([Main String], sub)),
b = Table.TransformColumnTypes(Table.Sort(Table.AddColumn(Table.FromList(a), "len", each Text.Length([Column1])), {{"len", 1},{"Column1",0}}), {"len", type text}),
c = Table.AddColumn(Table.AddIndexColumn(Table.FromList(b[Column1]), "i", 1, 1), "key", each "MSS" & Text.From([i])),
d = Table.AddColumn(Table.AddIndexColumn(Table.FromList(b[len]), "i", 1, 1), "key", each "ML" & Text.From([i])),
e = Table.Sort(Table.Combine({c,d}),{"i"}),
f = Table.Pivot(e[[key],[Column1]], List.Distinct(e[key]), "key", "Column1"),
count = List.Count(a)][[f],[count]]),
expand = Table.ExpandRecordColumn(temp, "temp", {"count", "f"}),
final = Table.ExpandTableColumn(expand, "f", List.Buffer(Table.ColumnNames(Table.Sort(expand,{"count", 1}){0}[f])))
in
final
Aleksei-你是个天才!这太棒了!我想我快到了。再加上几件事,我就完蛋了。第一:需要保留数据集的原始顺序。第二:需要在主字符串列之后添加一个额外的列,该列指示迷你子字符串匹配的数量。例如,从您文章中的图像,此新列应分别包含值3、2和3。如果我最后请你帮个忙会不会太过分?你不知道这个解决方案已经给我带来了多大的安慰-说真的,非常感谢!非常好,再次感谢你,阿列克谢!嗨,Aleksei,很抱歉再次打扰你!是否有一种方法可以按匹配长度的降序从左到右排列每行的MSS和ML对?请检查预期输出的第一行。虽然AB首先出现在子字符串中,但CDE被放在MSS1下,因为CDE的长度大于AB。这可以做到吗?嗨,Aleksei-我知道我说过一次,但你是PQ天才!你从哪里获得专业知识的?我很乐意浏览你使用过的所有资源。再次感谢你!再次感谢你,我很感激:)但是有很多人,谁更值得这个级别。其中之一是伊姆克·费尔德曼。你可以在她的博客中找到很多有用的帖子,包括以下学习资源: