自分を活かして 相手を活かして 今を活かす

【GAS】カタカナ表記をパスポートでも使えるヘボン式ローマ字に変換するスクリプト

こんにちは、おかちゃんせんせいです!

これまで番外編として、業務効率化のために作業を自動化する話を何回かピックアップしました。

【解決】Excel 2019 for MacのVBAにて、複数ファイルを選択する方法 【業務効率化】Windows版Excel VBAでChromeを自動操作して、Webスクレイピングする方法(初期設定編) 【解決】Power AutomateでExcel Onlineにある日付と実行日が一致する場合に、処理を実行するようにする

もちろん自動化すればいいってものでもないですが、自動化することでミスや作業時間を減らし、他に生産的な仕事に時間を割くことができるようになることもあります。

自動化という意味では、プログラムを組まなくてもGoogleスプレッドシートの関数だけで、なんとかやりくりする方法もあります。

今回は、Googleスプレッドシートでマクロを組む際に使用する開発言語Google Apps Script(GAS)についての記事を特集します。

◆お知らせ◆

【まとめ記事】

現在、これまで書いてきた記事をテーマ別にまとめています。

詳しくはこちらから

GASで実現したい作業

メールアドレス作成の際に必要となるアカウント名

今回GASで実現したいことは、
メールアドレス作成の際に必要となるアカウント名を、特定のデータがあれば自動作成すること
です。

本当はそれ以外にもやりたいことはありますが、まずは上述の部分であれば一定のルールのもとで自動化できると考えました。

今のところは、フリガナを見てローマ字に変換して、メールアドレスのアカウント名にしていましたが……

ローマ字で表現するときに、
「H」なのか「F」なのか?
「N」なのか「M」なのか?
「Z」なのか「J」なのか?
よくわからなくなってしまうことがあるので、そんなときには下記サイトにかなり助けられました。

ただ、毎回サイト開いてコピペするのも面倒だし、同じ作業の繰り返し、かつ、一定のルールがあるから自動化できないかと思い、ネットを検索。

カタカナではないですが、GASでローマ字変換するスクリプトが公開されているサイトがありましたので、参考にさせていただきました。

問題は『ヘボン式』になっていないこと

ただ、スクリプトでひらがなの部分をカタカナに変えて、
「はい、終わり!」
というわけにはいかなかったのです。

なぜかというと、参考サイトで紹介されているスクリプトはあくまで訓令式ローマ字に変換するものであって、ヘボン式ではないから。
社内ではアカウント名をヘボン式で表記するルールがあったため、そのままでは使えません。

ちなみに、ヘボン式とはパスポートなどにも使えるローマ字表記で、たとえば下記のような例外ルールがあります。

※その他、個別・例外ルール
①「 ん 」 ・・・ 「 N 」に変換。ただし、「 NB 」・「 NM 」・「 NP 」となる場合は「 N→M 」で表記。
  (例: かんだ→KANDA 、 なんば→NAMBA 、 へんみ→HEMMI 、 らんぽ→RAMPO)
②「 っ 」 ・・・ 後に続く子音を重ねる。ただし、「 CH 」が続く場合は「 TCH 」となる。
  (例: べっぷ→BEPPU 、 こっち→KOTCHI )
③長音について ・・・ 母音の重なりを1文字で表記します。「 おお = OH 」表現も可能なようですが、任意表記のようなので変換君では考慮していません。
  (例: とおる→TORU 、 おおにし→ONISHI )

ヘボン式変換君サイトより引用

他にも微妙に違う表記方法の文字があるので、そういったことは下記サイトを確認しながら編集することに決めました。

サンプルコード

自分が考えたコードではないので、詳しい説明は割愛しますが、、、

要は、まず変換したい文字列(string)を受け取って、splitで分割。該当するカタカナの組み合わせが見つかったら(3文字→2文字→1文字)、紐付けたローマ字で変換していく流れ。

基本的な流れは、すべて参考サイトからの引用になりますが、カタカナの組み合わせはヘボン式用に追加・修正しています。

