実現したいこと
定時的にフォルダ内のファイルの再帰的探索をし、前回の実行以降に新規で追加されているデータをスプレッドシートに追記したあと、「新規で追加されたデータのみをメールで通知する」
※初めて投稿するため、【試したこと】などの記載内容が不適切かもしれません。投稿の方法に不備がある場合はコメントでご指摘いただければ幸いです。
前提
Googleドライブで共有されている特定のフォルダ内に、新しくファイルが追加されているかどうかを検索し、スプレッドシートに追記していくコードを作成しています。
検索と追記の部分については問題なく動くので、他の機能の追加が考慮されない範囲では修正の必要がない状態です。
ドライブには複数の担当者が不定期にファイルを格納するため、コードは時間トリガーで定時的にバックグラウンド処理する事を前提にしています。
ドライブの親フォルダ名ごとに、同名のシートが同一ID内のスプレッドシートにそれぞれ作成されており、
親フォルダの検索結果と対応するシートの内容を比較して、追記をしていきます。
(下記コードでは フォルダID"AAAA",シート名"aaaa"で仮表記しています)
シートの内容はコード実行以外では編集される事なく保持されるので、コード実行時点でシートに存在していなかったもの=「新規で追加されたもの」と判定します。
対象のファイルを判定した場合、必ずしも最終行への追加ではなく、サブフォルダ順に並ぶように情報が挿入される機能になっているはずです。
(セルへの挿入方式は運用上必須として指定されているので、結果が変わってしまう修正は望ましくないです)
担当者ごとにサブフォルダの作成方法が異なる(作成ルールが存在しない)ので、フォルダ内を再帰的に検索する方式を採用しています。
発生している問題・エラーメッセージ
ファイルの検索とシートへの書き込みは出来ています。しかし、それをメールで通知する方式が全く達成出来ません。
『今回の検索で、〇〇がシートに新規で追加されたよ』といった感じの内容をメールでお知らせしたいのです。
実現するにはどのようなコードを追加すればいいでしょうか?
サンプルコードをくれなどと贅沢は言いません。メソッドの活用方法だけを教えていただく形で、もちろん構いません。
書き込み時点で変数にpush格納したり、最後にまとめてデータを比較したり、様々な方法を試しましたが、知識不足のために上手くいきません。
コードの実行時にシートへ追記されたもの、即ち新しく格納されたと判定したファイルの情報だけをメールで通知したいのですが、どのような方法を試しても
「シート内に記載されているデータ全て」が送付されるか、
「新しく追加されたデータ行から下のデータ全て」が送付されてしまいます。
当該実行の時点で新しく追記されたものだけを、重複チェックをしてシート内で非重複と判定されたものだけを、メールで通知したいのです。
メールの送信タイミングは、コード終了後に一括で行いたかったのですが上手くいかなかったので、
for (var i = 0; i < folderIds.length; i++)のループ終了時点 //メール送信機能の予定地A と、
while (files.hasNext())の終了条件到達時点 //メール送信機能の予定地B の二ヶ所で検討しました。
しかしどちらで組み合わせても上手くいかなかったため、下記ソースコードからは一旦オミットしています。
(知識不足のため、そもそも挿入箇所を間違えている可能性もありますが)
理想としては、var sheetNames で宣言されているシートへ書き込む内容全て、すなわちフォルダ名とファイル名とURLと更新日時が全てメールで送られてほしいです。
ただし配列の問題などで困難な場合、どのような形になっても構いませんので、実現方法の例を教えていただけると幸いです。
該当のソースコード
function searchFilesInFolder2() {
var folderIds = ["AAAA", "BBBB", "CCCC"];
var sheetId = "XXXXXXXXXXXXXXXXXXXXXXXXX";
var sheetNames = ["aaaa", "bbbb", "cccc"];
for (var i = 0; i < folderIds.length; i++) {
var folderId = folderIds[i];
var sheetName = sheetNames[i];
var folder = DriveApp.getFolderById(folderId);
var sheet = SpreadsheetApp.openById(sheetId).getSheetByName(sheetName);
var lastRow = sheet.getLastRow();
var existingData = lastRow > 1 ? sheet.getRange(2, 6, lastRow-1, 2).getValues() : [];
processFolder(folder, sheet, existingData);
var date = Utilities.formatDate(new Date(), "Asia/Tokyo", "yyyy/MM/dd HH:mm");
sheet.getRange(1, 9).setValue(date);
}
//メール送信機能の予定地A
SpreadsheetApp.getUi().alert("完了");//テスト段階での確認用、実装時に削除予定
}
function processFolder(folder, sheet, existingData, row = 2, folderNames = []) {
//暫定的な宣言
var newData = [];
// フォルダ内の全てのファイルを処理
var files = folder.getFiles();
while (files.hasNext()) {
var file = files.next();
// ファイル名とリンクURLを取得
var fileName = file.getName();
var fileUrl = file.getUrl();
// ファイルの作成日時を取得
var fileDate = file.getDateCreated();
// ファイルが既に存在するかチェック
var duplicate = existingData.some(function(row) {
return row[0] == fileUrl && row[1] == Utilities.formatDate(fileDate, "Asia/Tokyo", "yyyy/MM/dd HH:mm");
});
// ファイルが存在しない場合、シートに記入
if (!duplicate) {
// フォルダ名を書き込む
for (var i = 0; i < folderNames.length; i++) {
sheet.getRange(row, i + 1).setValue(folderNames[i]);
}
// ファイル名とリンクURLをハイパーリンクとして書き込む
sheet.getRange(row, 6).setValue(fileName).setFormula('=HYPERLINK("' + fileUrl + '","' + fileName + '")');
// ファイルの更新日時を書き込む
sheet.getRange(row, 7).setValue(Utilities.formatDate(fileDate, "Asia/Tokyo", "yyyy/MM/dd HH:mm"));
row++;
}
//メール送信機能の予定地B
}
// サブフォルダを処理
var subfolders = folder.getFolders();
while (subfolders.hasNext()) {
var subfolder = subfolders.next();
// フォルダ名をコピー
var newFolderNames = folderNames.slice();
newFolderNames.push(subfolder.getName());
// サブフォルダ内のファイルを再帰的に処理
row = processFolder(subfolder, sheet, existingData, row, newFolderNames);
}
return row;
}
試したこと
// ファイル名とリンクURLをハイパーリンクとして書き込む
sheet.getRange(row, 6).setValue(fileName).setFormula('=HYPERLINK("' + fileUrl + '","' + fileName + '")');
newData.push([fileName, fileUrl]); // 追加
// ファイルの更新日時を書き込む
var formattedDate = Utilities.formatDate(fileDate, "Asia/Tokyo", "yyyy/MM/dd HH:mm");
sheet.getRange(row, 7).setValue(formattedDate);
newData[newData.length - 1].push(formattedDate); // 追加
上記のように書き込みデータを変数に格納して、whileの最後にメールを送信する形式を試しました。
これで新規の書き込みだけが格納されるかと思っていたのですが、それ以外の行のデータも格納されてしまいました。
また、比較する為の新しいシートを作成して、実行前と実行後の比較差分を格納する方式も試したかったのですが、
新しいシートを作成する事自体が管理者に許可されませんでした。
補足情報(FW/ツールのバージョンなど)
「スプレッドシートの通知機能の利用」や「外部ツール(Slackなど)の併用」は組織の管理者から却下されています。
『全てGASのコードの仕様内で完結させる』との条件が示されています。
なお、一部OpenAIに書かせた記述を引用しているので、書式の統一されていない箇所があるのはご容赦下さい。

回答1件
あなたの回答
tips
プレビュー