読者です 読者をやめる 読者になる 読者になる

pslaboの日記

はてなダイヤリーからはてなブログに引っ越してきました

この日記は現在実行中の減量記録を含む個人的なメモとして始めましたが、最近はコンピュータやガジェット、ハック、セキュリティネタのほうがメインになっております。

iPad3のSIMロックに関する考察とSIM下駄による解除の試みはSoftbank版iPad3にiPhone用のSIM下駄を履かせてみるにいろいろ書いてます。

ポストした内容のカテゴリー分けがちゃんと出来てないので、過去記事を探したい方はお手数ですが検索で探してみてください。


Google Form で「休暇申請用フォーム」を作成し、申請内容を共有カレンダーに自動登録する。

Google Form Google Calendar Google Apps Script

※このネタが Google Apps 以外でイケるかどうかは検証しておりません。


グループウェアとして Google Apps を利用してスケジュール共有する場合に案外困るのは「いつ、誰が休暇の予定を入れているか」が分かりづらいことだと思います。

そこでこういう運用を考えてみました。

  • 「全員の休暇予定を登録する共有カレンダー」を作る。
  • 休暇を取得する方は「自分のカレンダー」に予定登録しつつ、その予定のゲストとして「全員の休暇予定を登録する共有カレンダー」を登録しておく。

この運用をスムースに行うために「サテライトオフィス 組織カレンダー」を利用していて、概ね上手く行ってはいます。しかしこの方法の欠点は「全員の休暇予定を登録する共有カレンダー」を見た時に「誰かが休むことはわかるけれど、誰が休むかは分かりづらい」という点にあります。予定の詳細を見れば予定の登録者は分かります。でも日、週、月の予定一覧には予定の登録者情報は出ないからです。

よって、このような運用を行う場合は「件名に休暇取得予定者の名前を記入する」というルールを運用でカバーせねばなりません。しかし運用でカバーするのは案外面倒くさい。


だから代わりに「休暇申請用フォーム」を Google Form で作成しておき、その Form の送信時に動くスクリプトでスケジュール登録することにより、件名の文字列を正規化することにします。

Calendar を作る。

「休暇取得予定」を全員で閲覧共有するためのカレンダーを作ります。特筆すべき点はありませんが、全員が編集可能であることが多分必要。あるいは Form のオーナーを特権管理者とかにしておけば、閲覧専用で作ってもよいかもしれんけど。

また作成した Calendar ID は後ほど説明するスクリプトに埋め込む必要があります。

Form を作る

Form はこんな要件で作ります。

  • 2ページ構成の Form にします。
  • 1ページ目は「休暇種別」「休暇取得期間」「休暇取得目的」を入力する。なお、「休暇種別」と「休暇取得期間」は必須項目にする。
  • 2ページ目は2種類作る。1つは「1日または半日の休暇取得時の日付入力用」。もう一つは「日付の期間指定を行う」ため。

1ページ目の例
f:id:pslabo:20160221181746p:plain

2ページ目の例
f:id:pslabo:20160221181806p:plain

1ページ目→2ページ目の遷移は「休暇取得期間」の回答内容に合わせて変える。
f:id:pslabo:20160221181858p:plain

Form に連動するScriptを作る。

Script を作る前に Form 編集画面左下の「以前のGoogleフォームに戻す」を選んでおきます。「新しい Google フォーム」で Script を組み合わせる方法がイマイチわからないので。。。

で、「ツール」「スクリプトエディタ」からスクリプトを作ります。作り終わったら「リソース」→「現在のプロジェクトのトリガー」から、スクリプトがフォーム送信時に動くように設定します。

スクリプトの例

holiday calendar の情報だけ差し替えればとりあえず動くはず……

// 「休暇取得予定者」のカレンダー情報。
var holidaycalendar = "xxxxxxxxxx@group.calendar.google.com";

// フォームの内容に元づいてスケジュール登録する。
function sendThingToCalendar(e) {
  
  var holidaytype      = "夏季休暇";
  var holidayterm      = "終日";  // 午前半休、午後半休、終日、複数日
  var holidaystart     = "2015-08-04";
  var holidayend       = "2015-08-04"
  var holidaystarttime = "00:00:00"
  var holidayendtime   = "00:00:00";
  var holidayreason    = "";

  var itemResponses    = e.response.getItemResponses();
//  var editURL          = e.response.getEditResponseUrl();
  
  for ( var i = 0 ; i< itemResponses.length ; i++ ) {

    switch( itemResponses[i].getItem().getTitle() ) {
      case "休暇種別":       holidaytype   = itemResponses[i].getResponse(); break;
      case "休暇取得期間":   holidayterm   = itemResponses[i].getResponse(); break;
      case "休暇取得開始日": holidaystart  = itemResponses[i].getResponse(); break;
      case "休暇取得終了日": holidayend    = itemResponses[i].getResponse(); break;
      case "休暇取得日":     holidaystart  = itemResponses[i].getResponse(); holidayend=holidaystart; break;
      case "休暇取得目的":   holidayreason = itemResponses[i].getResponse(); break;
    }

  // 午前半休、午後半休の場合は開始終了時刻を予定に追加する。
    switch( holidayterm ) {
      case "午前半休":
        holidaystarttime = "00:00:00";
        holidayendtime   = "15:00:00";
        holidaytype     = holidaytype + ":" + holidaytype;
        break;
      case "午後半休": 
        holidaystarttime = "15:00:00";
        holidayendtime   = "23:59:59";
        holidaytype     = holidaytype + ":" + holidaytype;
        break;
    }
  }
  
  // 休暇種別の文字列に休暇申請者のメールアドレスを追記する。
  holidaytype  = holidaytype + ":" + e.response.getRespondentEmail();

  // フォーム送信者のメールアドレスに対応するカレンダーにスケジュール登録するためにカレンダーIDを取得する。
  var calendar = CalendarApp.getCalendarById(e.response.getRespondentEmail());

  // 予定の開始日時、終了日時の文字列から、
  // 日付文字列と時刻文字列を組み合わせて、日付時刻型にする。
  var holidaystartDate = dateString2Date( holidaystart, holidaystarttime );
  var holidayendDate   = dateString2Date( holidayend,   holidayendtime );

  var calendar_event;

  if ( holidaystartDate < holidayendDate ) {
  // 開始日時 < 終了日時なら、期間指定のイベントとして登録する。  
    calendar_event = calendar.createEvent(
      holidaytype,
      holidaystartDate,
      holidayendDate,
      {
        guests: holidaycalendar,
        description: holidayreason
      }
    );
  }
  else if ( holidaystart == holidayend && holidaystarttime == holidayendtime ) {
    // 開始日と終了日が同じ、かつ開始時刻と終了時刻が同じならば、
    // 終日の予定として登録する。
    calendar_event = calendar.createAllDayEvent(
      holidaytype,
      holidaystartDate,
      {
        guests: holidaycalendar,
        description: holidayreason
      }
    );
  }

  var calendar_eventid = calendar_event.getId()

  
  var logmessage = holidaytype;
  logmessage = logmessage + " " + holidayterm;
  logmessage = logmessage + " " + holidaystartDate;
  logmessage = logmessage + " " + holidayendDate;
  
  Logger.log( logmessage );          
    
}



function dateString2Date( datestring, timestring ) {
  var datearray = datestring.split( "-" );
  var timearray = timestring.split( ":" );
  
  if ( datearray.length == 3 ) { 
    string2date = new Date(
      datearray[0], datearray[1]-1, datearray[2],
      timearray[0], timearray[1],   timearray[2] );
  }

  return string2date;
}