Excel LAMBDAでORが配列全体を判定する原因と要素ごとのORに直す方法

ExcelのLAMBDAに配列(スピルする範囲や配列定数)を渡したとき、「ORだけが要素ごとに判定されず、配列全体を見てしまう」現象に悩む人は少なくありません。原因はLAMBDAではなく、OR/ANDが“集約(配列→1つの結果)”として設計されていることです。要素ごとのORに直す実務的な書き方を、再現例と一緒に整理します。

目次

起きている現象:ORが“各要素”ではなく“配列全体”を評価してしまう

次のように、LAMBDAの引数に配列(例:{"aaa";"bbb"} や {"ccc";123})を渡し、ISNUMBER() の判定結果を確認している状況を想定します。

=LET(
  txtA, {"aaa";"bbb"},
  txtB, {"ccc";123},
  f, LAMBDA(a,b,
    HSTACK(
      a,
      b,
      ISNUMBER(a),
      ISNUMBER(b),
      OR(ISNUMBER(a), ISNUMBER(b))
    )
  ),
  f(txtA, txtB)
)

感覚としては「1行目(aaa/ccc)はどちらも数値ではないからORはFALSE、2行目(bbb/123)はどちらかが数値だからTRUE」になってほしいはずです。ところが、実際にはOR列が両方TRUEになったり、逆に両方FALSEになったりします。

行a(txtA)b(txtB)ISNUMBER(a)ISNUMBER(b)OR(ISNUMBER(a),ISNUMBER(b))期待するOR
1aaacccFALSEFALSETRUE(配列全体に123があるため)FALSE
2bbb123FALSETRUETRUETRUE

さらに厄介なのが、txtB の2行目だけを 123 から "ddd" に変えると、1行目のORまで巻き添えで変わることです。これは「ORが各行のペアを見ている」のではなく、「配列全体のどこかにTRUEがあるか」を一度だけ判定しているために起きます。

原因:OR/ANDは“配列を受けると1つの結果に集約する”関数

ポイントは、OR/ANDは配列に対して要素ごとにスピルする関数ではなく、配列全体をまとめて1つの真偽値に潰す(集約する)という性質を持つことです。

Excelでは昔から、OR(A1:A10) のように範囲を渡すと「範囲のどこかがTRUEならTRUE」という集計をしてきました。動的配列(スピル)やLAMBDAを使っても、この“集計としてのOR”は変わりません。

今回の例では、ISNUMBER(a) と ISNUMBER(b) は配列(2行分)を返します。ところが、そこへ OR(...) をかけると、ORは配列を横断して1回だけ評価し、単一のTRUE/FALSEを返します。さらに HSTACK のように配列同士を結合する場面では、スカラー(1つの値)は配列サイズに合わせて自動的に拡張(ブロードキャスト)されるため、同じTRUE/FALSEが“各行に横流し”されて見えてしまいます。

式結果の形意味合い
ISNUMBER({"aaa";123}){FALSE;TRUE}(配列)要素ごとの判定
OR(ISNUMBER({"aaa";123}))TRUE(1値)配列全体を集約して判定
HSTACK({"a";"b"}, TRUE)2行×2列(TRUEが各行に複製)スカラーが配列に拡張される

つまり「LAMBDAが突然“配列全体の文脈”に切り替わった」のではなく、ORが最初から“配列→1値”の関数であり、結果が結合時に拡張されて見えているだけ、という整理になります。

解決策A:ORを使わず、真偽値の加算で“要素ごとのOR”を作る

実務で最も手堅く、式も短いのがこの方法です。OR相当は「TRUE/FALSEを1/0として足し算し、合計が1以上ならTRUE」と考えます。

(ISNUMBER(a)+ISNUMBER(b))>0

これを先ほどの式に差し替えると、期待どおりに要素ごとの結果が返ります。

=LET(
  txtA, {"aaa";"bbb"},
  txtB, {"ccc";123},
  f, LAMBDA(a,b,
    HSTACK(
      a,
      b,
      ISNUMBER(a),
      ISNUMBER(b),
      (ISNUMBER(a)+ISNUMBER(b))>0
    )
  ),
  f(txtA, txtB)
)
行ab(ISNUMBER(a)+ISNUMBER(b))>0
1aaacccFALSE
2bbb123TRUE

加算方式の良いところは、配列同士の演算(+)は基本的に要素ごとに計算されるため、ORのように“全体集約”が起きにくい点です。スピル範囲にそのまま使えるので、データ検証・抽出条件・判定列の生成に向きます。

加算ORの定番テンプレート