GAS
 /**
 * フリガナをヘボン式ローマ字に変換
 *
 * @param {string} input - カタカナ
 * @return {string} ローマ字
 */
 function kana2romaji(string) {

    var arrayedString = string.split('');
    var value = '';

    var triTable = {
        'ギュウ' : 'gyu','ジュウ' : 'ju','ビュウ' : 'byu','ヂッウ' : 'dyu','ピュウ' : 'pyu',
        'キョウ' : 'kyo','ショウ' : 'sho','チョウ' : 'cho',
        'ニョウ' : 'nyo','ヒョウ' : 'hyo','ミョウ' : 'myo','リョウ' : 'ryo',
        'ギョウ' : 'gyo','ジョウ' : 'jo','ヂョウ' : 'dyo','ビョウ' : 'byo','ピョウ' : 'pyo',
        'ウ゛ァ': 'va','ウ゛ィ' : 'vi', 'ウ゛ゥ' : 'vu','ウ゛ェ' : 've', 'ウ゛ォ' : 'vo'
    };

    var biTable = {
        'ギャ' : 'gya','ギュ' : 'gyu','ギョ' : 'gyo',
        'シャ' : 'sha','シュ' : 'shu','ショ' : 'sho',
        'クウ' : 'ku','スウ' : 'su','ツウ' : 'tsu','ヌウ' : 'nu',
        'フウ' : 'fu','ムウ' : 'mu','ユウ' : 'yu','ルウ' : 'ru',
        'オオ' : 'o','コオ' : 'ko','ソオ' : 'so','トオ' : 'to','ノオ' : 'no',
        'ホオ' : 'ho','モオ' : 'mo','ヨオ' : 'yo','ロオ' : 'ro',
        'コウ' : 'ko','ソウ' : 'so','トウ' : 'to','ノウ' : 'no',
        'ホウ' : 'ho','モウ' : 'mo','ヨウ' : 'yo','ロウ' : 'ro',
        'ゴウ' : 'go','ドウ' : 'do','ボウ' : 'bo','ポウ' : 'po',
        'ジェ' : 'jie','チェ' : 'chie','ティ' : 'tei','ディ' : 'dei','デュ' : 'deyu',
        'ファ' : 'fua','フィ' : 'fui','フェ' : 'fue','フォ' : 'fuo',
        'ヴァ' : 'bua','ヴィ' : 'bui','ヴ' : 'bu','ヴェ' : 'bue','ヴォ' : 'buo',
        'ンバ' : 'mba','ンビ' : 'mbi','ンブ' : 'mbu','ンベ' : 'mbe','ンボ' : 'mbo',
        'ンマ' : 'mma','ンミ' : 'mmi','ンム' : 'mmu','ンメ' : 'mme','ンモ' : 'mmo',
        'ンラ' : 'mra','ンリ' : 'mri','ンル' : 'mru','ンレ' : 'mre','ンロ' : 'mro',        
        'キャ' : 'kya','キュ' : 'kyu','キョ' : 'kyo',
        'ジャ' : 'ja','ジュ' : 'ju','ジョ' : 'jo',
        'チャ' : 'cha','チュ' : 'chu','チョ' : 'cho',
        'ヂャ' : 'dya','ヂュ' : 'dyu','ヂョ' : 'dyo',
        'デャ' : 'dha','デョ' : 'dho',
        'ニャ' : 'nya','ニュ' : 'nyu','ニョ' : 'nyo',
        'ヒャ' : 'hya','ヒュ' : 'hyu','ヒョ' : 'hyo',
        'ビャ' : 'bya','ビュ' : 'byu','ビョ' : 'byo',
        'ピャ' : 'pya','ピュ' : 'pyu','ピョ' : 'pyo',
        'ミャ' : 'mya','ミュ' : 'myu','ミョ' : 'myo',
        'リャ' : 'rya','リュ' : 'ryu','リョ' : 'ryo',
        'テァ' : 'tha','テェ' : 'tee',
        'ウ゛' : 'vu','ア゛' : 'a"',
        'ッカ' : 'kka','ッキ' : 'kki','ック' : 'kku','ッケ' : 'kke','ッコ' : 'kko',
        'ッサ' : 'ssa','ッシ' : 'sshi','ッス' : 'ssu','ッセ' : 'sse','ッソ' : 'sso',
        'ッタ' : 'tta','ッチ' : 'tchi','ッツ' : 'ttu','ッテ' : 'tte','ット' : 'tto',
        'ッナ' : 'nna','ッニ' : 'nni','ッヌ' : 'nnu','ッネ' : 'nne','ッノ' : 'nno',
        'ッハ' : 'hha','ッヒ' : 'hhi','ッフ' : 'ffu','ッヘ' : 'hhe','ッホ' : 'hho',
        'ッマ' : 'mma','ッミ' : 'mmi','ッム' : 'mmu','ッメ' : 'mme','ッモ' : 'mmo',
        'ッヤ' : 'yya', 'ッユ' : 'yyu','ッヨ' : 'yyo',
        'ッラ' : 'rra','ッリ' : 'rri','ッル' : 'rru','ッレ' : 'rre','ッロ' : 'rro',
        'ッワ' : 'wwa',
        'ッガ' : 'gga','ッギ' : 'ggi','ッグ' : 'ggu','ッゲ' : 'gge','ッゴ' : 'ggo',
        'ッザ' : 'zza','ッジ' : 'jji','ッズ' : 'zzu','ッゼ' : 'zze','ッゾ' : 'zzo',
        'ッダ' : 'dda','ッヂ' : 'ddi','ッヅ' : 'ddu','ッデ' : 'dde','ッド' : 'ddo',
        'ッバ' : 'bba','ッビ' : 'bbi','ッブ' : 'bbu','ッベ' : 'bbe','ッボ' : 'bbo',
        'ッパ' : 'ppa','ッピ' : 'ppi','ップ' : 'ppu','ッペ' : 'ppe','ッポ' : 'ppo'
    };

    var uniTable = {
        'ア' : 'a','イ' : 'i','ウ' : 'u','エ' : 'e','オ' : 'o',
        'カ' : 'ka','キ' : 'ki','ク' : 'ku','ケ' : 'ke','コ' : 'ko',
        'サ' : 'sa','シ' : 'shi','ス' : 'su','セ' : 'se','ソ' : 'so',
        'タ' : 'ta','チ' : 'chi','ツ' : 'tsu','テ' : 'te','ト' : 'to',
        'ナ' : 'na','ニ' : 'ni','ヌ' : 'nu','ネ' : 'ne','ノ' : 'no',
        'ハ' : 'ha','ヒ' : 'hi','フ' : 'fu','ヘ' : 'he','ホ' : 'ho',
        'マ' : 'ma','ミ' : 'mi','ム' : 'mu','メ' : 'me','モ' : 'mo',
        'ヤ' : 'ya','ユ' : 'yu','ヨ' : 'yo',
        'ラ' : 'ra','リ' : 'ri','ル' : 'ru','レ' : 're','ロ' : 'ro',
        'ワ' : 'wa','ヲ' : 'wo','ン' : 'n',
        'ガ' : 'ga','ギ' : 'gi','グ' : 'gu','ゲ' : 'ge','ゴ' : 'go',
        'ザ' : 'za','ジ' : 'ji','ズ' : 'zu','ゼ' : 'ze','ゾ' : 'zo',
        'ダ' : 'da','ヂ' : 'ji','ヅ' : 'zu','デ' : 'de','ド' : 'do',
        'バ' : 'ba','ビ' : 'bi','ブ' : 'bu','ベ' : 'be','ボ' : 'bo',
        'パ' : 'pa','ピ' : 'pi','プ' : 'pu','ペ' : 'pe','ポ' : 'po',
        'ァ' : 'xa','ィ' : 'xi','ゥ' : 'xu','ェ' : 'xe','ォ' : 'xo'
    };

    if(triTable[string] !== undefined){
        return triTable[string];
    } else if(biTable[string] !== undefined) {
        return biTable[string];
    }

    var biCheck = new Object();
    for (var k in biTable){
        var tmp = k.split('');
        biCheck[tmp[0]] = true;
    }

    var triCheck = new Object();
    for (var tk in triTable){
        var tmp = tk.split('');
        triCheck[tmp[0] + tmp[1]] = true;
        biCheck[tmp[0]] = true; 
    }


    var buf = '';
    for(var i = 0; i < arrayedString.length ; i++){
        var str = arrayedString[i];
        buf += str;
        if(buf.length === 3){
            if(triTable[buf] !== undefined){
                value += triTable[buf];
            } else {
                tmp = buf.split('');
                value += biTable[tmp[0] + tmp[1]];
                value += uniTable[tmp[2]] === undefined ? tmp[2] : uniTable[tmp[2]]
            }
            buf = '';
        } else if(buf.length === 2) {
            if(triCheck[buf] !== undefined) { 
            } else if(biTable[buf] !== undefined) {
                    value += biTable[buf];
                    buf = '';
            } else {
                    tmp = buf.split('');
                    value += uniTable[tmp[0]]; 
                    if(uniTable[tmp[1]] !== undefined){
                      value += uniTable[tmp[1]] === undefined ? tmp[1] : uniTable[tmp[1]]; 
                      buf = '';                    
                    }else{
                      buf = ''; 
                      buf += tmp[1];
                    }
            }
        } else if(i === arrayedString.length -1){
                value += uniTable[str];
                buf = '';
        } else if(biCheck[buf] !== undefined){
        } else { 
                value += uniTable[str] === undefined ? str : uniTable[str];
                buf = '';
        }
    }

    // 母音のoとuが続く場合はuを打ち消すように修正(2024/01/25追記)
    if(value.indexOf('ou') !== -1){
      value = value.replace('ou','o');
    }

    return value;
}

