【问题标题】:Table column split by value to other columns and it's values表列按值拆分到其他列及其值
【发布时间】:2016-12-02 00:16:44
【问题描述】:

我有这种表格,如果看起来,它代表产品的规格

其中第 1 列是 SKU 并用作 ID,第 2 列是我们规范规范标题,值和 0 或 1 作为可选参数(如果错过,则默认为 1)由“~”分隔,ech 选项由 ^ 分隔p>

我想将它拆分为带有 SKU 的表格,每个规格标题作为列标题,值作为它的值

我设法编写此代码以将其拆分为具有深入规范的记录和堆栈,并将每个规范和记录的标题与值分开,以及如何寻求帮助

    let
    Source = Excel.CurrentWorkbook(){[Name="Таблица1"]}[Content],
    Type = Table.TransformColumnTypes(Source,{{"Part Number", type text}, {"Specifications", type text}}),
    #"Replaced Value" = Table.ReplaceValue(Type,"Specification##","",Replacer.ReplaceText,{"Specifications"}),
    SplitByDelimiter = (table, column, delimiter) => 
        let 
            Count = List.Count(List.Select(Text.ToList(Table.Column(table, column){0}), each _ = delimiter)) + 1, 
            Names = List.Transform(List.Numbers(1, Count), each column & "." & Text.From(_)), 
            Types = List.Transform(Names, each {_, type text}), 
            Split = Table.SplitColumn(table, column, Splitter.SplitTextByDelimiter(delimiter), Names), 
            Typed = Table.TransformColumnTypes(Split, Types) 
        in 
            Typed, 
    Split = SplitByDelimiter(#"Replaced Value","Specifications","^"),
    Record = Table.ToRecords(Split)
in
    Record

【问题讨论】:

  • 有一些很好的答案at this question 关于在 excel 中用分隔符分割字符串。那里的第一个 VBA UDF 可以很容易地完成您需要的工作,而且非常轻量级。
  • 能否提供一个代码示例表,好吗?使用 Table.FromRecords 或 #table({},{{}})
  • 同意 Sergey 的观点,请不要只发布您输入数据的屏幕截图。另外,您能否发布您的代码今天返回的内容,以及您希望它返回的输出内容?

标签: excel powerquery


【解决方案1】:

好的,我希望你仍然需要这个,因为它花了整个晚上。 :)) 我必须说非常有趣的任务!

我假设 "~1" 总是与 "^" 组合,所以 "~1^" 总是结束字段的值。我还假设值中没有 ":",因为所有冒号都被删除了。

IMO,您根本不需要使用 Table.SplitColumn 函数。

let 
    //replace it with your Excel.CurrentWorkbook(){[Name="Таблица1"]}[Content],
    Source = #table(type table [Part Number = Int64.Type, Specifications = text], {{104, "Model:~104~1^Type:~Watch~1^Metal Type~Steel~1"}, {105, "Model:~105~1^Type:~Watch~1^Metal Type~Titanium~1^Gem Type~Ruby~1"}}),

    //I don't know why do you replace these values, do you really need this?
    ReplacedValue = Table.ReplaceValue(Source,"Specification##","",Replacer.ReplaceText,{"Specifications"}),
    TransformToLists = Table.TransformColumns(Source, {"Specifications", each List.Transform(List.Select(Text.Split(_ & "^", "~1^"), each _ <> "") , each Text.Split(Text.Replace(_, ":", ""), "~"))  } ),
    ConvertToTable = Table.TransformColumns(TransformToLists, {"Specifications", each Table.PromoteHeaders(Table.FromColumns(_))}),
    ExpandedSpecs = Table.TransformRows(ConvertToTable, (x) => Table.ExpandTableColumn(Table.FromRecords({x}), "Specifications", Table.ColumnNames(x[Specifications])) ),
    UnionTables = Table.Combine(ExpandedSpecs),
    Output = UnionTables
in
    Output

更新:

它是如何工作的(跳过明显的步骤):

TransformToLists:TransformColumns 采用表格,以及应用于 列值的列名和函数列表。所以它将几个嵌套函数应用于每一行的“规范”字段的值。这些函数执行以下操作: List.Select 返回非空值列表,按顺序通过将 Text.Split 函数应用于已删除“:”的“规范”字段的值获得该列表:

   Text.Split(
              Text.Replace(_, ":", "")
              , "~")

每个关键字表示对每个处理过的值(可以是字段、列、行/记录、列表项、文本、函数等)应用以下函数,用下划线符号表示。这个下划线可以用函数代替:

  each _ equals (x) => some_function_that_returns_corresponding_value(x) 

所以,

  each Text.Replace(_, ":", "") 
      equals 
  (x) => Text.Replace(x, ":", "") //where x is any variable name. 

  //You can go further and make it typed, although generally it is not needed:
  (x as text) => Text.Replace(x, ":", "") 

  //You can also write a custom function and use it:
  (x as text) => CustomFunctionName(x)

话虽如此,TransformToLists 步骤会返回一个包含两列的表格:“零件号”和“规格”,其中包含列表列表。这些列表中的每一个都有两个值:列名及其值。发生这种情况是因为“规格”字段中的初始值必须拆分两次:首先将其拆分为“~1^”对,然后将每对拆分为“~”。所以现在我们在每个嵌套列表中都有列名及其值,现在我们必须将它们全部转换为一个表。

ConvertToTable:我们再次应用 TransformColumns,对每一行的“规范”字段使用一个函数(记住,一个列表的列表)。我们使用 Table.FromColumns,因为它将列表列表作为参数,并返回一个表,其中第一行是列标题,第二行是它们的值。然后我们将第一行提升为标题。现在我们有一个表,“规格”字段包含具有可变列数的嵌套表。我们必须把它们放在一起。

ExpandedSpecs:Table.TransformRows 将转换函数应用于表中的每一行(作为记录)(在代码中它被签名为 x em>)。您可以像我一样编写自定义函数:

= Table.ExpandTableColumn( //this function expands nested table. It needs a table, but "x" that we have is a record. So we do the conversion:
    Table.FromRecords({x}) //function takes a list of records, so {x} means a list with single value of x
    , "Specifications" //Column to expand
    , Table.ColumnNames(x[Specifications]) //3rd argument is a list of resulting columns. It takes table as an argument, and table is contained within "Specifications" field.
 ) 

它返回一个表列表(每个表都有一行),我们在 UnionTables 步骤使用 Table.Combine 将它们组合起来。这会导致一个表包含组合表中的所有列,如果其中一些列中没有这样的列,则为空值。

希望对您有所帮助。 :)

【讨论】:

  • 看看它的工作。它抛出关于重复列“零件号”的错误,但我修复了它。 "~1" 并不总是在规范中,但是是的,它总是在 "^" 之前。你能解释一下 - 使用“每个”,下划线字符“_”和这种收缩“(x)=> Table.ExpandTableColumn”
  • 我已经编辑了答案并添加了详细说明。
  • 谢谢。现在有机会了解每个命令的语法
【解决方案2】:

如果我明白你在问什么MSDN for Range.TextToColumnsTextToColumns VBA 解决方案会简单得多

【讨论】:

  • 这是通常的拆分,这就像 Power 查询中的“SplitTextByDelimiter”一样,并且没有机会从 Value 中拆分 Spec-Title 并保留对零件号的引用。我希望它拆分到(例如 - 我发送的表格的第一行)“零件号”、“型号”,然后如果它出现在单元格中,则与零件号和模型规格的值一起排
猜你喜欢
  • 1970-01-01
  • 2021-07-26
  • 2020-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-23
  • 2021-10-05
  • 2016-01-17
相关资源
最近更新 更多