GASで呪術廻戦のキャラクターからメッセージが送られる、自動メール送信スクリプトを作ってみた。

## はじめに
 今週、知り合いの方からスプレッドシートで選択した行のみ自動でメール送信するスクリプトを作成してみて欲しいと依頼がありました。そこで初めてGAS(Google Apps Script)を使用したので、その中で学んだことを書いていきたいと思います。

 ## GASとは？
 Google Apps Scriptの略です。Googleが提供する様々なサービス（スプレッドシート、カレンダー等）で扱うことができて、自動化や機能の拡張を行うことができます。
 
 javascriptベースで作られているので、独自の関数等ありますが、書き方としてはほぼ同じように書くことができます。（違ってたらすみません）
 イメージとしてはサーバ上で動くjajavascriptといったところでしょうか。
  javascriptは最近学んでいる言語だったので、学んだことを活かしたり、復習にもなり楽しく作成できました。
 

 詳しくは公式ページを見てください。

 https://developers.google.com/apps-script?hl=ja

 ## 呪術廻戦キャラ自動メール送信スクリプトを作ってみよう！
 頼まれて作成したものとしては、チェックボックスにチェックを入れた行の宛先、名前、等の情報からそれぞれのメール本文を作成、送信するというものでした。流石にそれを載せることはできないので今回学んだこと、使った機能を取り入れて好きなアニメでもある「呪術回線キャラ自動メール送信スクリプト」という需要０のスクリプトを作りました。笑

 ## 完成品
 #### 送信したい人にチェックを入れる
 ![スクリーンショット 2024-01-21 12.19.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301763/3378ff05-cd5a-edd0-6e14-8379d45c8daf.png)
 
 #### 実行する（正常に送信されるとアラートが表示される）
 ![スクリーンショット 2024-01-21 12.19.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301763/8021b9e8-e5c2-1c31-fcca-8ada81b76f0a.png)

 #### （失敗するとエラーのアラートが表示される）
 ![スクリーンショット 2024-01-21 12.20.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301763/9940a803-2cfb-efd8-1ab1-ad14f2c312a0.png)

#### 送信結果
![IMG_3474.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301763/3138cbcb-9e15-1401-3a15-37f08ebd380c.jpeg)
![IMG_3473.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3301763/21e276a2-8d97-4e8b-90b7-eed138d1e46d.jpeg)

 
 ## ソースコード
 ```javascript
 function sendMail() {
  try {
    // アクティブなシートの取得
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
    const data = sheet.getDataRange().getValues();

    // データをループしてメールを送信
    data.forEach((row, index) => {
      if (index > 0 && row[2] === true) { // ヘッダ行を除外し、チェックされた行のみ処理
        const recipient = row[0]; // 宛先
        const name = row[1]; // 名前
        // ランダムで呪術廻戦キャラクターのメッセージを作成
        const messageBody = JujutsuKaisenMessageSet(name);

        // メール送信
        GmailApp.sendEmail(recipient, `${name}さんへ`, messageBody);
      }
    });

    // 処理完了のアラート表示
    showCompletionAlert();

  } catch (e) {
    // スクリプト実行中のエラーハンドリング
    scriptErrorMessage(e);
  }
}

// 受け取った名前から呪術キャラのメッセージをランダムで生成
function JujutsuKaisenMessageSet(name) {
  const characters = ["虎杖悠仁", "伏黒恵", "釘崎野薔薇", "五条悟", "東堂", "伏黒甚爾"];
  const messages = {
    "虎杖悠仁": "よろしくおなしゃす！",
    "伏黒恵": "いまとてもイラッとしました。",
    "釘崎野薔薇": `${name}寝不足か？毛穴開いてんぞ`,
    "五条悟": "大丈夫、僕最強だから",
    "東堂": `起きろ、${name}、俺たちの戦いはこれからだ！`,
    "伏黒甚爾": `${name}は俺が殺した`
  };
  const character = characters[Math.floor(Math.random() * characters.length)];
  return messages[character];
}

// スクリプト実行失敗時の例外処理の関数
function scriptErrorMessage(error) {
  Logger.log('スクリプトの実行中にエラーが発生しました: ' + error.message); // エラーログの記録
  SpreadsheetApp.getUi().alert('スクリプトの実行中にエラーが発生しました: ' + error.message); // ユーザーへの通知
}

// 正常処理時にアラートを表示する関数
function showCompletionAlert() {
  const ui = SpreadsheetApp.getUi();
  ui.alert('スクリプトの処理が正常に完了しました。');
}

 ```

 ## 解説

 #### シートのデータ取得
 ```javascript
// アクティブなシートの取得
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
const data = sheet.getDataRange().getValues();
 ```
 まず初めの二行ではGASの４つの関数を使用してスプレッドシートの情報を取得しております。

 ```
 SpreadsheetApp
 ```
 こちらはGASのクラスの１つでこちらを通じてスプレッドの情報を操作したり、取得したりできます。
 `getActiveSpreadsheet`　スプレッドの全体のシートを取得
 `getActiveSheet`現在選択しているシートを取得
 `getDataRange` シートのセル内でデータが入力されているものを取得
 `getValues` データが入力されているものを２次元配列にして返す

 この一連の流れでシート内の情報を取得し、かつ２次元配列にしてあげることでプログラム内で扱えるようにしています。


