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

半角カタカナを全角化する名前付き関数をループ処理なしで作成しました。

    はじめに

    Googleスプレッドシートの名前付き関数で半角カタカナと一部の記号("。" "「" "」" "、" "・")を全角化する関数を作成しました。

    メイン工程ではループ処理を排し、配列をあれやこれやして実現しています。

    定義式内にMAP関数は出てきますが、これは1セル入力で配列展開に対応させるためのもので、1セルに対する処理についてはループなしです。
    (これって、タイトル詐欺に入りますか…><?)

    さて、今回は大部分AIの力を借りての作成となりました。

    というのも私自身最初はこれを作るつもりがあまりなかったので「自分で考えてみる」からスタートしておらず、最初から最後までAIとのやり取りの中で完成させたためです。

    たまたま他の方が作った半角カタカナ全角化の式を見かけて、それが全角・半角の対応表を式の外側に別途用意して処理するものだったので「文字コードの連番とかを使えば対応表を定義式内に無理なく持っておくことができないかしら…?」と寝る前に軽い気持ちでGeminiに問いかけたところからスタートし、気付いたら3時になっていたという……

    なにはともあれ、以下、定義式です。

    【定義式】
    ※2026/06/02 アップデート (名前付き関数一覧シートをご確認下さい)

    引数:対象

    =LET(
      全角カナ全件, ARRAYFORMULA(UNICHAR(SEQUENCE(86, 1, 12449))),
      半角カナ全件, ARRAYFORMULA(ASC(全角カナ全件)),
    
      抽出条件, ARRAYFORMULA(LEN(半角カナ全件)=1),
      全角カナ, FILTER(全角カナ全件, 抽出条件),
      半角カナ, FILTER(半角カナ全件, 抽出条件),
    
      全角記号, {"。";"「";"」";"、";"・";"ー"},
      半角記号, {"。";"「";"」";"、";"・";"ー"},
      全角リスト, VSTACK(全角記号, 全角カナ),
      半角リスト, VSTACK(半角記号, 半角カナ),
    
      半角コード, ARRAYFORMULA(UNICODE(半角リスト)),
      清音コード, ARRAYFORMULA(UNICODE({"カ";"キ";"ク";"ケ";"コ";"サ";"シ";"ス";"セ";"ソ";"タ";"チ";"ツ";"テ";"ト";"ハ";"ヒ";"フ";"ヘ";"ホ";"ウ"})),
      半清音コード, ARRAYFORMULA(UNICODE({"ハ";"ヒ";"フ";"ヘ";"ホ"})),
    
      濁音, {"ガ";"ギ";"グ";"ゲ";"ゴ";"ザ";"ジ";"ズ";"ゼ";"ゾ";"ダ";"ヂ";"ヅ";"デ";"ド";"バ";"ビ";"ブ";"ベ";"ボ";"ヴ"},
      半濁音, {"パ";"ピ";"プ";"ペ";"ポ"},
    
      処理判定配列, INDEX(IFERROR(REGEXMATCH(TO_TEXT(対象), "[。「」、・ーア-ン゙゚]"), )),
    
      MAP(対象,処理判定配列, LAMBDA(文字列,処理判定, 
       IF(文字列="",,IF(処理判定,
        INDEX(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(現在コード, 半清音コード, 半濁音),
            XLOOKUP(現在コード, 半角コード, 全角リスト, 現在)
           )
          )
         ),
         JOIN("", 変換配列)
        )),
       文字列))
      ))
    )
    

    半角カタカナの全角化で特に厄介になってくるのが以下の仕様です。

    • 濁点・半濁点は1文字扱い(濁音・半濁音は2文字構成)

    • スプレッドシートは「イ」=「ィ」などをTRUEと判定してしまう

    この辺りをどう捌くのかが、作り手の個性が出るところかなと思います。

    それでは、その辺りも踏まえて私とGeminiの合作について以下に解説していきます。

    【解説】

    【全角配列と半角配列の作成】

    =LET(
      全角カナ全件, ARRAYFORMULA(UNICHAR(SEQUENCE(86, 1, 12449))),
      半角カナ全件, ARRAYFORMULA(ASC(全角カナ全件)),

    UNICHARとSEQUENCEで全角カナ全件はやはり作成可能でした。

    具体的な数字についてはさすがAIといったところです。

    半角カナ全件はこれにASCをかけることで一対一で作成できます。

    【濁点・半濁点の除去と記号の追加】

      抽出条件, ARRAYFORMULA(LEN(半角カナ全件)=1),
      全角カナ, FILTER(全角カナ全件, 抽出条件),
      半角カナ, FILTER(半角カナ全件, 抽出条件),
    
      全角記号, {"。";"「";"」";"、";"・";"ー"},
      半角記号, {"。";"「";"」";"、";"・";"ー"},
      全角リスト, VSTACK(全角記号, 全角カナ),
      半角リスト, VSTACK(半角記号, 半角カナ),

    濁音と半濁音は別途処理しますので、全件リストからは排しておきます。
    濁点・半濁点が付くと2文字になりますので、LEN(...)=1で弾くことができます。

    あとは文字コードの連番に含まれていない記号の配列をそれぞれ対応するように作成し、VSTACKして一旦リストの完成です。

    【コード化と置換用全角濁音・半濁音リスト】

      半角コード, ARRAYFORMULA(UNICODE(半角リスト)),
      清音コード, ARRAYFORMULA(UNICODE({"カ";"キ";"ク";"ケ";"コ";"サ";"シ";"ス";"セ";"ソ";"タ";"チ";"ツ";"テ";"ト";"ハ";"ヒ";"フ";"ヘ";"ホ";"ウ"})),
      半清音コード, ARRAYFORMULA(UNICODE({"ハ";"ヒ";"フ";"ヘ";"ホ"})),
    
      濁音, {"ガ";"ギ";"グ";"ゲ";"ゴ";"ザ";"ジ";"ズ";"ゼ";"ゾ";"ダ";"ヂ";"ヅ";"デ";"ド";"バ";"ビ";"ブ";"ベ";"ボ";"ヴ"},
      半濁音, {"パ";"ピ";"プ";"ペ";"ポ"},

    さて、ここで「スプレッドシートが小文字と大文字をTRUE判定してしまう件」についての対策です。
    半角リストをUNICODEでコード化してしまいます…!

    これで検索をコード(数字)で行えるので、完全一致検索ができますね。

    そして、濁音・半濁音の変換のための準備です。
    ここは連番で取れないので、いちいち書くより他にないですね…。

    半角側が濁音・半濁音ではなく、「清音コード」「半清音コード」と清音のリストになっているのがポイントで、SUBSTITUTEやREGEXREPLACEで処理する方法と違うところです。

    【各セルに対する処理の下準備】

    処理判定配列, INDEX(IFERROR(REGEXMATCH(TO_TEXT(対象), "[。「」、・ーア-ン゙゚]"), )),
    
      MAP(対象,処理判定配列, LAMBDA(文字列,処理判定, 
       IF(文字列="",,IF(処理判定,
          INDEX(LET(
            文字数, LEN(文字列),
            連番, SEQUENCE(文字数),
            現在, MID(文字列, 連番, 1),
            次, MID(文字列 & " ", 連番 + 1, 1),
            前, MID(" " & 文字列, 連番, 1),
    
            現在コード, UNICODE(現在),
            前コード, IFERROR(UNICODE(前), 0),

    ※2026/06/02 アップデート部分
    処理判定配列:変換対象のカタカナや記号が含まれているかを判定した「TRUE/FALSEの配列」を作成。
    この配列をMAPに渡し、処理の冒頭でTRUE/FALSEを判定する。
    FALSEの場合変換処理をスキップする。


    前段までは前提となる各リストの準備でした。

    ここから対象となる各セルに対しての処理に入っていきます。

    複数セルへの対応のためMAPを使いますが、冒頭の通りMAPの中ではループ処理は行いません。

    まず、SEQUENCEで対象の文字数分の連番を作成し、これとMID関数を使って1文字ずつに分解した配列を作成します。

    更に、2文字目からの配列(「現在」と同じ座標で「次」の文字になる配列)と、
    一文字目を空白とした配列(「現在」と同じ座標で一文字「前」の文字になる配列)を作成しておきます。

    そして、完全一致検索のために「現在」と「前」についてはコード化しておきます。

    「次」については、半角の濁点・半濁点を見たいだけなので、コード化は不要です。

    【条件式の設定】

            濁音化, (次 = "゙") * ISNUMBER(XMATCH(現在コード, 清音コード)),
            半濁音化, (次 = "゚") * ISNUMBER(XMATCH(現在コード, 半清音コード)),
            不要記号, ((現在 = "゙") * ISNUMBER(XMATCH(前コード, 清音コード))) + 
                     ((現在 = "゚") * ISNUMBER(XMATCH(前コード, 半清音コード))),

    「もし〇〇ならxxする」の「〇〇」の部分を作っていきます。

    • 濁音化:「次」が濁点かつ現在の文字コードが「清音コード」(濁音化する文字コードリスト)に含まれている

    • 半濁音化:「次」が半濁点かつ現在の文字コードが「半清音コード」(ハヒフヘホのコードリスト)に含まれている

    • 不要記号:「現在」が濁点かつ「前」が濁音化するカタカナまたは「現在」が半濁点かつ「前」がハヒフヘホ

    不要記号の部分で濁点・半濁点を問答無用で消してしまわないのは、表現として本来濁音・半濁音化しない文字にわざと濁点・半濁点を付けている場合も想定されるためです。

    【置換処理と結合】

            変換配列, IF(不要記号, "",
              IF(濁音化, XLOOKUP(現在コード, 清音コード, 濁音),
                IF(半濁音化, XLOOKUP(現在コード, 半清音コード, 半濁音),
                  IFNA(XLOOKUP(現在コード, 半角コード, 全角リスト), 現在)
                )
              )
            ),
    
            JOIN("", 変換配列)
          ))
        )
      ))
    )

    いよいよ「〇〇ならxxする」を定義していきます。

    • 「不要記号」なら消す

    • 「濁音化」ならXLOOKUPで現在の文字コードを「清音コード」で探して対応する「濁音」を返す

    • 「半濁音化」ならXLOOKUPで現在の文字コードを「半清音コード」で探して対応する「半濁音」を返す

    • そうでないなら文字コードの完全一致検索で半角カタカナを検索し、対応する全角カタカナに置換、見つからない(半角カタカナではない)なら元の文字のまま!

    これで置換え完了です。

    最後に、JOINで結合して処理完了…!!

    これを各セル分繰り返すことで配列展開に対応します。

    お疲れ様でした><!!

    おわりに

    今回中身はほとんどGeminiに書いてもらった形にはなりますが、最初は濁音・半濁音をREDUCEで処理しようとしていたりと色々違っていました。

    実際のところどちらの処理が良いのかは分かりませんがループ処理は重いというイメージがあり、
    途中で「うーーーん、たとえば、0始まりのSEQUENCEで濁点・半濁点の位置を読めば濁音化・半濁音化するべき文字の位置を特定できるので、その辺りから何とかなりませんか…?」と聞いてみたところ、上の通りの「現在」「次」「前」の三配列処理を出してきてくれました。

    こちらとしては「な、なるほど〜…」となるばかりでしたが、それもこちらから働きかければこそという部分もあり「AIを使う」ということについて何か学びがあったような気がします。

    それでは、ここまで読んで頂きありがとうございました!

     
     

    イネ

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

    あなたへのおすすめ