やりたいことテンプレートメモ
2条件のOR(cond1+cond2)>0最も基本
3条件以上のOR(cond1+cond2+cond3)>0条件を足していくだけ
AND(全て満たす)(cond1*cond2*cond3)>0掛け算は“全てTRUEなら1”
ORの結果を明示的にTRUE/FALSEにするIF((cond1+cond2)>0, TRUE, FALSE)表示を揃えたい時

注意点:エラー値が混ざる可能性がある場合

ISNUMBER() 自体は通常エラーを返しにくいですが、実務では「途中に#N/Aが入る」「別の判定式がエラーになる」ことがあります。足し算・掛け算はエラーを伝播しやすいので、必要ならエラーを0(FALSE扱い)に落とす一工夫を入れると安定します。

=LET(
  c1, IFERROR(--ISNUMBER(a),0),
  c2, IFERROR(--ISNUMBER(b),0),
  (c1+c2)>0
)

--(ダブルマイナス)はTRUE/FALSEを1/0に強制変換する定番テクニックです。IFERRORで包めば、エラーを0として扱えます。

解決策B:MAPで“要素ごと”にORを呼ぶ(ORを残したい人向け)

「どうしてもORという関数名のまま書きたい」「条件が複雑で加算より読みやすい」場合は、MAPで1要素ずつスカラーにしてからORを実行するのが正攻法です。

=LET(
  txtA, {"aaa";"bbb"},
  txtB, {"ccc";123},
  MAP(txtA, txtB, LAMBDA(a,b, OR(ISNUMBER(a), ISNUMBER(b))))
)

MAPは、対応する要素同士を1件ずつLAMBDAに渡していくため、LAMBDA内のaとbはスカラー(単一値)になり、ORが集約を起こしません。その結果、出力は要素ごとのTRUE/FALSEになります。

MAPで“デバッグ表示”も一緒に作る

判定の途中経過を文字列化して確認したい場合も、MAPは便利です。

=LET(
  txtA, {"aaa";"bbb"},
  txtB, {"ccc";123},
  MAP(txtA, txtB,
    LAMBDA(a,b,
      "A="&a
      &" / B="&b
      &" / ISNUMBER(A)="&ISNUMBER(a)
      &" / ISNUMBER(B)="&ISNUMBER(b)
      &" / OR="&OR(ISNUMBER(a),ISNUMBER(b))
    )
  )
)

「どの行で何がTRUEになっているか」を可視化しやすく、判定式が長い場合の切り分けにも使えます。

MAPを使うときの実務メモ

  • 配列の形(行数・列数)は揃える:MAPは基本的に対応する要素同士を処理します。片方だけ縦2行、もう片方が縦3行のようにサイズが違うと意図しない結果やエラーになります。
  • スピル範囲にもそのまま使える:MAP(A2:A100, B2:B100, ...) のように範囲を渡せば、結果が縦にスピルします。
  • Microsoft 365の新しめのExcelで利用できる:環境によってはMAPが未提供の場合があります。その場合は次のBYROW/BYCOLや、加算方式が現実的です。

解決策C:行単位・列単位の判定ならBYROW/BYCOLが分かりやすい

「要素ごと」ではなく「行ごと(1行の中でどれかがTRUEならTRUE)」のような要件なら、ORはむしろ得意です。集約が起きる性質を意図してスコープを狭めるのがコツです。

例えば、A~C列のどこかに数値がある行だけTRUEにしたい場合は、次のように書けます。

=BYROW(A2:C10, LAMBDA(r, OR(ISNUMBER(r))))

BYROWが1行ずつ r(1×3の配列)を渡し、ORがその行の中だけを集約して1つの結果を返します。これなら「ORが配列全体を見てしまう」問題にはなりません。逆に、列ごとに判定したいならBYCOLです。

=BYCOL(A2:C10, LAMBDA(c, OR(ISNUMBER(c))))
関数向いている判定単位ORの“集約”は?
MAP要素(セル)ごと起きない(スカラーで実行できる)
BYROW行ごとその行の中だけで集約(意図通り)
BYCOL列ごとその列の中だけで集約(意図通り)

「LAMBDAが配列全体の文脈に切り替わらないようにする」ことはできる?

結論から言うと、OR/AND自体の挙動を“要素ごとにする設定”はありません。LAMBDAは“自動でループする関数”ではなく、引数に配列が来たときは、Excel全体の配列計算ルールに従って各関数が動くだけです。

そのため、対処は次のどちらかになります。

  • ORの代替を、配列演算(+や*)で書く(解決策A)
  • MAP/BYROW/BYCOLなどで「1回に扱う単位」を強制的に小さくする(解決策B/C)

「突然の文脈切り替えを止める」というより、“集約される場所”をコントロールすると考えると整理しやすくなります。

ORの代替:実務で使える“安定する書き方”まとめ

要素ごとのORを作りたいときに、最終的に迷わないための実務向けチートシートです。

