メインコンテンツへスキップ
見出し画像

【Googleスプレッドシート】「名前付き関数」について〜GASも良いけど関数もね〜

    はじめに

    私、気付きました。

    もしかして「名前付き関数」って、思った以上にマイナーなのかもしれない……と。

    思えば、名前付き関数が

    • スプレッドシートで特に複雑なことをやりたいと思っていない

    • 複雑なことをやるならGASを使う

    この狭間にあると考えるなら、使っている人が少ないとしてもさもありなんと言ったところです。

    更に今だと「少し複雑な関数が必要そうならAIに書いてもらう」という層にも流れてしまっていそうですね…。

    ただ、私としては本来GASと名前付き関数は領分が違っていると思っていますし、AIについても「その場限りの処理」よりむしろ名前付き関数を書いてもらったら良いのではないかと思っています。

    ここではまず
    「なぜ今更名前付き関数なのか〜関数の魅力〜」
    を少しお話しさせて頂いて、
    「まぁ、関数も悪くないかもね。(GASのが凄いけど)」
    くらいの気持ちになってもらってから、
    「名前付き関数とはどういったものか」について説明させて頂こうと思います。

    なぜ今更名前付き関数なのか〜関数の魅力〜

    名前付き関数、ひいては関数の魅力は端的に言うと
    「気軽さ」と「処理速度」にあります。
    (「関数を組むことは単純に楽しい!」は今回はおいておきます…)

    GASは非常に強力ですし「何でもできる」と言って過言ではないほど便利です。

    GASでしか実現し得ないことが山ほどありますし、しかも今ならAIに書いてもらえるので導入のハードルも大幅に下がりました。

    ただ、「関数の代わり」をやらせようとすると上で挙げた「気軽さ」と「処理速度」が課題になってきます。

    例えば…ちょっと極端な例を出してみますが…

    「VLOOKUPをあらかじめ入力しておきたいんだけど、検索値が空白だとエラーが表示されちゃって気持ち悪いんだよね。これがエラーにならないカスタム関数作ってくれない?」
    と頼まれたらまず間違いなく断りますよね?
    「いや、それくらいはIF関数で簡単に処理できますから…」と…
    そこで更に
    「関数を組み合わせるとか難しすぎて分からないし、頼むよ」
    などと言われたとしても、「仕方ないなぁ…」とはならないと思います。
    この程度の処理でももしカスタム関数を使うとしたら一瞬の「読み込み中...」がいちいち挟まってしまいますし、保守性も下がってしまいますので…。
    (そんな人から「カスタム関数」なんて言葉は飛び出してこないでしょという点には目をつぶって下さい)

    これは本当に極端な例ではありましたが、結局のところ「関数で解決できることは関数で処理したほうが速い」わけです。

    そして、LET関数やLAMBDA関数の登場によってシート上の「純粋なデータ処理・計算」という点においては関数でできないことはほぼなくなりました。

    しかも相当に複雑な処理であっても、今ならAIにロジックの構築を助けてもらうことができます。

    「なぜ今更名前付き関数なのか?」
    それは、

    • LET関数やLAMBDA関数によって関数で複雑な処理を解決する土台が整っていること

    •  AIを活用することで、やりたいことを実現する具体的な方法を比較的容易に導き出せること

    が今まさに揃っているからです…!

    今更というよりは、まさに今こそ!という時代なのです!

    良い時代になりましたね!
    (…などと言いながら、私自身はLET関数やLAMBDA関数についてはつい2〜3ヶ月前に知ったばかり、名前付き関数もこの1〜2ヶ月ハマって作っているだけなのですが…。)

    名前付き関数とは

    「『関数の時代!』なんてはしゃいでるけど、いくらAIに書いてもらうと言っても複雑なものは何十行にもわたる数式になって、『気軽さ』とは程遠いものになるのでは?」

    という当然の疑問に対する解答がお察しの通り「名前付き関数」ということになります。

    「名前付き関数とは?」を簡単に説明するために以前部署内の勉強会では以下のような表現を使いました。

    「関数を組み合わせて作成した便利に使える計算式に名前をつけて、一まとまりのパッケージとして登録したもの」と

    今回、こういった記事を読んで下さる方向けにもう少し違った言い回しをGeminiに考えてもらいました。

    「名前付き関数とは…!」

    「複雑な計算ロジックを再利用可能な『コンポーネント(部品)』として切り出し、独自のインターフェース(関数名)を定義したものです。

    ちょっと格好良い…
    こちらで伝わるでしょうか?

    具体例を出します。

    以下は前回(https://note.com/ine_take/n/n2b279fb69b45)紹介させてもらった「半角カタカナを全角化するロジック」です。

    =LET(
      全角カナ全件, ARRAYFORMULA(UNICHAR(SEQUENCE(86, 1, 12449))),
      半角カナ全件, ARRAYFORMULA(ASC(全角カナ全件)),
      
      抽出条件, ARRAYFORMULA(LEN(半角カナ全件)=1),
      全角カナ, FILTER(全角カナ全件, 抽出条件),
      半角カナ, FILTER(半角カナ全件, 抽出条件),
    
      全角記号, {"。";"「";"」";"、";"・";"ー"},
      半角記号, {"。";"「";"」";"、";"・";"ー"},
      全角リスト, VSTACK(全角記号, 全角カナ),
      半角リスト, VSTACK(半角記号, 半角カナ),
    
      半角コード, ARRAYFORMULA(UNICODE(半角リスト)),
      清音コード, ARRAYFORMULA(UNICODE({"カ";"キ";"ク";"ケ";"コ";"サ";"シ";"ス";"セ";"ソ";"タ";"チ";"ツ";"テ";"ト";"ハ";"ヒ";"フ";"ヘ";"ホ";"ウ"})),
      半清音コード, ARRAYFORMULA(UNICODE({"ハ";"ヒ";"フ";"ヘ";"ホ"})),
    
      濁音, {"ガ";"ギ";"グ";"ゲ";"ゴ";"ザ";"ジ";"ズ";"ゼ";"ゾ";"ダ";"ヂ";"ヅ";"デ";"ド";"バ";"ビ";"ブ";"ベ";"ボ";"ヴ"},
      半濁音, {"パ";"ピ";"プ";"ペ";"ポ"},
    
      MAP(対象, LAMBDA(文字列, 
        IF(文字列="", "",
          ARRAYFORMULA(LET(
            文字数, LEN(文字列),
            連番, SEQUENCE(文字数),
            現在, MID(文字列, 連番, 1),
            次, MID(文字列 & " ", 連番 + 1, 1),
            前, MID(" " & 文字列, 連番, 1),
    
            現在コード, UNICODE(現在),
            前コード, IFERROR(UNICODE(前), 0),
    
            濁音化, (次 = "゙") * ISNUMBER(XMATCH(現在コード, 清音コード)),
            半濁音化, (次 = "゚") * ISNUMBER(XMATCH(現在コード, 半清音コード)),
            不要記号, ((現在 = "゙") * ISNUMBER(XMATCH(前コード, 清音コード))) + 
                     ((現在 = "゚") * ISNUMBER(XMATCH(前コード, 半清音コード))),
    
    
            変換配列, IF(不要記号, "",
              IF(濁音化, XLOOKUP(現在コード, 清音コード, 濁音),
                IF(半濁音化, XLOOKUP(現在コード, 半清音コード, 半濁音),
                  IFNA(XLOOKUP(現在コード, 半角コード, 全角リスト), 現在)
                )
              )
            ),
    
            JOIN("", 変換配列)
          ))
        )
      ))
    )
    

    私はこれに「L_Z_KANA」という名前を付けました。

    そうすると、実際にセル上で使用する際は以下のようになります。

    =L_Z_KANA(A2:A)

    \スッキリ!/

    大変スッキリして良い感じですね。
    このように扱えるのであればとても「気軽」です。

    画像
    Gemini製サンプルに対して半角→全角処理

    まあ「セル上での書き方」という意味ではカスタム関数も同じ形になるのでここに差はないのですが……その中身がスプレッドシートネイティブの関数であるという点は大きな差異になります。

    つまり、拡張機能であるGASは処理のたびにGoogleのサーバーとの通信が必要であるのに対して、名前付き関数はスプレッドシート内で全ての処理が完結するものであるということです。

    「気軽」ですね!

    名前付き関数の作り方(登録方法)

    では具体的にどのように作るのかを説明していきます。

    L_Z_KANAの定義式は長大すぎるので、ここでは以下の式を例に進めてみます。

    =IF(検索値="","",VLOOKUP(検索値,範囲,指数,0))

    はい。
    カスタム関数では「それはさすがに…」という感じだったこちらも、名前付き関数であれば環境によっては作成するのも全然アリです。

    これを登録してみましょう。

    • ​​Step 1: メニューの [データ] > [名前付き関数] を選択

    画像
    •  Step 2: 「新しい関数の追加」をクリック

    画像
    • Step 3: 「関数名」「引数のプレースホルダ」「定義式」を入力

    画像

      「関数名」は大文字限定・記号は「_」のみなどいくらかの制約はありますが、既に使用されている名前以外であれば基本的に自由に決めることができます。

    ここでは「空白(NULL)なら空白(NULL)を返すVLOOKUP」ですので、「NULL_NULL_VLOOK」とでもしておきましょうか。
    ぬるぬるぶいるっく。

    …と言いたいところですが、少し長いですし、それともう一点命名では気を付けたいポイントもあります。

    それは一般関数と一目で区別できるように頭に決まった文字列を付けるというもので、絶対の決まりではありませんが慣習というものですね。

    一般的には"Function"や"My Function"の"FN_"や"MY_"などを付けることが多いようです。

    私は"Library","Local","Lambda"等の頭文字から"L_"を採用しています。

    そんな訳で、頭にL_を付けつつもう少し短く…
    「L_N_VLOOK」くらいで良いかなと思います。
    (もちろんNULL_NULLでも登録はできます)

    「引数のプレースホルダ」には日本語を設定することができますが、「数式の定義」の欄に直接日本語を入力しようとすると変換がなかなか上手くいきません…。

    画像
    直接入力しようとすると変なことに…

    少し面倒ですが、別のところで書いてコピペすれば大丈夫です。

    また、実際に入力されている式をそのまま「数式の定義」欄にコピペすると、セルや範囲の参照が「引数の候補」として抜き出されるので、ここから引数名を決めることもできます。(この入力欄は問題なく日本語入力できます)

    画像
    セルや範囲の参照以外は「引数の候補」にならないことに注意

    「次へ」と進むと補足情報として引数の説明を記載することができます。
    ここをしっかり書いておくと使う時にサジェストが出てきて公式関数のような使い心地になります。

    画像
    VLOOKUPの「数式のヘルプ」を参考に入力…

    「作成」を押せば完成です。

    =L_N_VLOOK(検索値,範囲,指数)
    画像
    名前等はGemini製サンプルデータです

    これで「あらかじめ入力しておいても検索値の空白に対してエラーを吐かず、かつ使い心地はほぼVLOOKUPな上、"何のために入力しているのか分からない最後の0"(と思われがち)の入力まで省略される」…という、例のあの人もにっこりな形になりました。

    他のシートで使うには

    作成した名前付き関数を別のシートで使用するには、名前付き関数を使いたいシート上で「インポート」する必要があります。

    • Step 1: メニューの [データ] > [名前付き関数] を選択

    画像
    • Step 2: 「関数をインポート」をクリック

    画像
    • ​Step 3: インポート元のファイルを選択し「挿入」をクリック

    画像
    「検索」や「最近使用したアイテム」から探して選択
    •  Step 4: 「すべてインポート」をクリック(特定の名前付き関数のみをインポートする場合はチェックボックスで選択して「インポート」をクリック)

    画像
    基本的には「すべてインポート」で全てインポートしましょう

    自身の名前付き関数を管理するマスタのようなファイルを1つ作っておけば、ここからどこでも迷わず全ての名前付き関数をインポートできます。

    また、このインポートは閲覧権限さえあれば可能ですので、チームで共通の「関数ライブラリ用シート」を作って閲覧権限を配っておけば、「組織標準の関数」を全員が手軽に呼び出せるようになります。

    おわりに

    ここまで読んで頂きありがとうございました。

    上手く説明できたでしょうか…。
    少しでも「名前付き関数も良いね」というふうに思って頂けたら嬉しいです。

    なお、GASのカスタム関数と比較する形で「関数は処理速度が速い」という書き方をしましたが、そうは言っても複雑な処理で非効率的な書き方をするとさすがに重くなります。
    ですので、名前付き関数でも「美しく効率的な書き方」は非常に大事です。

    それを考えるのがパズルみたいで楽しいのですよね。

    そういった議論といいますか、意見交換ができたら良いなと思いながらここで記事を書いています。

    ご意見・ご感想を頂けると嬉しく思います。
    (お手柔らかにお願いできればとは思いますが…)

     
     

    イネ

     
     
    しがないバックオフィス系社員。 Googleスプレッドシートで関数を書き名前付き関数を作りながらどうにか生存しています。

    あなたへのおすすめ