Reputation: 5
My use-case is importing a CSV data table. The imported table has by default type 'text' for all columns. Then transform each column based on a separate transformation table.
'Key' 'Name' 'Creation Date'
-------------------------------------------
'1' 'Bob' '21/Jan/20 12:00 AM'
'Field' 'Directive'
-------------------------------------
'Key' 'int64'
'Name' 'text'
'Creation Date' 'date'
My objective is to transform the CSVTable based on the directive in the TransformationTable.
NOTE: 'Name' field is already in text format in the CSV, so no need to transform.
Currently I have hard-coded the transformation in below code line. This snippet
OutputTable = Table.TransformColumnTypes(CSVTable,{{"Key", Int64.Type}, {"Creation Date", type datetime}}),
I want to control the transformation based on the definitions in TransformationTable, instead of hard-coded. How do I achieve that?
Upvotes: 0
Views: 469
Reputation: 21413
I'll start off by saying I don't think it is possible, because you have the Int64 type in there. I believe you can only change programmatically to these Primitive Types
type null, which classifies the null value
type logical, which classifies the values true and false
type number, which classifies number values
type time, which classifies time values
type date, which classifies date values
type datetime, which classifies datetime values
type datetimezone, which classifies datetimezone values
type duration, which classifies duration values
type text, which classifies text values
type binary, which classifies binary values
type type, which classifies type values.
type list, which classifies list values
type record, which classifies record values
type table, which classifies table values
type function, which classifies function values
type anynonnull, which classifies all values excluding null
That said, assuming you had TransformationTable and CSVTable, this code would (a) list columns in CSVTable (b) Merge the transformation table (c) Expand the merge (d) pull out just the type column (e) add prefix (f) evaluate the expression result to make the result usable (g) use List.Zip to create a paired set of lists of column and type (h) rename based on the List.Zip
let Source = CSVTable,
//List of column names
Columns=Table.ColumnNames(Source),
// Merge in Transformation table to get types for each column
#"Merged Queries" = Table.NestedJoin(Table.FromList(Columns),{"Column1"},TransformationTable,{"Field"},"TransformationTable",JoinKind.LeftOuter),
#"Expanded TransformationTable" = Table.ExpandTableColumn(#"Merged Queries", "TransformationTable", {"Directive"}, {"Directive"}),
// Pull just the column with types in it
Directives=Table.Column(#"Expanded TransformationTable","Directive"),
// Add a prefix and evaluate the expression to make it usable
Directives2 = List.Transform(Directives, each Expression.Evaluate("type " & _)),
// Convert the column names and types to a paired list
TransformList = List.Zip({Columns, Directives2}),
// Convert the column names to the types
TypeTable= Table.TransformColumnTypes(Source, TransformList)
in TypeTable
Upvotes: 0
Reputation: 5696
Based on this setup:
Column types table name: TableTypes
Values table name: Table1
Source code:
Table: TableTypes
let
Source= Excel.CurrentWorkbook(){[Name="TableTypes"]}[Content],
ChangeColTypes = Table.TransformColumnTypes(Source,{{"Column header", type text}, {"Type", type text}}),
ToType = Table.TransformColumns(ChangeColTypes,{{"Type", Expression.Evaluate}}),
ToField = Table.AddColumn(ToType, "Custom", each Record.FieldValues(_)),
RemoveOtherCols = Table.SelectColumns(ToField,{"Custom"}),
ToList = RemoveOtherCols[Custom]
in
ToList
Table: Table1
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
ChangeTypes = Table.TransformColumnTypes(Source,TableTypes)
in
ChangeTypes
Output:
If you really need the non-primitive types (like Int64.Type) use:
= Table.TransformColumns(types, {{"col Type", each Expression.Evaluate(_, [Currency.Type=Currency.Type, Int64.Type=Int64.Type, Percentage.Type=Percentage.Type]) }})
Upvotes: 2