(2022/09/27追記)
テストサンプルをいくつか試していましたら、子音が続く場合(例:テッタ)に正常に動作しないことが判明しました。
修正内容は、下記2箇所です。

・uniTableからャ・ュ・ョ・ッを除外
・buf.length == 2の場合に子音が続くケースを追加条件分岐


(2023/05/31追記)
・文字数の判定で最後が3文字の場合に、bufに値が残ってしまう不具合を解消


(2024/01/25追記)
・クドウの場合、kudouになってしまう不具合を解消


(2024/06/03追記)
・スバラシイの場合、suundefinedrashiiになってしまう不具合を解消
⇒「ば」がunderfinedになっていたので修正


(2024/11/14追記)
・最後の一文字がローマ字変換されない不具合を修正

改良版サンプルコード

※追記(2024年09月10日)※
2024年9月時点で質問してくださった方の内容を反映させるために、
引数がカタカナでもひらがなでもどちらの場合でも最終的にローマ字に変換する関数を作成しました。

追加した関数はこちらのconvertCharacters関数です。

GAS
 /**
 * カタカナ⇔ひらがなに変換する関数
 *
 * @param {string} input - カタカナ or ひらがな
 * @param {string} kind - 変換したい入力文字種(カタカナ:0、ひらがな:1)
 * @return {string} カタカナ→ひらがな or ひらがな→カタカナ
 */
