論文・子育て・ご飯のハック

多忙な社会人・大学院生のためのGoogle Apps Script (GAS) 活用術:Gmail・スプレッドシート連携で日常タスクを自動化する具体的なハック

Tags: GAS, 自動化, 効率化, スプレッドシート, Gmail

はじめに

社会人として働きながら大学院で学ぶ日々は、膨大なタスクと限られた時間との戦いです。研究、授業、仕事、そして家事。これらのバランスを取りながら成果を出すためには、一つひとつの作業を効率化し、自動化できる部分はテクノロジーに任せることが極めて重要になります。特に、デジタルツールを活用した効率化は、多忙な社会人大学院生にとって強力な味方となります。

本記事では、Googleが提供するローコードプラットフォームであるGoogle Apps Script(GAS)に焦点を当てます。GASは、Gmail、Googleスプレッドシート、GoogleドキュメントなどのGoogle Workspaceサービスを連携させ、自動化や機能拡張を実現するためのスクリプト言語です。特別な開発環境は不要で、ウェブブラウザ上でコードを記述し実行できます。PCスキルが高い方であれば、基本的なコーディング知識があれば十分に活用を始められます。

ここでは、GASを活用して日常の煩雑なタスクを自動化し、家事や勉強の時間を確保するための具体的なハックを、Gmailとスプレッドシートの連携を中心にご紹介します。これらのハックを取り入れることで、定型的な作業から解放され、より創造的で重要なタスクに集中できるようになることを目指します。

Google Apps Script(GAS)とは何か、なぜ社会人大学院生に向いているのか

Google Apps Script(GAS)は、JavaScriptをベースとしたスクリプト言語です。Googleアカウントがあれば誰でも利用でき、追加のソフトウェアインストールは不要です。ブラウザ上でスクリプトエディタを開き、コードを記述して実行します。

GASが多忙な社会人大学院生に向いている主な理由は以下の通りです。

これにより、普段手作業で行っているルーチンワークをGASに任せることで、貴重な時間を節約し、研究や勉強、あるいは休息に充てることが可能になります。

具体的なGAS活用ハック例:Gmail・スプレッドシート連携による自動化

ここでは、Gmailとスプレッドシートを連携させた、社会人大学院生に役立つ具体的な自動化ハックを3つご紹介します。

ハック1:特定の条件を満たすGmailをスプレッドシートに自動記録する

学費の領収書、オンライン講座の受講確認メール、研究関連のニュースレターなど、後で参照したい特定のメールを自動的にリスト化したい場合があります。手作業でメールを検索し、情報をコピー&ペーストするのは非常に手間がかかります。GASを使えば、これを自動化できます。

実現できること:

具体的な手順とコード例:

  1. 記録用のスプレッドシートを用意: Googleスプレッドシートで新しいシートを作成します。1行目に列見出し(例: 受信日時, 差出人, 件名, 本文抜粋, メールURL)を入力しておきます。このスプレッドシートのURLまたはIDを控えておきます。
  2. GASエディタを開く: スプレッドシートのメニューバーから「拡張機能」>「Apps Script」を選択し、スクリプトエディタを開きます。
  3. スクリプトを記述: 以下のコード例を参考に、スプレッドシートIDや検索条件を書き換えて記述します。
