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

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

Power Query:検索リストを使って部分一致で抽出する

例えば、住所の一覧から「北海道」「青森県」……みたいな都道府県名リストを基にして部分一致で抽出を掛けたい時。あるいは特定のキーワードを含むデータを抽出したい時。「部分位置で抽出」の用途は多岐にわたるかと思う。

 

社名リストの中から検索リストに該当する会社名だけを抽出する時、完全一致の場合はクエリのマージを使って一致するものだけ抽出すればいいので簡単。ただ上のような部分一致で検索して抽出したい場合、マージではうまくいかない。こういう場合はカスタム関数を作ったほうがいいかと思う。

「社名リスト」と「検索リスト」はそれぞれクエリを作成済みとして

部分一致検索関数
(検索値 as text) =>
let
    ソース = 社名リスト,
    行の抽出 = Table.SelectRows(ソース, each Text.Contains([会社名], 検索値))
in
    行の抽出

こういう専用の関数を作っておいて、呼び出して展開。

検索結果
let
    ソース = 検索リスト,
    部分一致検索 = Table.AddColumn(
        ソース, "部分一致検索", each 部分一致検索([検索名])
    ),
    検索結果を展開 = Table.ExpandTableColumn(
        部分一致検索, "部分一致検索", {"会社名"}
    ),
    空白行を削除 = Table.SelectRows(
        検索結果を展開, each [会社名] <> null
    ),
    列の選択 = Table.SelectColumns(空白行を削除,{"会社名"})
in
    列の選択

手続き的に簡単なのは多分これ。抽出結果はこんな感じ。

ただ、このやり方だと順番を検索リストに合わせる形になるので若干不細工。できれば社名リストの順に並んで欲しい。なのでちょっとやり方を変えて見る。

    部分一致抽出 = Table.SelectRows(社名リスト, each
        let 会社名 = _[会社名],
            検索名リスト=List.Buffer(検索リスト[検索名]),
            抽出 = List.Select(検索名リスト, each Text.Contains(会社名, _))
        in List.Count(抽出) > 0
    )

こうすれば社名リストの順に抽出される。似たようなやり方で、次のような方法もある。

    部分一致抽出 = Table.SelectRows(社名リスト, (t)=>[
        検索名リスト=List.Buffer(検索リスト[検索名]),
        抽出=List.Select(
            検索名リスト, each Text.Contains(t[会社名], _)
        ),
        結果=List.Count(抽出)>0
    ][結果])

どっちがいいとも言い難いので、好みの問題かなと思う。