Excel 每次找到电子邮件地址时动态转置

Excel dynamically transpose every time an email address is found

我在 excel 中有一列包含类似于以下内容的长列表:

alfa.zulu@test.com
9v46by8
9016767312
TX961779
1DM90F4
bravo.zulu@test.com
B935536
24086942
9486388284
UAUG350583
0P47MB2
asd65f4
813asdg
357yvjy
jxvn97
iopu634
charlie.zulu@test.com
1DM90F4
0P47MB2
delta.zulu@test.com
9016767312
asd65f4
357yvjy
iopu634
echo.zulu@test.com
9v46by8
TX961779
B935536

我需要转置列表,但是每次我有一个电子邮件地址时,我都需要跳到下一行并重新开始,例如:

alfa.zulu@test.com  9v46by8 9016767312  TX961779    1DM90F4                     
bravo.zulu@test.com B935536 24086942    9486388284  UAUG350583  0P47MB2 asd65f4 813asdg 357yvjy 
charlie.zulu@test.com   1DM90F4 0P47MB2                             
delta.zulu@test.com 9016767312  asd65f4 357yvjy iopu634                     
echo.zulu@test.com  9v46by8 TX961779    B935536 

                    

有没有不使用 vba 就可以实现的方法? 提前致谢!

这可以通过组合 INDEXAGGREGATESEARCH 函数来完成。 但有一些先决条件:

  1. SEARCH 函数将搜索带有 @ 符号的单元格 - 因此它应该只在电子邮件地址中
  2. 在列表末尾,必须在第一个空白单元格中输入 @ 符号

公式:

=IFERROR(INDEX(INDEX($A:$A,AGGREGATE(15,6,(1/ISNUMBER(SEARCH("@",$A:$A)))*ROW($A:$A),ROW())):INDEX($A:$A,AGGREGATE(15,6,(1/ISNUMBER(SEARCH("@",$A:$A)))*(ROW($A:$A)-1),ROW()+1)),COLUMN()-2),"")

如果列表很长,最好听从 Ron 的建议。

使用 Power Query:

  • 使列数据类型=文本

  • 测试条目是否为电子邮件 - 使用 @ 但可以更复杂

  • 添加索引列

  • 添加另一列,每当第 1 列中有一封电子邮件时,该列包含一个唯一编号

  • 填写唯一编号,以便每个“组”都有相同的编号

  • 在唯一编号列上对行进行分组

  • 将每一行的数据提取到分隔列表中

  • 添加一些逻辑以启用潜在列数的变化,否则高级查询将无法适应。

  • 根据分隔符将数据列表拆分为新列

  • 在此过程中,我们删除了无关的列


  • 将下面的代码粘贴到 Power Query 编辑器中
  • 更改第 2 行中的 Table 以反映工作表中的真实 table 姓名。
  • 双击 Applied Steps window 中的语句,探索每一步都做了什么
  • 如果您的数据 table 发生变化,只需刷新即可。

M码

let
    Source = Excel.CurrentWorkbook(){[Name="Table3"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", type text}}),
    #"Added Custom" = Table.AddColumn(#"Changed Type", "isEmail", each Text.Contains([Column1],"@")),
    #"Added Index" = Table.AddIndexColumn(#"Added Custom", "Index", 0, 1, Int64.Type),
    #"Added Custom1" = Table.AddColumn(#"Added Index", "Grouper", each if [isEmail]  then [Index] else null),
    #"Filled Down" = Table.FillDown(#"Added Custom1",{"Grouper"}),
    #"Removed Columns" = Table.RemoveColumns(#"Filled Down",{"isEmail", "Index"}),
    #"Grouped Rows" = Table.Group(#"Removed Columns", {"Grouper"}, {{"Grouped", each _, type table [Column1=nullable text, Grouper=number]}}),
    #"Added Custom2" = Table.AddColumn(#"Grouped Rows", "Value", each Table.Column([Grouped],"Column1")),
    #"Removed Columns2" = Table.RemoveColumns(#"Added Custom2",{"Grouper", "Grouped"}),
    #"Added Custom3" = Table.AddColumn(#"Removed Columns2", "numSplits", each List.Count([Value])),

        //Make column splitting dynamic for each refresh, in case maximum number of columns changes
        splits = List.Max(Table.Column(#"Added Custom3","numSplits")),
        newColList = List.Zip({List.Repeat({"Value"},splits),List.Generate(() => 1, each _ <= splits, each _ +1)}),
        #"Converted to Table" = Table.FromList(newColList, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
        newColNamesTbl = Table.TransformColumns(#"Converted to Table", {"Column1", each Text.Combine(List.Transform(_, Text.From)), type text}),
        newColNamesList = Table.Column(newColNamesTbl,"Column1"),
        
    #"Extracted Values" = Table.TransformColumns(#"Added Custom3", {"Value", each Text.Combine(List.Transform(_, Text.From), ";"), type text}),
    #"Removed Columns1" = Table.RemoveColumns(#"Extracted Values",{"numSplits"}),
    #"Split Column by Delimiter" = Table.SplitColumn(#"Removed Columns1", "Value", Splitter.SplitTextByDelimiter(";", QuoteStyle.Csv), newColNamesList)
in
    #"Split Column by Delimiter"

源数据

结果