function convertCharacters (input,kind) {
  if(input == null) return "";
  
  // ひらがな、カタカナの一覧を文字列として取得する
  // ※文字位置はそれぞれ対応している(例:あ(2番目)⇔ア(2番目))
  const hiragana = "ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろわをんゎゐゑゕゖ";
  const katakana = "ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロワヲンヮヰヱヵヶ";

  // デフォルト:変換前(ひらがな)、変換後(カタカナ)
  let before = hiragana;
  let after = katakana;
  const charArr = input.split('');
  // 入力文字にひらがなが含まれておらず、かつ、入力文字がひらがなの場合
  // 変換前をカタカナ、変換後をひらがなとする
  if(hiragana.indexOf(charArr[0]) === -1 && kind === 1){
    before = katakana;
    after = hiragana;
  // 入力文字にひらがなが含まれておらず、かつ、入力文字がカタカナ
  // または、入力文字にひらがなが含まれておらず、かつ、入力文字がひらがなの場合
  // 特に変換する必要はないため入力文字を返す
  }else if(hiragana.indexOf(charArr[0]) === -1 && kind === 0
         || hiragana.indexOf(charArr[0]) !== -1 && kind === 1){
    return input;
  }
  console.log(input);

  // 入力した文字を一文字ずつ取り出して変換する
  const afterText = charArr.map(function(char) {
                      var index = before.indexOf(char);
                      return index >= 0 ? after[index] : char;
                    }).join('');
  console.log(afterText);

  return afterText;
}

