Safely transforming column types in Power Query

The Table.TransformColumnTypes function in M throws an error when you try to transform the data type of a column that does not exist. As of March 2020, there is no missingField parameter that can address this issue, in contrast to some other Table functions, like Table.RemoveColumns, which I blogged about before. This blog post shows how to imitate the behavior of the MissingField.Ignore argument in Table.TransformColumnTypes.

Sample data

To illustrate the problem, I’m going to use the similar queries as in my previous blog post:

  1. Source Table
  2. Transformation
Source Table

This is the initial query that contains our data. Sometimes you process a dynamic data source, and the list of columns can change.

A table with two columns, A and B

let
    Source =
        #table(
            type table [A=number, B=number],
            {{1, 2}, {3, 4}}
        )
in
    Source
Transformation

This query transforms the Source Table query: it transforms column types to Whole Number (note the different icons next to column names).

let
    Source = #"Source Table",
    #"Changed Type" =
        Table.TransformColumnTypes(
            Source,
            {{"A", Int64.Type}, {"B", Int64.Type}}
        )
in
    #"Changed Type"

The problem

Using the queries above as is, there is no error. Now imagine the column B is gone from Source Table:

let
    Source =
        #table(
            type table [A=number, B=number],
            {{1, 2}, {3, 4}}
        ),
    #"Removed Columns" = Table.RemoveColumns(Source,{"B"})
in
    #"Removed Columns"

The Transformation query now returns an error:

Expression.Error: The column 'B' of the table wasn't found. Details: B

This is because we’re trying to transform the column type of column B, which cannot be found in Source Table.

The solution

To solve the problem, we can use List.Accumulate and create the following custom function:

(table as table,
 typeTransformations as list,
 optional culture as nullable text) as table =>

List.Accumulate(
    typeTransformations,
    table,
    (x, y) => try Table.TransformColumnTypes(x, y, culture)
              otherwise x
)

This function can be called fSafelyTransformColumnTypes, for example. Once you create the custom function, you can use it instead of Table.TransformColumnTypes, because they have the same signature:

let
    Source = #"Source Table",
    #"Changed Type" =
        fSafelyTransformColumnTypes(
            Source,
            {{"A", Int64.Type}, {"B", Int64.Type}}
        )
in
    #"Changed Type"

The error is now gone, and the Transformation query returns column A.

To save type from typing the column-type pairs (the typeTransformations parameter in the function), you can change the column types by using the user interface first, then substitute Table.TransformColumnTypes with fSafelyTransformColumnTypes in the formula bar to protect your queries in the future.

Reminder: an idea

Please keep voting on the idea so the Power Query team can include the missingField parameter in the next releases: Include MissingField Argument with Table.TransformColumnTypes Function for Power Query

  • Artur Nawrocki

    Hi Daniil,
    I have really trouble with understanding the function (overall no just yours) syntax. What is a “culture” here? typeTransformation {{“A”, Int64.Type}, {“B”, Int64.Type}} or just {“A”, Int64.Type}? What is just {} in middle of function? And why x and y are introduced all of the sudden? They weren’t declared before. I hope you can explain – for me “M” functions are quite confusing.

    • Hi, Artur, explaining M syntax would require more than just a Disqus comment 🙂 Have you read any books on M? For example, Gil Raviv’s book? If not, that’s where I’d start.

  • You could also use Table.TransformColumns, as Table.TransformColumns(Table, {{“Col1”,Int64.From},{“Col2”,Text.From}) is the same as Table.TransformColumnTypes(Table, {{“Col1”,Int64.Type},{“Col2”,type text}) (You don’t need to supply the 3rd sub argument in the former as the column type will be changed by the function return type). Table.TransformColumns has the missingField argument.

    The other nice thing about Table.TransformColumns is that it also has the defaultTransformation argument as well.

  • Elegant Solution!!