function recordSpecificEmails() {
  // === 設定項目 ===
  const spreadsheetId = 'ここにスプレッドシートのIDを入力'; // スプレッドシートのURLから取得できます
  const sheetName = 'シート1'; // 記録したいシート名
  const searchKeyword = 'subject:"領収書" from:("@example.com")'; // Gmailの検索クエリ例
  const labelNameToProcess = '記録済み'; // 処理済みのメールに付けるラベル名 (任意)
  const processThresholdHours = 24; // 何時間前までのメールを処理対象とするか (例: 24時間以内)

  // スプレッドシートとシートを取得
  const ss = SpreadsheetApp.getActiveSpreadsheet() || SpreadsheetApp.openById(spreadsheetId);
  const sheet = ss.getSheetByName(sheetName);

  if (!sheet) {
    Logger.log('指定されたシートが見つかりません: ' + sheetName);
    return;
  }

  // 最終実行日時をプロパティサービスから取得、なければ現在時刻
  const scriptProperties = PropertiesService.getScriptProperties();
  let lastRunTime = scriptProperties.getProperty('lastRunTime');
  let query = searchKeyword;

  if (lastRunTime) {
    const lastRunDate = new Date(parseInt(lastRunTime, 10));
    const timeLimit = new Date(Date.now() - processThresholdHours * 60 * 60 * 1000); // 指定時間前
    // 最終実行時刻以降、かつ指定時間以内のメールを対象にするクエリを追加
    query += ' after:' + Utilities.formatDate(lastRunDate, Session.getScriptTimeZone(), 'yyyy/MM/dd HH:mm') +
             ' before:' + Utilities.formatDate(new Date(), Session.getScriptTimeZone(), 'yyyy/MM/dd HH:mm');
    Logger.log('検索クエリ: ' + query);
  } else {
     // 初回実行時は指定時間前までのメールを対象とする
     const timeLimit = new Date(Date.now() - processThresholdHours * 60 * 60 * 1000);
     query += ' after:' + Utilities.formatDate(timeLimit, Session.getScriptTimeZone(), 'yyyy/MM/dd HH:mm');
     Logger.log('初回検索クエリ (指定時間前): ' + query);
  }


  // Gmailからメールを検索
  const threads = GmailApp.search(query, 0, 100); // 最大100件取得

  if (threads.length === 0) {
    Logger.log('新しいメールは見つかりませんでした。');
    // 最終実行日時を現在時刻で更新
    scriptProperties.setProperty('lastRunTime', new Date().getTime().toString());
    return;
  }

  const dataToAppend = [];
  const processedThreads = [];

  threads.forEach(function(thread) {
    const messages = thread.getMessages();
    messages.forEach(function(message) {
       // スレッド内の最新メッセージのみを処理するなど、必要に応じて条件を追加
       // ここではシンプルに各メッセージを処理対象とする
       const receivedTime = message.getDate();
       const from = message.getFrom();
       const subject = message.getSubject();
       const body = message.getPlainBody();
       const emailUrl = 'https://mail.google.com/mail/u/0/#inbox/' + thread.getId(); // メールへのリンク生成

       // 本文の最初の100文字を取得 (HTMLタグは除去)
       const bodySnippet = body ? body.replace(/<[^>]*>?/gm, '').substring(0, 100) + (body.length > 100 ? '...' : '') : '';

       dataToAppend.push([receivedTime, from, subject, bodySnippet, emailUrl]);
    });
    processedThreads.push(thread);
  });

  // スプレッドシートにデータを追加
  if (dataToAppend.length > 0) {
    sheet.getRange(sheet.getLastRow() + 1, 1, dataToAppend.length, dataToAppend[0].length).setValues(dataToAppend);
    Logger.log(dataToAppend.length + ' 件のメール情報をスプレッドシートに追加しました。');

    // 処理済みのラベルを付ける (任意)
    if (labelNameToProcess) {
        let label = GmailApp.getUserLabelByName(labelNameToProcess);
        if (!label) {
            label = GmailApp.createLabel(labelNameToProcess);
        }
        GmailApp.moveThreadsToInbox(processedThreads); // 一旦受信トレイに戻さないとラベルを付けられない場合がある
        label.addToThreads(processedThreads);
         Logger.log(processedThreads.length + ' 件のスレッドにラベル "' + labelNameToProcess + '" を付けました。');
    }

  } else {
     Logger.log('追加するデータはありませんでした。');
  }

  // 最終実行日時を現在時刻で更新
  scriptProperties.setProperty('lastRunTime', new Date().getTime().toString());
}
  1. トリガーを設定: スクリプトエディタの左側メニュー(時計アイコン)からトリガー設定を開き、「トリガーを追加」ボタンをクリックします。実行したい頻度(例: 1時間ごと、1日1回)に合わせて時間主導型トリガーを設定します。関数名としてrecordSpecificEmailsを選択することを忘れないでください。
  2. 権限を承認: 初回実行時やトリガー設定時に、GASがGmailやスプレッドシートにアクセスするための権限承認を求められます。内容を確認し、承認してください。

これで、設定した頻度でスクリプトが自動実行され、条件に合うメール情報がスプレッドシートに蓄積されていきます。検索クエリを工夫することで、様々な種類の情報を自動収集できます。

ハック2:スプレッドシートのデータに基づき、指定日時にリマインダーメールを自動送信する

研究の締め切り、論文投稿のデッドライン、タスクの期日、あるいは家族の記念日など、忘れてはならない重要な日付をスプレッドシートで管理している場合、その情報を元に自動でリマインダーメールを受け取れると便利です。

実現できること:

具体的な手順とコード例:

  1. リマインダー用スプレッドシートを用意: 期日、タスク内容、メール送信済みフラグなどの列を持つシートを作成します。
  2. GASエディタを開き、スクリプトを記述: 以下のコード例を参考に、スプレッドシートIDや列番号、リマインダー条件を書き換えて記述します。