そして、完成形が下記になります。
カタカナ・ひらがな、どちらのバージョンでも対応したい場合には下記コードを活用してください。

GAS
 /**
 * フリガナをヘボン式ローマ字に変換
 *
 * @param {string} input - カタカナ
 * @return {string} ローマ字
 */
 function kana2romaji(string) {

    var arrayedString = string.split('');
    var value = '';

    var triTable = {
        'ギュウ' : 'gyu','ジュウ' : 'ju','ビュウ' : 'byu','ヂッウ' : 'dyu','ピュウ' : 'pyu',
        'キョウ' : 'kyo','ショウ' : 'sho','チョウ' : 'cho',
        'ニョウ' : 'nyo','ヒョウ' : 'hyo','ミョウ' : 'myo','リョウ' : 'ryo',
        'ギョウ' : 'gyo','ジョウ' : 'jo','ヂョウ' : 'dyo','ビョウ' : 'byo','ピョウ' : 'pyo',
        'ウ゛ァ': 'va','ウ゛ィ' : 'vi', 'ウ゛ゥ' : 'vu','ウ゛ェ' : 've', 'ウ゛ォ' : 'vo'
    };

    var biTable = {
        'ギャ' : 'gya','ギュ' : 'gyu','ギョ' : 'gyo',
        'シャ' : 'sha','シュ' : 'shu','ショ' : 'sho',
        'クウ' : 'ku','スウ' : 'su','ツウ' : 'tsu','ヌウ' : 'nu',
        'フウ' : 'fu','ムウ' : 'mu','ユウ' : 'yu','ルウ' : 'ru',
        'オオ' : 'o','コオ' : 'ko','ソオ' : 'so','トオ' : 'to','ノオ' : 'no',
        'ホオ' : 'ho','モオ' : 'mo','ヨオ' : 'yo','ロオ' : 'ro',
        'コウ' : 'ko','ソウ' : 'so','トウ' : 'to','ノウ' : 'no',
        'ホウ' : 'ho','モウ' : 'mo','ヨウ' : 'yo','ロウ' : 'ro',
        'ゴウ' : 'go','ドウ' : 'do','ボウ' : 'bo','ポウ' : 'po',
        'ジェ' : 'jie','チェ' : 'chie','ティ' : 'tei','ディ' : 'dei','デュ' : 'deyu',
        'ファ' : 'fua','フィ' : 'fui','フェ' : 'fue','フォ' : 'fuo',
        'ヴァ' : 'bua','ヴィ' : 'bui','ヴ' : 'bu','ヴェ' : 'bue','ヴォ' : 'buo',
        'ンバ' : 'mba','ンビ' : 'mbi','ンブ' : 'mbu','ンベ' : 'mbe','ンボ' : 'mbo',
        'ンマ' : 'mma','ンミ' : 'mmi','ンム' : 'mmu','ンメ' : 'mme','ンモ' : 'mmo',
        'ンラ' : 'mra','ンリ' : 'mri','ンル' : 'mru','ンレ' : 'mre','ンロ' : 'mro',        
        'キャ' : 'kya','キュ' : 'kyu','キョ' : 'kyo',
        'ジャ' : 'ja','ジュ' : 'ju','ジョ' : 'jo',
        'チャ' : 'cha','チュ' : 'chu','チョ' : 'cho',
        'ヂャ' : 'dya','ヂュ' : 'dyu','ヂョ' : 'dyo',
        'デャ' : 'dha','デョ' : 'dho',
        'ニャ' : 'nya','ニュ' : 'nyu','ニョ' : 'nyo',
        'ヒャ' : 'hya','ヒュ' : 'hyu','ヒョ' : 'hyo',
        'ビャ' : 'bya','ビュ' : 'byu','ビョ' : 'byo',
        'ピャ' : 'pya','ピュ' : 'pyu','ピョ' : 'pyo',
        'ミャ' : 'mya','ミュ' : 'myu','ミョ' : 'myo',
        'リャ' : 'rya','リュ' : 'ryu','リョ' : 'ryo',
        'テァ' : 'tha','テェ' : 'tee',
        'ウ゛' : 'vu','ア゛' : 'a"',
        'ッカ' : 'kka','ッキ' : 'kki','ック' : 'kku','ッケ' : 'kke','ッコ' : 'kko',
        'ッサ' : 'ssa','ッシ' : 'sshi','ッス' : 'ssu','ッセ' : 'sse','ッソ' : 'sso',
        'ッタ' : 'tta','ッチ' : 'tchi','ッツ' : 'ttu','ッテ' : 'tte','ット' : 'tto',
        'ッナ' : 'nna','ッニ' : 'nni','ッヌ' : 'nnu','ッネ' : 'nne','ッノ' : 'nno',
        'ッハ' : 'hha','ッヒ' : 'hhi','ッフ' : 'ffu','ッヘ' : 'hhe','ッホ' : 'hho',
        'ッマ' : 'mma','ッミ' : 'mmi','ッム' : 'mmu','ッメ' : 'mme','ッモ' : 'mmo',
        'ッヤ' : 'yya', 'ッユ' : 'yyu','ッヨ' : 'yyo',
        'ッラ' : 'rra','ッリ' : 'rri','ッル' : 'rru','ッレ' : 'rre','ッロ' : 'rro',
        'ッワ' : 'wwa',
        'ッガ' : 'gga','ッギ' : 'ggi','ッグ' : 'ggu','ッゲ' : 'gge','ッゴ' : 'ggo',
        'ッザ' : 'zza','ッジ' : 'jji','ッズ' : 'zzu','ッゼ' : 'zze','ッゾ' : 'zzo',
        'ッダ' : 'dda','ッヂ' : 'ddi','ッヅ' : 'ddu','ッデ' : 'dde','ッド' : 'ddo',
        'ッバ' : 'bba','ッビ' : 'bbi','ッブ' : 'bbu','ッベ' : 'bbe','ッボ' : 'bbo',
        'ッパ' : 'ppa','ッピ' : 'ppi','ップ' : 'ppu','ッペ' : 'ppe','ッポ' : 'ppo'
    };

    var uniTable = {
        'ア' : 'a','イ' : 'i','ウ' : 'u','エ' : 'e','オ' : 'o',
        'カ' : 'ka','キ' : 'ki','ク' : 'ku','ケ' : 'ke','コ' : 'ko',
        'サ' : 'sa','シ' : 'shi','ス' : 'su','セ' : 'se','ソ' : 'so',
        'タ' : 'ta','チ' : 'chi','ツ' : 'tsu','テ' : 'te','ト' : 'to',
        'ナ' : 'na','ニ' : 'ni','ヌ' : 'nu','ネ' : 'ne','ノ' : 'no',
        'ハ' : 'ha','ヒ' : 'hi','フ' : 'fu','ヘ' : 'he','ホ' : 'ho',
        'マ' : 'ma','ミ' : 'mi','ム' : 'mu','メ' : 'me','モ' : 'mo',
        'ヤ' : 'ya','ユ' : 'yu','ヨ' : 'yo',
        'ラ' : 'ra','リ' : 'ri','ル' : 'ru','レ' : 're','ロ' : 'ro',
        'ワ' : 'wa','ヲ' : 'wo','ン' : 'n',
        'ガ' : 'ga','ギ' : 'gi','グ' : 'gu','ゲ' : 'ge','ゴ' : 'go',
        'ザ' : 'za','ジ' : 'ji','ズ' : 'zu','ゼ' : 'ze','ゾ' : 'zo',
        'ダ' : 'da','ヂ' : 'ji','ヅ' : 'zu','デ' : 'de','ド' : 'do',
        'バ' : 'ba','ビ' : 'bi','ブ' : 'bu','ベ' : 'be','ボ' : 'bo',
        'パ' : 'pa','ピ' : 'pi','プ' : 'pu','ペ' : 'pe','ポ' : 'po',
        'ァ' : 'xa','ィ' : 'xi','ゥ' : 'xu','ェ' : 'xe','ォ' : 'xo'
    };

    if(triTable[string] !== undefined){
        return triTable[string];
    } else if(biTable[string] !== undefined) {
        return biTable[string];
    }

    var biCheck = new Object();
    for (var k in biTable){
        var tmp = k.split('');
        biCheck[tmp[0]] = true;
    }

    var triCheck = new Object();
    for (var tk in triTable){
        var tmp = tk.split('');
        triCheck[tmp[0] + tmp[1]] = true;
        biCheck[tmp[0]] = true; 
    }


    var buf = '';
    for(var i = 0; i < arrayedString.length ; i++){
        var str = arrayedString[i];
        buf += str;
        if(buf.length === 3){
            if(triTable[buf] !== undefined){
                value += triTable[buf];
            } else {
                tmp = buf.split('');
                value += biTable[tmp[0] + tmp[1]];
                value += uniTable[tmp[2]] === undefined ? tmp[2] : uniTable[tmp[2]]
            }
            buf = '';
        } else if(buf.length === 2) {
            if(triCheck[buf] !== undefined) { 
            } else if(biTable[buf] !== undefined) {
                    value += biTable[buf];
                    buf = '';
            } else {
                    tmp = buf.split('');
                    value += uniTable[tmp[0]]; 
                    if(uniTable[tmp[1]] !== undefined){
                      value += uniTable[tmp[1]] === undefined ? tmp[1] : uniTable[tmp[1]]; 
                      buf = '';                    
                    }else{
                      buf = ''; 
                      buf += tmp[1];
                    }
            }
        } else if(i === arrayedString.length -1){
                value += uniTable[str];
                buf = '';
        } else if(biCheck[buf] !== undefined){
        } else { 
                value += uniTable[str] === undefined ? str : uniTable[str];
                buf = '';
        }
    }

    // 母音のoとuが続く場合はuを打ち消すように修正(2024/01/25追記)
    if(value.indexOf('ou') !== -1){
      value = value.replace('ou','o');
    }

    return value;
}
 
 
 /**
 * カタカナ⇔ひらがなに変換する関数
 *
 * @param {string} input - カタカナ or ひらがな
 * @param {string} kind - 変換したい入力文字種(カタカナ:0、ひらがな:1)
 * @return {string} カタカナ→ひらがな or ひらがな→カタカナ
 */
