年越しのTODOリスト大掃除(…をしたかったけど、タスク処理が間に合わないのでGcalのTODOリストを一覧表示・修正できるGoogle Apps Script書いた)


ほぼ間違いなく今年最後の更新です。

本当はTODOリストに書いているタスクの大半を終わらせて、綺麗に年越ししたかったのですが、間に合いそうになかったのでとりあえず一覧表示、完了処理だけでもスプレッドシートで簡単にできるようなGASを書きました。

はじめに、今年はいろいろとタスクを貯めこんでしまい、処理が追いつかないどころか、自分のやることの優先度をつけるのも時間がかかってしまうことも多かったので、TODOリストはほぼ必須のはずだったのですが、自分にしっくり来るTODO管理のシステムorサービスがあまりありませんでした。

個人的にTODOシステムを探す際には以下の点を重視していました。

  • 日付順にソートできる → 締切の近いものから処理したい
  • 毎週・毎月等のタスクを登録しやすい → 週報的なものもわかっている分は一括登録したい
  • 複数デバイスで同期 → TODOリストがあちこちにあるとTODOリストを管理するTODOが必要
  • 完了したタスクも見直せる → 見直しのためというよりミスしてdoneすることもあるので戻せるように
  • できれば特別なアプリなしでも見えるように → 思い出した時にすぐ書ける・見える

こういった点を考えていると、Remember The Milkもかなりいい感じだったのですが、モバイル端末との自由な同期が有料会員限定だったのでちょっと二の足を踏んでいました。結局、直近ではgoogleカレンダーにTODOリスト用のカレンダーを作成して、タイトルに”[done]”等つけてそこで管理していました。(googleカレンダー純正のTODOリストは毎週タスクが登録できない等あったので)

ただ、この方法でもTODOリストだけを一覧表示しようと思うと、一旦別のカレンダーを全部隠した上で表示変更しなければならないことや完了タスクの非表示などは面倒だったので、結局あまり使わないまましばらく放置気味でした。

しかし、最近またタスク量が増えてきてこのままだと管理しきれなくなりそうだったので、その不満部分を解消すべく、このtodoリストカレンダーをgoogleスプレッドシートにいい感じに書き出したうえで、そこで終了設定等もできるようにgoogle apps scriptで処理コードを書きました。

概要としては以下の様な形です。

  • 未処理タスクを一覧表示(週間タスクは最初の未処理のみ)
  • スプレッドシートに完了処理を書き込むだけでカレンダーにも反映
  • 休止等も別扱いでタグ管理

実際に実行した場合、以下のようにスプレッドシートにTODOリストが表示されます。そして一番右のセルにdoneやstay等書き込むとカレンダーにも反映されます。処理は毎回、「書き込み部を処理→スプレッドシート初期化→カレンダーからリスト再生成」をトリガーで処理しています。

スクリーンショット 2013-12-31 22.01.57

以下に今回作成したコードを記載します。

そもそもこのコードを書き始めたのが今日の18時過ぎ頃なので、実質2,3時間強で書いたコードなので汚い、バグ等いくらでもあると思いますので、もし使われる場合には予めご了承ください。使う際は、カレンダーのタイトルを変数CAL_NAMEに指定しているものと同一のものにまた、スプレッドシートのIDを変数ssの引数に指定した後、run関数を同期周期に指定したい時間のトリガーで実行してください。そのうち気が向いらリファクタリングや自分が使ってるうちに見つけたバグの修正はするかもしれません。

 

var ss =  SpreadsheetApp.openById("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
var CAL_NAME="〆切一覧";
var sheet_list =['todo','stay','cancel','done','New'];

function init(){
  if(ss.getSheets().length>sheet_list.length)
  {
    while(ss.getSheets().length>sheet_list.length)
    {
      var sheet = ss.getSheets()[0];
      //シートの全消去は不可能
      ss.deleteSheet(sheet);
    }
  }
  else
  {
    while(ss.getSheets().length<sheet_list.length)
    {
      ss.insertSheet();  
    }
  }

  for(var i=0;i<sheet_list.length;i++)
  {    
    var sheet = ss.getSheets()[i];
//    ss.moveActiveSheet(i+1);
    sheet.setName(sheet_list[i]);
  }

  for(var i=0;i<ss.getSheets().length;i++)   {     var sheet =  ss.getSheets()[i];     if(sheet.getLastRow()>=1 &&  sheet.getLastColumn()>=1)
    {
      sheet.getRange(1,1,sheet.getLastRow(),sheet.getLastColumn()).clear();
    }
    sheet.getRange(1,1).setValue("タイトル");
    sheet.getRange(1,2).setValue("締切");
    sheet.getRange(1,3).setValue("ID");
    sheet.hideColumn(sheet.getRange(1,3));
    sheet.getRange(1,5).setValue("開始時間");
    sheet.hideColumn(sheet.getRange(1,5));
    sheet.getRange(1,4).setValue("['done','stay','cancel']");
  }
}

function getAllList() {
  var cal = CalendarApp.getCalendarsByName(CAL_NAME)[0];
  var sheets = ss.getSheets();
  var start_date =  new Date();
  var end_date = new Date();
  start_date.setYear(start_date.getYear()-1);
  end_date.setYear(end_date.getYear()+1);
  var events = cal.getEvents(start_date,end_date);
  var row=[2,2,2,2];
  var num;
  var myObj = new Object();
  for(var i=0;i<events.length;i++)
  {
    num=-1;
    var i_end = events[i].getEndTime();
    var i_title = events[i].getTitle();
    var i_id = events[i].getId();
    var i_start = events[i].getStartTime();

    if(i_title.indexOf("[cancel]")==0)
    {
      num=2;
    }
    else if(i_title.indexOf("[stay]")==0)
    {
      num=1;
    }
    else if(i_title.indexOf("[done]")==0)
    {
      num=3;
    }
    else
    {
     num=0; 
    }
    if(num!=-1 &&myObj[i_title]!=1)
    {     
      var sheet = sheets[num];
      sheet.getRange(row[num],1).setValue(i_title);
      sheet.getRange(row[num],2).setValue(i_end);
      sheet.getRange(row[num],3).setValue(i_id);
      sheet.getRange(row[num],5).setValue(i_start);      

      row[num]++;
      myObj[i_title]=1;
    }
  }  
}

function setTodoList() {
  var sheet = ss.getSheets()[0];
  var LastRow = sheet.getLastRow();
  var cal = CalendarApp.getCalendarsByName(CAL_NAME)[0];
  for(var i=2;i<=LastRow;i++)
  {
    var flag = sheet.getRange(i,4).getValue();
    if(flag != '')
    {
      var title = sheet.getRange(i,1).getValue();
      var date = sheet.getRange(i,5).getValue();
      var id =sheet.getRange(i,3).getValue();
      var events = cal.getEventsForDay(date, {search: title});
      events[0].setTitle('['+flag+']'+title);      
      Logger.log(events[0].getTitle());
    }
  }
  /*
  Logger.log(date);
  date.setYear(date.getYear()+1);
  Logger.log(date);
*/
}

function run(){
 setTodoList();
 init(); 
 getAllList();
}

それでは、皆様今年も1年間ありがとうございました。良いお年を!


コメントを残す

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

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください