LoginSignup
13
9

More than 5 years have passed since last update.

対象となる列やフィールドがないときどうするって話

Last updated at Posted at 2019-02-28

ソースデータにあるはずと思っていた列やフィールドが存在しないことがあるなんてわりとよくあることで、これについて Power Query ではどうしておくかなってこと。

Expression.Error: テーブルの列 '日付' が見つかりませんでした。

なんていうのはPower Query エディターでよく見かけます。

いきなり別件ですが、CSV や Excel ワークシート上のデータを読み込むとき "型の検出" が行われるのが既定なのでムキーってなる人はオフにするとかできますのでお好みでどうぞ。Power BI Desktop でも同じ。
image.png

で、列のデータ型変換(Table.TransformColumnTypes)はこのあといくつかの手段で解決できるものではないので早々にあきらめて。

挙動を指定できる関数

MissingField.Type

MissingField.Type
想定より少ない列を含む行内で不足している値に対して予期されるアクションを指定します。

  • MissingField.Error
  • MissingField.Ignore
  • MissingField.UseNull

MissingField.Error : Expression.Error になりクエリの評価ができなくなる(既定値)
MissingField.Ignore : 無視してクエリの評価は続行
MissingField.UseNull : null で補完してクエリの評価を続行

MissingField.Type を指定できる関数

MissingField.Type の定数すべてを受け付けるとは限らないけれども、MissingField.Type のオプション引数が定義されている関数。サポートされていない環境があったとしてそれはバージョンによるもの。

Record.RemoveFields
指定されたフィールドを入力レコードから削除します。

Record.RenameFields
{ old, new } という形式のリストを使用して、名前の変更を適用します。

Record.ReorderFields
指定されたフィールドを新しい順序で並べ替えます。

Record.SelectFields
指定されたフィールドのみを含むレコードを返します。

Record.TransformFields
指定された変換を適用したレコードを返します。

Table.FromRecords
レコードのリストをテーブルに変換します。

Table.SelectColumns
指定された列のみを含むテーブルを返します。

Table.RenameColumns
{old, new} という形式の名前の変更を適用します。

Table.ReorderColumns
指定された順序で列を含むテーブルを返します。

Table.RemoveColumns
指定された列を削除します。

Table.TransformColumns
{ column, transform } という形式の変換を適用します。

いくつかサンプル

Table.SelectColumns+MissingField.Ignore
let
    Source = #table(
        {"Column1","Column2","Column3"},
        {}
    ),
    SelectColumns = Table.SelectColumns(
        Source,
        {"Column1","ColumnX"},
        MissingField.Ignore
    ),
    ColumnNames = Table.ColumnNames(SelectColumns)
in
    ColumnNames // {"Column1"}
Table.SelectColumns+MissingField.UseNull
let
    Source = #table(
        {"Column1","Column2","Column3"},
        {{1, 1, 1}}
    ),
    SelectColumns = Table.SelectColumns(
        Source,
        {"Column2", "Column1","ColumnX"},
        MissingField.UseNull
    )
in
    SelectColumns

image.png
列の順番も変えてみた。

フィールドアクセスで挙動を指定

例えば Table.AddColumn で 存在しない列を参照したとき。

存在しない列を参照するとExpression.Error
let
    Source = #table(
        {"Column1", "Column2"},
        {
            {1, 1}
        }
    ),
    AddedCustom1 = Table.AddColumn(
        Source,
        "Custom1",
        each [Column2]
    ),
    RemovedColumn2 = Table.RemoveColumns(
        AddedCustom1,
        {"Column2"}
    ),
    AddedCustom2 = Table.AddColumn(
        RemovedColumn2,
        "Custom2",
        each [Column2]
    )
in
    AddedCustom2

クエリの評価はされるもののエラーとなる値が存在する。まぁそうですよね。
image.png

Expression.Error:レコードのフィールド 'Column2' が見つかりませんでした。

存在しない列を参照してもExpression.Errorにならない
let
    Source = #table(
        {"Column1", "Column2"},
        {
            {1, 1}
        }
    ),
    AddedCustom1 = Table.AddColumn(
        Source,
        "Custom1",
        each [Column2]?  // ココ
    ),
    RemovedColumn2 = Table.RemoveColumns(
        AddedCustom1,
        {"Column2"}
    ),
    AddedCustom2 = Table.AddColumn(
        RemovedColumn2,
        "Custom2",
        each [Column2]?  // ココ
    )
in
    AddedCustom2

ダイアログでの投入はこんな感じ
image.png

image.png

テーブルの行は record として参照できて、フィールドの値は "[ ]" ブラケットで指定するのだけど、"?"を追記すると、フィールドが存在しない場合 null を返し、存在する場合その値を返す。

フィールドの値が record のとき、そのフィールドの値は [ColumnName][FieldName] と繋げばアクセス可能で、[ColumnName]?[FieldName]? とすればよい。

列 / フィールド ではないけれども、"{ }" アイテムアクセスでも使用可能

0行のテーブルの1行目を参照
#table(null, {}){0}? = null

その他

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9