Excel の LAMBDA 関数を使ってユーザー定義関数を作成する

# はじめに

Excel に [LAMBDA 関数](https://support.microsoft.com/ja-jp/office/LAMBDA-%E9%96%A2%E6%95%B0-bd212d27-1cd1-4321-a34a-ccbf254b8b67) が実装されたことで、これまで VBA を利用しないとできなかったユーザー定義関数が Excel の式だけで作成することができるようになりました。
今回はブラウザーのユーザーエージェントを解析して OS やブラウザーを判別する例を元に確認していきます。

# LAMBDA 関数を使った OS の判断

[LAMBDA 関数](https://support.microsoft.com/ja-jp/office/LAMBDA-%E9%96%A2%E6%95%B0-bd212d27-1cd1-4321-a34a-ccbf254b8b67) は引数のリストと、実行する式を指定するちょっと特殊な関数になっています。
![Lambda関数の構造](https://support.content.office.net/ja-jp/media/627806f0-40f4-4a27-86d1-4ef77a86331c.png)

今回は A 列に記載された下記のようなユーザーエージェントの文字列をもとに解析を行います。

```text:ユーザーエージェントのサンプル
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36 Edg/98.0.1108.56
Mozilla/5.0 (iPhone; CPU iPhone OS 14_8_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Mobile/15E148 Safari/604.1
Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko
Mozilla/5.0 (Linux; Android 11; SO-41B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.101 Mobile Safari/537.36
```

例えば、B1 セルに次のように定義すると、対象の OS が何であるかを判断できます。
関数を定義した後、サイトに A1 セルを引数に関数を即時に実行しています。

```text:B1の式
=LAMBDA(ua,
        IF(NOT(ISERROR(SEARCH("iPad",ua,1))),    "iOS",
        IF(NOT(ISERROR(SEARCH("iPhone",ua,1))),  "iOS",
        IF(NOT(ISERROR(SEARCH("Android",ua,1))), "Android",
        IF(NOT(ISERROR(SEARCH("Windows",ua,1))), "Windows",
        "Other")
 ))))(A1)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/3b3e677e-a264-a16e-4db2-3165e1384539.png)

# ユーザー定義関数の作成

このままだと LAMBDA にしているうま味があまりないので、ユーザー定義関数にしていきます。
Excel のメニューからたどる場合は、`数式 > 名前の管理` から、ショートカットを利用する場合は `Ctrl+F3` から名前の管理ダイアログを表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/a55d0b1e-a72f-727f-63b8-0108dcb9661d.png)

新規作成から、新しい名前ダイアログを開き次のように入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/e5d73434-52f2-242b-288c-2f0752bec75b.png)

| 項目     | 値                |
| -------- | ----------------- |
| 名前     | OS を判断する関数 |
| 範囲     | ブック            |
| コメント |                   |
| 参照範囲 | ↓           |

```text:OSを判断する関数の定義
=LAMBDA(ua,
        IF(NOT(ISERROR(SEARCH("iPad",ua,1))),    "iOS",
        IF(NOT(ISERROR(SEARCH("iPhone",ua,1))),  "iOS",
        IF(NOT(ISERROR(SEARCH("Android",ua,1))), "Android",
        IF(NOT(ISERROR(SEARCH("Windows",ua,1))), "Windows",
        "Other")
 ))))
```

ユーザー定義関数が登録できたら、B1 の式を次のように書き換えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/e1db3a37-e388-827f-8168-a85ec049e09b.png)

```text:変更後のB1の式
=OSを判断する関数(A1)
```

同様に、ブラウザーを判断する関数も次のように定義します。

| 項目     | 値                       |
| -------- | ------------------------ |
| 名前     | ブラウザーを判断する関数 |
| 範囲     | ブック                   |
| コメント |                          |
| 参照範囲 | ↓                  |

```text:ブラウザーを判断する関数の定義
=LAMBDA(ua,
        IF(NOT(ISERROR(SEARCH("Edge",ua,1))),    "Edge",
        IF(NOT(ISERROR(SEARCH("Edg",ua,1))),     "Edge",
        IF(NOT(ISERROR(SEARCH("Chrome",ua,1))),  "Chrome",
        IF(NOT(ISERROR(SEARCH("Safari",ua,1))),  "Safari",
        IF(NOT(ISERROR(SEARCH("Trident",ua,1))), "IE",
        "Other")
 )))))
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36535/28153c65-8990-1ee5-3484-cc700769bcbd.png)

ブラウザーの種類を追加したくなったら、ユーザー定義関数の定義を次のように変えれば関数を呼び出しているすべての箇所に反映されます。

```text:ブラウザーを判断する関数の定義 変更後
=LAMBDA(ua,
        IF(NOT(ISERROR(SEARCH("Edge",ua,1))),    "Edge",
        IF(NOT(ISERROR(SEARCH("Edg",ua,1))),     "Edge",
        IF(NOT(ISERROR(SEARCH("Chrome",ua,1))),  "Chrome",
        IF(NOT(ISERROR(SEARCH("Safari",ua,1))),  "Safari",
        IF(NOT(ISERROR(SEARCH("Trident",ua,1))), "IE",
        IF(NOT(ISERROR(SEARCH("Firefox",ua,1))), "Firefox",
        "Other")
 ))))))
```

かっ、カッコの対応を取るのが難しいですね...
流れるようなインターフェイスで関数が定義できるようになれば良いのに。

# おわりに

今までも全てのセルに同じ式をコピーすれば同じような事は出来ましたが、変更があった場合などはすべてのセルの式を変更する必要がありましたし、複雑な式を定義しようとした場合には繰り返し同じ式を記述する必要がありました。
LAMBDA 関数を VBA を利用せずにユーザー定義関数を簡単に定義できるので、ブック内の式を効率よく管理できるようになりましたね。