### チェックボックスの判定、シートから情報をセット
```javascript
   // データをループしてメールを送信
   data.forEach((row, index) => {
     if (index > 0 && row[2] === true) { // ヘッダ行を除外し、チェックされた行のみ処理
       const recipient = row[0]; // 宛先
       const name = row[1]; // 名前
       // ランダムで呪術廻戦キャラクターのメッセージを作成
       const messageBody = JujutsuKaisenMessageSet(name);

       // メール送信
       GmailApp.sendEmail(recipient, `${name}さんへ`, messageBody);
     }
   });
```


先ほど２次元配列にしたシートデータをforEachでループします。
２次元配列なのでrowが行で配列内のインデックスが列(column)を表します。

`index > o` 0より大きくしているのは、一行目は、見出しの行なので判定する必要がないからです。
row[2]というのがスプレッドシートの３列目ということですね。配列のindexは0から始まるので初学者の方はこちらの点に注意してください。
なのでこちらのifの条件は
2行目以降かつ３列目のチェックボックスがtrue(チェックされている）いる場合にメールを送信するということになっております。

```javascript
const recipient = row[0]; // 宛先
const name = row[1]; // 名前
```
こちらで変数を定義し、シートの記入されている宛先、名前をセットします。

```
// メール送信
GmailApp.sendEmail(recipient, `${name}さんへ`, messageBody);
```
実際にメール送信をしているのはこちらですね。
GmailAppクラスのsendEmailメソッドを使用します。
引数に渡す項目の順番が決まっている点に注意してください。具体的には以下の通りになってます。
第1引数 (recipient): メールの宛先。メールアドレスを文字列で指定。
第2引数 (subject): メールの件名。文字列で指定。
第3引数 (body): メールの本文。文字列で指定。
第4引数 (options): オプション（任意）。メールの追加オプションを指定。例えば、添付ファイル、Bcc、Cc、など指定できます。
ちなみに送信もとは自動的に自身が現在ログインしているアカウントのアドレスになります。

詳しくは下記のドキュメントを参照してもらえばと思います。

https://developers.google.com/apps-script/reference/gmail/gmail-app?hl=ja

そしてこのnameを引数に渡してランダムの文章を生成するメソッドを実行します。
それがこちら

```javascript
// 受け取った名前から呪術キャラのメッセージをランダムで生成
function JujutsuKaisenMessageSet(name) {
 const characters = ["虎杖悠仁", "伏黒恵", "釘崎野薔薇", "五条悟", "東堂", "伏黒甚爾", "東堂葵"];
 const messages = {
   "虎杖悠仁": "よろしくおなしゃす！",
   "伏黒恵": "いまとてもイラッとしました。",
   "釘崎野薔薇": `${name}寝不足か？毛穴開いてんぞ`,
   "五条悟": "大丈夫、僕最強だから",
   "東堂葵": `起きろ、${name}、俺たちの戦いはこれからだ！`,
   "伏黒甚爾": `${name}は俺が殺した`
 };
 const character = characters[Math.floor(Math.random() * characters.length)];
 return messages[character];
}
```
単純にcharactersという配列にそれぞれのキャラの名前を入れる。
そしてmessagesオブジェクトを作成し、keyにキャラ名、valueにキャラごとのメッセージを設定しています。

const character = characters[Math.floor(Math.random() * characters.length)];
 return messages[character];
 Math.randomで生成された値を配列の最大値でかけることでキャラ名がランダムで出力され、そのキャラ名をkeyにメッセージを取得しています。

 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/random

 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/floor

 ### エラー処理、正常終了時のアラート
 最小限にしてます。
 全体をtryでcatchで囲んでアラート表示とログだけ吐き出すようにしています。
 ```javascript
 // スクリプト実行失敗時の例外処理の関数
function scriptErrorMessage(error) {
 Logger.log('スクリプトの実行中にエラーが発生しました: ' + error.message); // エラーログの記録
 SpreadsheetApp.getUi().alert('スクリプトの実行中にエラーが発生しました: ' + error.message); // ユーザーへの通知
}

// 正常処理時にアラートを表示する関数
function showCompletionAlert() {
 const ui = SpreadsheetApp.getUi();
 ui.alert('スクリプトの処理が正常に完了しました。');
 ```

 今のままだと、メール送信されたのが０件であっても、正常終了となるので、1件以上だった場合という判定を入れる必要もありそうですね。


 ### まとめ
 以上GASを使って自動メール送信スクリプト作成でした。

 GASは簡単な機能であれば、このように少ない行数で書くことができて、できたことも実感しやすいので、初学者がプログラミングの楽しさを経験する入り口としても良いなと感じました。
 複雑な機能となると、難しくなっていくとは思いますが・・・
 私自身も、配列、key、valueでの取得、Math系のメソッドなど基本的な構文を復習したり、理解を深めることができたのでとても良かったと感じました！