function convertCharacters (input,kind) {
  if(input == null) return "";
  
  // ひらがな、カタカナの一覧を文字列として取得する
  // ※文字位置はそれぞれ対応している(例:あ(2番目)⇔ア(2番目))
  const hiragana = "ぁあぃいぅうぇえぉおかがきぎくぐけげこごさざしじすずせぜそぞただちぢっつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもゃやゅゆょよらりるれろわをんゎゐゑゕゖ";
  const katakana = "ァアィイゥウェエォオカガキギクグケゲコゴサザシジスズセゼソゾタダチヂッツヅテデトドナニヌネノハバパヒビピフブプヘベペホボポマミムメモャヤュユョヨラリルレロワヲンヮヰヱヵヶ";

  // デフォルト:変換前(ひらがな)、変換後(カタカナ)
  let before = hiragana;
  let after = katakana;
  const charArr = input.split('');
  // 入力文字にひらがなが含まれておらず、かつ、入力文字がひらがなの場合
  // 変換前をカタカナ、変換後をひらがなとする
  if(hiragana.indexOf(charArr[0]) === -1 && kind === 1){
    before = katakana;
    after = hiragana;
  // 入力文字にひらがなが含まれておらず、かつ、入力文字がカタカナ
  // または、入力文字にひらがなが含まれておらず、かつ、入力文字がひらがなの場合
  // 特に変換する必要はないため入力文字を返す
  }else if(hiragana.indexOf(charArr[0]) === -1 && kind === 0
         || hiragana.indexOf(charArr[0]) !== -1 && kind === 1){
    return input;
  }
  console.log(input);

  // 入力した文字を一文字ずつ取り出して変換する
  const afterText = charArr.map(function(char) {
                      var index = before.indexOf(char);
                      return index >= 0 ? after[index] : char;
                    }).join('');
  console.log(afterText);

  return afterText;
}


