いきなり答える備忘録

Google Workspace・Microsoft 365・LibreOfficeなどに関するメモ

(Excel)XLOOKUP関数を縦横にスピルさせる

 ExcelのXLOOKUP関数では1つの検索キーに対し複数の値を一括して取得できますが、さらに検索キーが複数になった場合は各検索キーに対し値を1つずつしか取得できなくなります。いわゆる縦横同時にスピルしない問題です。
 別の関数を使って同じ結果を実現する手もありますが、ここではXLOOKUPを使ったうえで何とかしてみます。

  • REDUCE/LAMBDA関数等を併用することでXLOOKUP関数を事実上縦横にスピルさせることができます。
  • MAKEARRAY/LAMBDA関数等を併用する方法もあります。出力は理想的ですが、もはやスピルと言えるか微妙です。

手順

問題の再現

 H3セルにXLOOKUP関数を使った式を入力し、G3:G5の3つの値(氏名)に対応する3科目の成績を一括して取得しようとしています。
 しかし取得できるのは数学の成績(第3引数で指定した範囲のうち最も左の列)だけです。氏名の値が1つだけなら3科目の成績を一括して取得できますが、2つ以上になるとこのようにうまくいきません。

REDUCE/LAMBDA関数を併用する方法

 次の画像では、上の画像の式に手を加えてすべての値を一括して取得しています。

 H3セル

=DROP(
REDUCE("",G3:G5,LAMBDA(a,b,VSTACK(a,XLOOKUP(b,B3:B8,C3:E8,"")))),
1)

 MAP/LAMBDAで済みそうにも見えますがXLOOKUPとの相性が悪く、エラーになってしまいます。
 そこでREDUCE/LAMBDAを使っています。VSTACK関数を併用し、G3:G5(=b)の各値に対するXLOOKUP関数の実行結果を縦にスタックしています。
 最初の行に無駄な空文字列が残りますので最後にDROP関数で削除して完成です。この辺りはISOMITTEDなどを使って省けるかもしれませんが、かえって長くなりそうなので妥協しました。


 なお、XLOOKUP関数の第4引数(検索キーが見つからなかったときの値)を空文字列にしており、実際に値がないときの結果は次の画像のようになります。この戻り値を省略またはエラー値を指定すると、値が1つでも見つからないときに1つも結果が得られない(「#N/A」が1個だけ返る)という残念仕様のためこうしています。VSTACK単体ならエラー値だろうが列数が異なろうが連結できるので、この辺りは謎です。

 LAMBDA内で「IF(ISNA(~),EXPAND(~,NA()),VSTACK(~))」のようにすれば値が見つからない場合に#N/Aエラーだけの行が得られますが、式が長くなりますし、それは次の方法で実現できますので省略します。

MAKEARRAY/LAMBDA関数を併用する方法

 行列生成を行うMAKEARRAY関数を用いる方法です。
 REDUCE/LAMBDA関数の例と同様にすべての値を一括して取得できています。

 H3セル

=MAKEARRAY(ROWS(G3:G5),COLUMNS(C3:E8),
LAMBDA(r,c,XLOOKUP(INDEX(G3:G5,r),B3:B8,INDEX(C3:E8,,c)))
)

 検索キーであるG3:G5の行数をr、戻り値の範囲C3:E8の列数をcと定義し、行数r・列数cの行列を生成、そのセルの1つ1つでXLOOKUP関数を実行しています。個々のXLOOKUPではスピルを使っていないので縦横スピルとは言い難い感じですし、ちょっとややこしいのが難点です。重そうなのも気になります。


 ただし1つのメリットとして、値が見つからない場合にはすべて#N/Aエラーの行が得られます。