7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ニジボックスAdvent Calendar 2021

Day 20

作業の記録をとりたくて・・・GAS

Last updated at Posted at 2021-12-22

#はじめに
上手にスケジュールを立てるにはまず自分がどの作業にどれくらい時間を使っているのかを把握するところから!と言うことで、ちまちま作業記録をGoogleカレンダーに付けていたのですが、開始時間を忘れてしまったり、そもそもつけるのを忘れてしまったり…。そして何よりめんどくさい…。
ということで、GASでボタンを押すだけで作業記録が取れるようにタイムカード的なものを作ってみました。

#完成品
タイトルなし.gif

  1. 必要項目を入力してstartボタンを押下し、作業開始
  2. もくもくと作業する
  3. 作業が終了したらstopボタンを押下し、作業終了

するとこんな感じでgoogleカレンダーに登録されます。楽ちん!
グループ 1

#使うもの
使用するのは下記の3つだけです。

  1. Googleスプレッドシート
  2. Googleカレンダー
  3. Google Apps Script(GAS)

#実装
それでは早速実装していきましょう!

##まずは下準備
###1. スプレッドシートを新規作成し、記録をつけたいカレンダーの情報をまとめておく
グループ 2
GASを使って特定のGoogleカレンダーに予定(今回の場合は記録)を登録するためにはカレンダーIDが必要になります。
私は予定によってカレンダーをかなり細かく分けており、記録をつける際もカレンダーを分けたかったので、新しいスプレッドシートを作成して記録をつけたいカレンダーの名前とIDをまとめておきました。
ここで名前に設定したものがカレンダーのプルダウンで表示されます。
スクリーンショット 2021-12-14 20.21.10
ちなみにカレンダーIDはGoogleカレンダーを開いて、使いたいカレンダー横の3点リーダーをクリックして、
グループ 9
設定と共有を開き、
グループ 10
カレンダーの統合から取得できます。
グループ 3

###2. 1.で作成したスプレッドシートからスクリプトエディタを開いて、必要なファイルを作成する
1.で作成したスプレッドシートのメニュー内、拡張機能>Apps Scriptからエディタを開きます。
グループ 4
スクリーンショット 2021-12-14 20.53.08
コード.gsは最初から用意されていますが、それ以外に必要なファイルはファイル横の+ボタンから任意で追加作成します。
グループ 5
下準備はこれで完了です!次は作成したファイルにコードを書いていきます。

##コードを書く

###GAS
スプレッドシートやカレンダーの操作等、Googleのサーバーにアクセスする処理は.gsファイルに記述していきます。

コード.gs
// 公開したWebアプリにアクセスがあった場合に実行
function doGet() {
  // 表示させるhtmlを指定
  const temp = HtmlService.createTemplateFromFile("index");
  // スプレッドシートからカレンダーの情報を取得
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getActiveSheet();
  const calData = sheet.getRange(2, 1, sheet.getLastRow()-1, 2).getValues();

  temp.calData = calData;

  return temp
    .evaluate()
    .setTitle('タイムカード')
    .addMetaTag('viewport', 'width=device-width, initial-scale=1');
}

// カレンダーに記録を登録
function addCal(calId,calTtl,start,end,calDesc){
  const calendar = CalendarApp.getCalendarById(calId);
  const title = calTtl;
  const startTime = new Date(start);
  const endTime = new Date(end);
  const option = {
    description: calDesc
  }
  
  calendar.createEvent(title, startTime, endTime, option);
}

doGet(e) 関数は特定のイベントが発生したときに自動で実行されるシンプルトリガーの一種で、ユーザーがWebアプリにアクセスした際に実行されます。

※以下は上記ソースコードからの抜粋です

コード.gs
// スプレッドシートからカレンダーの情報を取得
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getActiveSheet();
const calData = sheet.getRange(2, 1, sheet.getLastRow()-1, 2).getValues();

temp.calData = calData;

この関数内でスプレッドシートからカレンダーの情報を取得し、テンプレートのプロパティに設定しておきます。
こうすることでHTMLに記述した<? ... ?>のようなスクリプトレットを使用して参照することができます。

スクリプトレットについてはこちらをご参照ください。

###HTML

index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <!-- cssを記述したHTMLファイルの読み込み -->
    <?!= HtmlService.createHtmlOutputFromFile('reset').getContent(); ?>
    <?!= HtmlService.createHtmlOutputFromFile('css').getContent(); ?>
  </head>
  <body>
    <div class="wrap">
      <h1 id="heading" class="heading">作業開始する?</h1>
      <div id="time" class="time"></div>
      <select required id="cal">
        <option value="" hidden>カレンダー</option>
        <!-- スプレッドシートの情報からカレンダーを追加 -->
        <? for(let i = 0; i < calData.length; i++){?>
          <option value="<?= calData[i][1] ?>"><?= calData[i][0] ?></option>
        <?}?>
      </select>
      <input type="text" id="ttl" placeholder="タイトル">
      <textarea id="desc" placeholder="説明"></textarea>
      <div class="btn">
        <button type="button" id="startBtn" class="btn__item">start</button>
        <button type="button" id="stopBtn" class="btn__item">stop</button>
      </div>
    </div>
    <!-- jsを記述したHTMLファイルの読み込み -->
    <?!= HtmlService.createHtmlOutputFromFile('js').getContent(); ?>
  </body>
</html>

※以下は上記ソースコードからの抜粋です

index.html
<!-- cssを記述したHTMLファイルの読み込み -->
<?!= HtmlService.createHtmlOutputFromFile('reset').getContent(); ?>
<?!= HtmlService.createHtmlOutputFromFile('css').getContent(); ?>

