|
let |
|
|
|
FnType = type function ( |
|
DataTable as (type table meta [ |
|
Documentation.FieldCaption = "DataTable", |
|
Documentation.FieldDescription = "Table that contains values that need replacing. Note that any columns in this table that have replacements in the DataMapTable should be type text" |
|
]), |
|
DataMapTable as (type table meta [ |
|
Documentation.FieldCaption = "DataMapTable", |
|
Documentation.FieldDescription = "Table that contains at least 3 text columns; ""Variable"", ""Value"" and ""Value Label"". These will be used to build the replacements." |
|
]), |
|
optional prefix as (type logical meta [ |
|
Documentation.FieldCaption = "prefix", |
|
Documentation.FieldDescription = "If true, prefixes the new values with the original ones." |
|
]) |
|
) as table meta [ |
|
Documentation.Name = "BulkReplaceValues", |
|
Documentation.Description = "Applies value labels to an entire table using the supplied data map.", |
|
Documentation.LongDescription = "A PowerQuery function that applies value transformations across multiple columins in a source table with value labels that are described in the data map", |
|
Documentation.Examples = {[ |
|
Description = "Typical usage", |
|
Code = "ApplyDataMapValues(#(lf) #table({""COL""}, {{""VAL""}}), #(lf) #table({""Variable"", ""Variable Name"", ""Value"", ""Value Label""}, {{""COL"", ""Column"", ""VAL"", ""Value""}})#(lf))", |
|
Result = "#table({""COL""}, {{""Value""}})" |
|
]} |
|
], |
|
|
|
// Bulk replaces a table's worth of values using DataMap |
|
// DataMap must contain "Variable", "Value" and "Value Label" columns. |
|
FnImpl = (DataTable as table, DataMapTable as table, optional prefix as logical) => |
|
|
|
let |
|
// Group the whole table by "Variable" |
|
GroupedDataMapTable = Table.Group(DataMapTable, {"Variable"}, {{ "Value Map", each _ }}), |
|
|
|
// Create the [value=label, transform=ation] records for each column |
|
ValueMapsDirty = Table.TransformColumns(GroupedDataMapTable, {{ "Value Map", each |
|
Record.FromList(Table.Column(_, "Value Label"), Table.Column(_, "Value")) |
|
}}), |
|
|
|
// Blatantly ignore any errors by removing them |
|
ValueMaps = Table.RemoveRowsWithErrors(ValueMapsDirty, {"Value Map"}), |
|
|
|
// List of column names in the source data that we actually have mapped values for |
|
IntersectingColumns = List.Intersect({ |
|
Table.Column(ValueMaps, "Variable"), |
|
Table.ColumnNames(DataTable) |
|
}), |
|
|
|
// Build a list of transforms |
|
Transforms = List.Transform(IntersectingColumns, (ColumnName) => { |
|
ColumnName, |
|
(DataValue) => |
|
if DataValue = null then null |
|
else ( |
|
(if prefix = true then (DataValue & " - ") else ("")) |
|
& Record.Field( |
|
ValueMaps{[Variable=ColumnName]}[#"Value Map"], |
|
DataValue |
|
) |
|
) |
|
} |
|
), |
|
|
|
// Now apply the transforms to the source data and we're done! |
|
TransformedData = Table.TransformColumns(DataTable, Transforms) |
|
|
|
in |
|
TransformedData |
|
|
|
in |
|
Value.ReplaceType( |
|
FnImpl, |
|
FnType |
|
) |