(2024/09/10追記)
・引数がひらがなでもカタカナでもどちらの場合でも対応できるバージョンを作成

まとめ

まだコードが出来上がったばかりで十分検証ができていませんので、もし不備がありましたらご指摘いただけますと幸いです!


最後まで読んでいただき、ありがとうございました!

14 COMMENTS

ぽんすけ

「くどう」が「kudou」になってしまっております。
調整いただけると助かります。

返信する
みそに

スバラシイ→suundefinedrashiiとなってしまいます。
調整していただけると幸いです。

返信する
hiro

初めまして

拡張機能からスクリプトをコピーして保存。
その後、実行してみるとエラーで、
TypeError: Cannot read properties of undefined (reading ‘split’)
と出てしまいます。
これは何が原因なのでしょうか。

返信する
おかちゃんせんせい

hiro様
はじめまして。
おそらくkana2romaji関数をそのまま実行されたのではないでしょうか。
kana2romajiには引数stringに文字列を渡してあげる必要があります。

hiro様がカナからローマ字に変換したい文字列をkana2romajiに渡してみていただければと思います。

下記が活用例になります。
function main(){
const kana = “ヤマダタロウ”;
const romaji = kana2romaji(kana);
console.log(romaji);
}

返信する
hiro

早々のお返事ありがとうございます。
全くの素人なのですが、スプレッドシート内でセル内のひらがなをローマ字に変換する関数ができないかなと模索しております。