プロジェクト内のcssやjsを記述したHTMLファイルもスクリプトレットを使用して読み込みます。

###Javascript

js.html
<script>
  const startBtn = document.getElementById('startBtn');
  const stopBtn = document.getElementById('stopBtn');
  const heading = document.getElementById('heading');
  const time = document.getElementById('time');
  const cal = document.getElementById('cal');
  const ttl = document.getElementById('ttl');
  const desc = document.getElementById('desc');
  startBtn.disabled = true;
  stopBtn.disabled = true;

  // 他の作業を開始していない状態でカレンダーの選択とタイトルの入力がされたらスタートボタンのdisabledをfalseに変更
  // 説明の入力は任意
  document.addEventListener('change', () => {
    if(!cal.value || !ttl.value || !stopBtn.disabled) return;
    startBtn.disabled = false;
  })

  // スタートボタンを押下した際の挙動
  startBtn.addEventListener('click', () => {
    const startTime = new Date().toLocaleString();
    time.textContent = startTime;
    heading.textContent = '作業開始!';

    startBtn.disabled = true;
    stopBtn.disabled = false;
  });

  // ストップボタンを押下した際の挙動
  stopBtn.addEventListener('click', () => {
    const calId = cal.value;
    const calTtl = ttl.value;
    const startTime = time.textContent;
    const endTime = new Date().toLocaleString();
    const calDesc = desc.value;

    // コード.gsに定義したaddCal()を呼び出して入力された内容を渡す
    google.script.run.addCal(calId,calTtl,startTime,endTime,calDesc);
    reset();
  });

  // 初期化
  const reset = () => {
    startBtn.disabled = true;
    stopBtn.disabled = true;
    heading.textContent = '作業開始する?';
    time.textContent = '';
    cal.selectedIndex = 0;
    ttl.value = '';
    desc.value = '';
  }
</script>

※以下は上記ソースコードからの抜粋です

js.html
// ストップボタンを押下した際の挙動
stopBtn.addEventListener('click', () => {
  const calId = cal.value;
  const calTtl = ttl.value;
  const startTime = time.textContent;
  const endTime = new Date().toLocaleString();
  const calDesc = desc.value;

  // コード.gsに定義したaddCal()を呼び出して入力された内容を渡す
  google.script.run.addCal(calId,calTtl,startTime,endTime,calDesc);
  reset();
});

google.script.runはクライアント側からサーバー側の関数を呼び出すAPIです。
stopBtnを押下したらカレンダーに記録をつけたいので、このAPIを使用してコード.gsに定義したaddCal()を呼び出します。

###css

css.html
<style>
  input,
  select,
  textarea {
    padding: 5px 10px;
    margin-top: 5px;
    width: 300px;
  }

  select:invalid {
    color: #757575;
  }
  
  ::placeholder {
    color: #757575;
  }

  button {
    border: none;
  }

  button:disabled {
    opacity: .5;
  }

  .wrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: 50px;
  }

  .ttl {
    font-size: 20px;
  }

  .time {
    min-height: 85px;
    display: flex;
    justify-content: center;
    align-items: center;
  }

  .btn {
    display: flex;
    margin-top: 20px;
    width: 300px;
  }

  .btn__item {
    flex: 1;
    padding: 12px;
    text-align: center;
    font-size: 14px;
    color: #fff;
    background: #798ebf;
    border-radius: 10px;
    cursor: pointer;
  }

  .btn__item + .btn__item {
    margin-left: 12px;
  }
</style>

reset.htmlはリセットcssなので省略します。私はA Modern CSS Resetを使用しました!

##いざ、デプロイ!

エディタ右上のデプロイ>新しいデプロイを開き、種類はウェブアプリを選択します。
それから、説明文、実行ユーザーとアクセスユーザーを設定してデプロイします。
グループ 6
グループ 7
アクセス許可を求められるので、アカウントを選択して許可してあげます。
グループ 11
グループ 12
赤枠のURLにアクセスして問題なくページが表示されていれば完成です!やったー!
グループ 8

##トラブルシューディング
あれ?登録できたけど時間がずれてるぞ?と思ったら…
グループ 8
タイムゾーンがずれている可能性があるので、一旦スクリプトエディタに戻って歯車マークのプロジェクトの設定を開きます。
グループ 8
グループ 8
「appsscript.json」マニフェスト ファイルをエディタで表示するにチェックを入れてエディタに戻ると、appsscript.jsonが追加されているので開きます。

appsscript.json
{
  "timeZone": "America/New_York",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "webapp": {
    "executeAs": "USER_DEPLOYING",
    "access": "MYSELF"
  }
}

timeZoneAmerica/New_Yorkになっていますね。日本在住の方は下記のようにAsia/Tokyo、それ以外の方はお住まいの地域のタイムゾーンに変更してあげましょう。

appsscript.json
{
  "timeZone": "Asia/Tokyo",
  "dependencies": {},
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "webapp": {
    "executeAs": "USER_DEPLOYING",
    "access": "MYSELF"
  }
}

保存して再度デプロイしてみてください!

#おわりに
サーバーサイドの知識がなくても簡単にサクサクっとWebアプリを公開できるし、Googleのアプリも操作できるし、GASって便利なやつですね。
他にもいろいろなことができそうなので、もう少し深堀して勉強してみたいです。
私のスケジューリングが上手になることを祈りつつ…完!

#参考
GASでWebページを表示するdoGet関数のスクリプトについて丁寧に解説
HTML Service: Templated HTML
GASでWebアプリを作ろう① | LogicalCreation
GASでウェブアプリケーション公開方法と実行・アクセスユーザー設定を解説 | AutoWorker〜Google Apps Script(GAS)とSikuliで始める業務改善入門

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?