function sendDeadlineReminders() {
  // === 設定項目 ===
  const spreadsheetId = 'ここにスプレッドシートのIDを入力'; // スプレッドシートのID
  const sheetName = 'リマインダー'; // リマインダー情報を持つシート名
  const dateColumn = 1; // 期日が含まれる列番号 (A列が1, B列が2...)
  const taskColumn = 2; // タスク内容が含まれる列番号
  const sentFlagColumn = 3; // 送信済みフラグを設定する列番号
  const reminderDaysBefore = 3; // 期日の何日前にリマインドするか
  const emailSubject = '【リマインダー】期日が近づいています'; // 送信するメールの件名
  const recipientEmail = Session.getActiveUser().getEmail(); // 送信先メールアドレス (自分自身)

  const ss = SpreadsheetApp.getActiveSpreadsheet() || SpreadsheetApp.openById(spreadsheetId);
  const sheet = ss.getSheetByName(sheetName);

  if (!sheet) {
    Logger.log('指定されたシートが見つかりません: ' + sheetName);
    return;
  }

  const data = sheet.getDataRange().getValues();
  // ヘッダー行を除外する場合
  const header = data.shift(); // ヘッダー行を削除し、残りを処理対象とする

  const today = new Date();
  today.setHours(0, 0, 0, 0); // 日付比較のために時間をゼロにする

  const remindersToSend = [];
  const rowsToUpdate = []; // 送信済みフラグを設定する行番号のリスト

  data.forEach(function(row, index) {
    const deadline = row[dateColumn - 1]; // 列番号は0から始まるため -1
    const task = row[taskColumn - 1];
    const sentFlag = row[sentFlagColumn - 1];

    // 期日が有効な日付であり、かつまだ送信済みでない場合
    if (deadline instanceof Date && task && sentFlag !== '送信済み') {
      const diffTime = deadline.getTime() - today.getTime();
      const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));

      // 期日が reminderDaysBefore 日以内、または本日、または既に過ぎている場合
      if (diffDays <= reminderDaysBefore) {
        remindersToSend.push({
          task: task,
          deadline: Utilities.formatDate(deadline, Session.getScriptTimeZone(), 'yyyy/MM/dd')
        });
        // 送信済みフラグを立てる対象の元の行番号 (ヘッダーを削除したので +2 を加える)
        rowsToUpdate.push(index + 2);
      }
    }
  });

  if (remindersToSend.length > 0) {
    let emailBody = '以下のタスクの期日が近づいています、あるいは過ぎています。\n\n';
    remindersToSend.forEach(function(item) {
      emailBody += '- ' + item.task + ' (期日: ' + item.deadline + ')\n';
    });
    emailBody += '\nスプレッドシートを確認してください。';

    GmailApp.sendEmail(recipientEmail, emailSubject, emailBody);
    Logger.log(remindersToSend.length + ' 件のリマインダーメールを送信しました。');

    // 送信済みフラグをスプレッドシートに書き込む
    rowsToUpdate.forEach(function(rowNumber) {
        sheet.getRange(rowNumber, sentFlagColumn).setValue('送信済み');
    });
     Logger.log(rowsToUpdate.length + ' 件のタスクに送信済みフラグを立てました。');

  } else {
    Logger.log('送信するリマインダーはありませんでした。');
  }
}
  1. トリガーを設定: 毎日決まった時間に実行される時間主導型トリガーを設定します。関数名としてsendDeadlineRemindersを選択します。
  2. 権限を承認: Gmailとスプレッドシートへのアクセス権限を承認します。

このスクリプトにより、スプレッドシートを更新するだけで、期日が近づいたタスクについて自動でリマインダーを受け取れるようになります。送信済みフラグを立てることで、何度も同じリマインダーが送られることを防いでいます。

ハック3:Googleフォームの回答を処理し、自動応答メールを送信する

共同研究者からの情報収集、イベント参加登録、簡単なアンケートなど、Googleフォームを利用する機会があるかもしれません。フォーム送信後、回答内容に基づいて確認メールを送ったり、特定の処理を行ったりする作業もGASで自動化できます。

実現できること:

具体的な手順とコード例:

  1. Googleフォームと連携したスプレッドシートを用意: Googleフォームを作成し、「回答」タブから「スプレッドシートにリンク」を選択して、回答が自動的に記録されるスプレッドシートを作成します。
  2. GASエディタを開き、スクリプトを記述: 以下のコード例を参考に、スプレッドシートIDや送信するメールの内容を記述します。