シーンおすすめ例
LAMBDAに配列を渡して、要素ごとにOR加算式(最短・高速)(ISNUMBER(a)+ISNUMBER(b))>0
ORという関数名で読みやすく保ちたいMAPでスカラー化MAP(a,b,LAMBDA(x,y,OR(ISNUMBER(x),ISNUMBER(y))))
行の中に1つでも該当があればTRUEにしたいBYROW + ORBYROW(A2:D10,LAMBDA(r,OR(r="OK")))
FILTERの条件でOR加算式(定番)FILTER(data,(cond1+cond2)>0)

「危険な関数」を見分けるコツ:配列を渡して“1つに潰れるか”で判断する

今回の混乱は「関数によって配列の扱いが違う」ことが根本原因です。そこで、判断基準をシンプルにします。

配列を渡したときに結果が1つに潰れる関数は“集約系”であり、要素ごとに使いたい場合はそのまま当てると事故りやすい、という覚え方です。

=OR({FALSE,TRUE,FALSE})   → TRUE(1つに潰れる)
=SUM({1,2,3})             → 6(1つに潰れる)
=ISNUMBER({1,"a",3})      → {TRUE,FALSE,TRUE}(要素ごと)
タイプ代表例配列を渡すと…要素ごとにしたい時の対処
集約・集計系OR, AND, SUM, MAX, MIN, COUNT, AVERAGE, TEXTJOIN など1つの値になりやすいMAP/BYROW/BYCOLで単位を区切る、または演算子(+/*)で置き換える
要素ごとに返す系ISNUMBER, LEN, UPPER, SUBSTITUTE, IF(条件次第)など同じ形の配列で返りやすいそのまま使えることが多い
配列を作る/整形する系MAP, BYROW, BYCOL, FILTER, TAKE, DROP, HSTACK, VSTACK などスピルを前提に組める集約系の“安全装置”として包む

迷ったら、{"a";1} のような小さな配列定数を直接渡してみて、結果が1つなら集約系・複数なら要素系、というテストが一番速いです。

よくある落とし穴:ORが原因の“巻き添え”を作らない設計

今回の相談で特に怖いのは、「別要素を変えただけで、関係ない行の結果まで変わる」ことです。これは、判定の最小単位が“行”ではなく“配列全体”になっているサインです。実務では、次のような場所で起きやすいので注意してください。

  • 検証列をスピルで一気に作る:HSTACKで判定列を並べると、スカラーのブロードキャストが目立つ
  • FILTER条件の中でOR/ANDを直接使う:範囲を渡した瞬間に全体集約になり、条件が1つに潰れることがある
  • LAMBDAで“汎用化”した瞬間に配列が引数に入る:セル参照ではなく配列参照になり、関数の配列対応差が表面化する

設計のコツは、「どの単位で判定したいか」を先に決め、その単位に合わせてMAP/BYROWを選ぶことです。要素ごとならMAP、行ごとならBYROW、列ごとならBYCOL。ここが決まると、ORが“危ない”のではなく“使いどころがある”と理解できます。

実務例:入力チェック関数をLAMBDAで作る(巻き添えを防ぐ書き方)

最後に、実務でよくある「A列は数値、B列は任意。どちらかが数値ならOK、両方非数値ならNG」といったチェックを、LAMBDAで関数化する例を示します。

パターン1:加算ORで作る(軽量・安定)

=LAMBDA(a,b,
  (ISNUMBER(a)+ISNUMBER(b))>0
)

これを名前の定義で ISNUM_OR のように登録しておけば、次のように使えます。

=ISNUM_OR(A2:A100, B2:B100)

パターン2:MAPで作る(ORを読みやすく残す)

=LAMBDA(a,b,
  MAP(a,b, LAMBDA(x,y, OR(ISNUMBER(x), ISNUMBER(y))))
)

判定を追加したい場合も、MAP内のORに条件を足すだけで済みます。

=LAMBDA(a,b,
  MAP(a,b, LAMBDA(x,y,
    OR(
      ISNUMBER(x),
      ISNUMBER(y),
      x="",
      y=""
    )
  ))
)

「空白ならOK」など、業務ルールをそのまま書けるので、保守性を優先する現場ではこちらが好まれます。

まとめ:ORが“悪い”のではなく、配列の単位を合わせるのがコツ

  • OR/ANDは配列を受け取ると配列全体を1つに集約する性質がある
  • LAMBDAが原因に見えても、実態はORの設計 + スカラーのブロードキャストで説明できる
  • 要素ごとのORが欲しいなら、加算式((cond1+cond2)>0)が最短で安定
  • ORを残したいなら、MAPでスカラー化してからORを実行する
  • 行/列単位なら、BYROW/BYCOLで“集約の範囲”を意図通りにする

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次