なんでもエクセル(Nandemo Excel)

何でもエクセルでやってしまう そこのあなた。ようこそ

Power Query:同行の範囲を指定して条件抽出する(Record.FieldValues)

時々あるんだけど「行全体から特定の値が1つでもあれば抽出」みたいな処理。

例えばこんな表で、日付列の中に1つでも「梨」がある行を抽出したい場合。抽出方法はいくつか考えらえる。

ひとつは、グループ化した列のリストを対象にして検索する方法。「テーブル1」は予め読み込んでいるものとする。

    行のグループ化 = Table.Group(テーブル1, 
        {"出席番号", "氏名"}, {"グループ", each _}
    ),
    行の抽出 = Table.SelectRows(行のグループ化, each [
        リスト = Table.Transpose([グループ])[Column1],
        除外リスト = List.Difference(リスト, {"出席番号", "氏名"}),
        検索 = List.FindText(除外リスト, "梨")<>{}
    ][検索]),
    グループ列の展開 = Table.ExpandTableColumn(
        行の抽出, "グループ", 
        List.Difference(
            Table.ColumnNames(テーブル1), {"出席番号","氏名"}
        )
    )

多分こっちがオーソドックスだと思うけど、これだとデータ型を指定するタイミングが難しい。この手の表は見出しが変動する可能性が高いので、グループ化の時にかっちりデータ型を指定するのが難しい。この場合、展開してから再度設定し直しが必要になるかと思われる。

というわけで「Record.FieldValues」を使う方法。

    行の抽出 = Table.SelectRows(ソース, each [
        値 = Record.FieldValues(_),
        チェック = 値<>List.RemoveItems(値, {"梨"})
    ][チェック])

これだとこんな感じ。これだと抽出の前にデータ型を指定しやすい。

let
    ブック = Excel.CurrentWorkbook(),
    ソース = ブック{[Name="テーブル1"]}[Content],
    見出し = Table.ColumnNames(ソース),
    タイプ = List.Transform(List.Skip(見出し), each {_, Text.Type}),
    型の変更 = Table.TransformColumnTypes(
        ソース, {{"出席番号", Int64.Type}} & タイプ
    ),
    行の抽出 = Table.SelectRows(型の変更, each [
        値 = Record.FieldValues(_),
        チェック = 値 <> List.RemoveItems(値, {"梨"})
    ][チェック])
in
    行の抽出

「Table.ColumnNames」や「Record.FieldValues」を使えば、日付列が右方向にどれだけ増えても関係ない。「日付列が全部空白の列は取り除く」ような作業も簡単にできる。