function onFormSubmit(e) {
  // この関数はGoogleフォームの「フォーム送信時」トリガーで実行されます。
  // 引数eにはフォーム送信に関する情報が含まれます。

  // === 設定項目 ===
  const spreadsheetId = 'ここにフォームの回答が記録されるスプレッドシートのIDを入力';
  const sheetName = 'フォームの回答 1'; // フォームの回答が記録されるシート名 (通常はこれ)
  const recipientEmailColumn = 2; // 回答者のメールアドレスが含まれる列番号 (A列が1) - フォーム設定でメール収集する場合
  const subjectColumn = 3; // 回答内容の一部を件名に使用する場合の列番号例
  const bodyColumn = 4; // 回答内容の一部を本文に使用する場合の列番号例

  // スプレッドシートとシートを取得
  const ss = SpreadsheetApp.getActiveSpreadsheet() || SpreadsheetApp.openById(spreadsheetId);
  const sheet = ss.getSheetByName(sheetName);

  if (!sheet) {
    Logger.log('指定されたシートが見つかりません: ' + sheetName);
    return;
  }

  // フォーム送信によって追加された行の情報を取得
  // e.rangeはフォーム送信によってデータが追加された範囲を示します
  const row = e.range.getRowIndex(); // データが追加された行番号
  const values = e.range.getValues()[0]; // 追加された行のデータ (配列として取得)

  // 回答者のメールアドレスを取得 (フォーム設定でメールアドレスを収集している場合)
  // emailAddressColumn - 1 は配列のインデックス
  const recipientEmail = values[recipientEmailColumn - 1];

  // 送信するメールの件名と本文を作成
  const emailSubject = '【回答ありがとうございます】フォームへのご入力内容について';
  let emailBody = 'この度はフォームへのご回答ありがとうございました。\n\n';
  emailBody += 'ご入力いただいた内容は以下の通りです。\n\n';

  // 回答内容をメール本文に追加 (例: 全ての項目をリストアップ)
  const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0]; // ヘッダー行を取得
  values.forEach(function(value, index) {
    // タイムスタンプ列など、メールに含めたくない列はスキップするなどの調整が可能
    if (headers[index]) { // ヘッダーがある項目のみ処理
       emailBody += headers[index] + ': ' + value + '\n';
    }
  });

  emailBody += '\n内容をご確認ください。';

  // メールを送信
  if (recipientEmail) {
     GmailApp.sendEmail(recipientEmail, emailSubject, emailBody);
     Logger.log('回答者 ' + recipientEmail + ' 宛に確認メールを送信しました。');
  } else {
     Logger.log('回答者のメールアドレスが取得できませんでした。');
  }

  // フォーム送信後の追加処理をここに追加することも可能
  // 例: スプレッドシートの特定セルにフラグを立てる、カレンダーに予定を追加するなど
}
  1. トリガーを設定: スクリプトエディタの左側メニュー(時計アイコン)からトリガー設定を開き、「トリガーを追加」ボタンをクリックします。「イベントのソース」として「スプレッドシートから」、「イベントの種類」として「フォーム送信時」を選択します。関数名としてonFormSubmitを選択します。
  2. 権限を承認: Gmailとスプレッドシートへのアクセス権限を承認します。

これにより、フォームが送信されるたびに自動的に確認メールが送信されるようになります。回答内容の処理や、回答者への個別対応が必要な場合に、大幅な時間短縮につながります。

GAS活用のヒントと注意点

まとめ

本記事では、多忙な社会人大学院生がGoogle Apps Script(GAS)を活用し、Gmailとスプレッドシートを連携させて日常タスクを自動化する具体的なハックをご紹介しました。特定のメールの自動記録、期日リマインダーの自動送信、Googleフォームへの自動応答といった処理をGASに任せることで、これまで手作業にかけていた時間を削減し、研究や勉強により集中できる時間を確保できます。

GASはローコードで記述でき、Google Workspaceとの連携が容易であるため、PCスキルが高い方であれば比較的短時間で習得し、実践に投入することが可能です。今回ご紹介したハックはあくまで一例です。ご自身の置かれた状況や繰り返しの多いタスクに合わせてスクリプトをカスタマイズしたり、他のGoogleサービス(カレンダー、ドライブなど)や外部サービスとの連携に挑戦したりすることで、さらなる効率化を実現できる可能性を秘めています。

日々の小さな自動化が積み重なることで、多忙な中でも時間を創出し、研究成果を高め、充実した大学院生活を送る一助となることを願っております。