【GAS】スプレッドシートからGoogleToDoリストにタスクを出力
ほとんどChatGPTに聞きました。
ひとまずこのスプレッドシートをマイドライブにコピーしてご覧下さい。
ChatGPTが作ってくれたスクリプト
【2023-07-11 16:05 不具合について確認済み。記事最下部に詳細あり。】
function getListNamesAndOutput() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet.clear(); // シートの内容をクリアしてから再度出力
var taskLists = Tasks.Tasklists.list().getItems();
if (taskLists.length === 0) {
sheet.getRange(1, 1).setValue("リストがありません");
return;
}
sheet.getRange(1, 1).setValue("リスト名");
sheet.getRange(1, 2).setValue("リストID");
sheet.getRange(1, 3).setValue("etag");
for (var i = 0; i < taskLists.length; i++) {
var listName = taskLists[i].title;
var listId = taskLists[i].id;
var etag = taskLists[i].etag;
sheet.getRange(i + 2, 1).setValue(listName);
sheet.getRange(i + 2, 2).setValue(listId);
sheet.getRange(i + 2, 3).setValue(etag);
}
}
function addTasksToGoogleToDoList() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var data = sheet.getDataRange().getValues();
var taskLists = Tasks.Tasklists.list().getItems();
var listIdMap = {}; // リストIDをキーとしたリスト名のマップを作成
for (var i = 0; i < taskLists.length; i++) {
listIdMap[taskLists[i].id] = taskLists[i].title;
}
for (var i = 1; i < data.length; i++) {
var dueDate = data[i][0];
var taskName = data[i][1];
var description = data[i][2];
var listName = data[i][3];
var check = data[i][4];
var listId = data[i][5];
// 未入力のタスク名、無効な期限、無効なリストIDの場合はスキップ
if (!taskName || !isValidDate(dueDate) || !listIdMap.hasOwnProperty(listId)) {
continue;
}
// 期限をISO8601形式に変換
var isoDueDate = Utilities.formatDate(new Date(dueDate), "JST", "yyyy-MM-dd") + "T00:00:00.000Z";
var task = {
title: taskName,
notes: description,
due: isoDueDate,
status: check === "済" ? "completed" : "needsAction"
};
try {
var result = Tasks.Tasks.insert(task, listId);
sheet.getRange(i + 1, 5).setValue("追加済"); // タスクが追加されたことを示す値を出力
} catch (e) {
Logger.log(e);
sheet.getRange(i + 1, 5).setValue("エラー: タスクを追加できませんでした"); // エラーが発生したことを示す値を出力
}
}
}
function isValidDate(dateString) {
var dateObject = new Date(dateString);
return Object.prototype.toString.call(dateObject) === "[object Date]" && !isNaN(dateObject);
}
function deleteResultValues() {
var sheet = SpreadsheetApp.getActiveSheet();
var range = sheet.getRange("E2:E");
range.clearContent();
}
詰めが甘いところがあるかもしれませんが大目に見てください。
シートの設定
今回は【ToDo登録】と【リスト一覧】の2つのシートを用意します。運用としてはシンプルな方なのではないかと思ってます。
詳細は以下の通りです。
【ToDo登録】シート
A列:タスクの期限
B列:タスクタイトル
C列:タスクの詳細
D列:タスクを追加する先のリスト名
E列:正常に追加されたかどうかのチェック
F列:D列のリストのID (非表示にしてます)
という構成にしています。
A,B,D列は入力必須です。
不備がある場合、そのタスクが追加されません。
期限を設定しなくても追加させてくれよ、と思うかもしれませんが、そもそも期限のないタスクは「タスクとして」設定すべきではありません。手入力でいいかと。
F列は非表示にしてありますが、後述の【リスト一覧】シートからVLOOKUPでリストIDを引っ張ってきています。
また、設置したボタンの挙動は以下の通りです。
《ToDo追加》…… E列が空欄になっているタスクを追加します。
《クリア》…… E列の登録状況を一括クリアします。このシートを複数人で運用する際は便利かもしれません。
【リスト一覧】シート
このシートは処理用の裏方シートです。
A列:リスト名
B列:リストID
C列:Etag (一応)
ボタンを押したら動くようにはしていますが、トリガー設定して定期的にリスト一覧を取得してもいいかもしれません。
ToDo追加の手順
①リスト一覧を取得
【リスト一覧】シートのボタンを押しましょう。(※最初は権限の承認プロセスがあります。承認後もう一度押してみてください。)
リストの取得元は、そのときスプレッドシートを開いているアカウントです。★つきリスト以外の全てのリストとそのIDが取得されます。
②タスクを入力
【ToDo登録】シートに必要事項を入力していきます。期限とタイトルとリスト名は必須です。パソコンで開くこと前提ですが、期限(A列)はダブルクリックでカレンダーからの日付入力が可能です。また、リスト名はドロップダウンリストからの選択式にしています。
③タスクを追加
同シートの《ToDo追加》ボタンを押しましょう。うまく追加できれば、指定したリストにToDoが出力され、シートのE列に「追加済」と出ます。スマホ等でGoogle ToDoリストを確認してみましょう。
④登録状況のクリア(任意)
これは必須ではありません。複数人で同じタスクを登録したくてスプレッドシートを共有する場合や、何らかの理由でもう一度追加する必要があるときに《クリア》ボタンを押してください。
参考記事
勝手ながら、ともかつさんの記事を参考にしました。期限の変数部分とか。助かりました。
余談
スプレッドシートのテンプレート集にあるToDoリストについて
「スプレッドシート todo」とかで検索かけていると、よく見かけるのがテンプレート版ToDoリスト(以下:テンプレToDo)です。
Google ToDoリストのアプリ(Googleカレンダーの右側サイドバーから見れるあれorスマホ版アプリ)ではなく、スプレッドシートの新規作成時テンプレートから作れるToDoリストですね。
「3秒でToDoリスト完成😁」「日々のタスクも整理できます🥹成長したいビジネスパーソンには必須✨」などと持て囃されてはいますが、要はスプレッドシートです。
テンプレートとして「ToDoリスト」と名付けられてはいますが、スプレッドシートである旨味を存分に引き出し切れていない感じは否めません。
パソコンのみで扱うならまだしも、スマホで(も)見るのであれば、圧倒的にアプリ版のGoogle ToDoリストに軍配が上がります。
テンプレToDoは誰かが詳しく解説してくれていると信じ、ここではあまり深堀りしません。
ただ、アプリ版Google ToDoリストの良いところは、リストの確認までに取る手数の少なさだと思うんですね。
アプリを起動すればすぐリストを確認できる。つまり1アクションで確認できる。ウィジェットを使ってホーム画面に常時表示できるのであれば0アクションです。
方やテンプレToDoを使おうとすると、Googleスプレッドシートのアプリを起動→当該スプレッドシートを開いて確認、と2アクションは必要になります。(他アプリで自動化していたり、SlackやLINE、Gmailなどと連携させている場合は除きます。)
もちろん、共有できる点においてはテンプレToDoが優れているとは思います。しかしテンプレToDoをそのままの形で、何もいじらずに使うのはつまらないと思うんですよ。(感想です。) スプレッドシートである必要あるかなあ、と。
ChatGPTの利用について
今回はスプレッドシートからToDoを出力したいという思いはもちろんありましたが、それ以上にChatGPTを使ってGASを組んでみたかったんです。
非エンジニアでも云々と宣伝して情報商材で一儲けしようという気持ちは毛頭ありませんが、いい経験になりました。面白かったです。
特に良かったのは、
・「ここの処理ってどういうこと?詳しく教えて」などと聞いてみると丁寧に教えてくれる
・注文を何度付け足しても、すぐ修正版をくれる
・参考にした他のスクリプトと比較させると、作りたい条件に応じて採用してくれる
……と、こんなところですかね。
ただ、ChatGPTが「これでうまくいくはずです」と堂々出してきたスクリプトに、素人のぼくが見ても間違いだと分かる箇所があったのは確かです。
まあその辺は慣れもありますが、頭の中に最終的な出力の完成図があることや、エラーのときに何が起こっているか(もしくは起こらなかったのか)を冷静に考えられる力とかは大事なのかなあと思った次第です。
【2023-07-11 16:05追記】
詳細欄に入力した内容が、期限なしのタスクとして登録されるという不具合があります。鋭意改善中です。タスクタイトルに設定したタスクは、期限やリスト等に関しても問題なく登録されます。
【2023-07-14 15:51追記】
どうやら詳細欄ではなくて、手動で足したサブタスクと、アプリでの「日付」並べ替えの相性が良くないっぽい。「指定した順序」ではサブタスクがちゃんとメインタスク直下に表示される。