Power Query Применение функции в каждом столбце - PullRequest
3 голосов
/ 15 марта 2019

Я пытаюсь написать запрос, который берет таблицу и умножает каждое число в таблице на 100. Я подошел близко, но у меня возникают проблемы с его корректным применением к каждому столбцу. Ниже приведен код, который у меня есть. Строка, начинающаяся с ReplaceTable , - это строка, которую я работаю для одного столбца, а строка ниже была моей попыткой заставить его работать для других столбцов. В настоящее время я имею дело с небольшим подмножеством, но реальные данные могут иметь ~ 100 столбцов, поэтому я не хочу делать это вручную. Если есть лучший способ сделать это, пожалуйста, дайте мне знать. Я новичок в Power Query, поэтому, если сможете, пожалуйста, объясните мою ошибку / решение, чтобы я мог узнать. Спасибо!

let
    Source = Excel.CurrentWorkbook(){[Name="Data"]}[Content],
    //Organization will always be of type text.  The others will be should be numbers, unless user error
    #"Changed Type" = Table.TransformColumnTypes(Source, {{"Organization", type text}, {"A", Int64.Type}, {"B", Int64.Type}, {"C", Int64.Type}}),
   //function to replace all values in all columns with multiplied values
   MultiplyReplace = (DataTable as table, DataTableColumns as list) =>
     let
        Counter = Table.ColumnCount(DataTable),
        ReplaceCol = (DataTableTemp, i) =>
            let
                colName = {DataTableColumns{i}},
                col = Table.Column(DataTableTemp, colName),
                //LINE THAT WORKS- want this functionality for ALL columns
                ReplaceTable = Table.ReplaceValue(DataTableTemp, each[A], each if [A] is number then [A]*100 else [A], Replacer.ReplaceValue, colName)
                //ReplaceTable = Table.ReplaceValue(DataTableTemp, each col, each if col is number then col*100 else col, Replace.ReplaceValue, colName)
            in
                if i = Counter-1 then ReplaceTable else @ReplaceCol(ReplaceTable, i+1)
     in
        ReplaceCol(DataTable, 0),
    allColumns = Table.ColumnNames(#"Changed Type"),
    #"Multiplied Numerics" = MultiplyReplace(#"Changed Type", allColumns)
    //#"Restored Type" = Value.ReplaceTypes(#"Multiplied Numerics", #"Changed Type")
in
    #"Multiplied Numerics"

1 Ответ

1 голос
/ 15 марта 2019

Проблема связана с объемом функций и переменных.

С жестко закодированным именем столбца (например, [A]) код понимает сокращение, которое фактически означает _[A]. В функции Table.ReplaceValue этот _ ссылается на текущую запись или строку. Однако переменная col ссылается на столбец таблицы whole . При использовании в функции заменителя это вызывает ошибку. (К сожалению (?), Ошибки в функциях заменителя просто игнорируются без сообщения об ошибке, поэтому проблемы трудно отследить.)

В исправленном коде я избавился от переменной col, поскольку она определяется на неправильном уровне области видимости. Я изменил colName на текст вместо списка, а затем использовал функцию Record.Field с _ (текущая запись в функции Table.ReplaceValue) и текстовое значение colName, чтобы извлечь нужную запись для расчеты с самой функцией Table.ReplaceValue.

Исправленный код


let
    Source = Excel.CurrentWorkbook(){[Name="Data"]}[Content],
    //Organization will always be of type text.  The others will be should be numbers, unless user error
    #"Changed Type" = Table.TransformColumnTypes(Source, {{"Organization", type text}, {"A", Int64.Type}, {"B", Int64.Type}, {"C", Int64.Type}}),
   //function to replace all values in all columns with multiplied values
   MultiplyReplace = (DataTable as table, DataTableColumns as list) =>
     let
        Counter = Table.ColumnCount(DataTable),
        ReplaceCol = (DataTableTemp, i) =>
            let
                colName = DataTableColumns{i},
                //LINE THAT WORKS- want this functionality for ALL columns
                ReplaceTable = Table.ReplaceValue(DataTableTemp,each Record.Field(_, colName), each if Record.Field(_, colName) is number then Record.Field(_, colName)*100 else Record.Field(_, colName),Replacer.ReplaceValue,{colName})
                //ReplaceTable = Table.ReplaceValue(DataTableTemp, each col, each if col is number then col*100 else col, Replace.ReplaceValue, colName)
            in
                if i = Counter-1 then ReplaceTable else @ReplaceCol(ReplaceTable, i+1)
     in
        ReplaceCol(DataTable, 0),
    allColumns = Table.ColumnNames(#"Changed Type"),
    #"Multiplied Numerics" = MultiplyReplace(#"Changed Type", allColumns)
    //#"Restored Type" = Value.ReplaceTypes(#"Multiplied Numerics", #"Changed Type")
in
    #"Multiplied Numerics"
...