セル内に関数で特定のセルのひらがなをローマ字にすることはできないのでしょうか?

返信する
おかちゃんせんせい
  • セル内に関数で特定のセルのひらがなをローマ字にすることはできないのでしょうか?
  • そちらの内容と、本日更新した記事の内容を基にすれば実現可能です。
    https://hajimarinomachi.com/gas-spreedsheet-function/

    また、ご質問いただいた内容を反映させるため、
    先ほどひらがなでもカタカナでも対応できるバージョンを公開しました。

    合わせてご確認ください。

    返信する
    hiro

    早々のお返事ありがとうございます。
    全くの素人なのですが、スプレッドシート内でセル内のひらがなをローマ字に変換する関数ができないかなと模索しております。

    セル内に関数で特定のセルのひらがなをローマ字にすることはできないのでしょうか?

    返信する
    n

    お世話になります。
    以下のキーワードがうまく表示されず困ってしまっております。ご相談可能でございますでしょうか。

    ヤハギ = yaha(gi がでない)
    オオハシ = oha(shi がでない)
    カヨ = ka(yo がでない)

    返信する
    おかちゃんせんせい

    お世話になります。

    不具合のご指摘ありがとございます。
    ご指摘いただいた内容について、修正いたしました。

    現在のスクリプトで再度検証をよろしくお願いいたします。

    返信する
    n

    反映を確認できました、、!
    早急にご対応いただきましてありがとうございました。

    返信する

    コメントを残す

    メールアドレスが公開されることはありません。 が付いている欄は必須項目です

    CAPTCHA