質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

Q&A

解決済

1回答

288閲覧

GASでフォルダ検索してファイル情報を書き出すコードに、メールで通知する機能を追加したい

try_Sunlight

総合スコア6

Google Apps Script

Google Apps ScriptはGoogleの製品と第三者のサービスでタスクを自動化するためのJavaScriptのクラウドのスクリプト言語です。

0グッド

2クリップ

投稿2023/11/10 07:11

編集2023/11/10 07:48

実現したいこと

定時的にフォルダ内のファイルの再帰的探索をし、前回の実行以降に新規で追加されているデータをスプレッドシートに追記したあと、「新規で追加されたデータのみをメールで通知する」

※初めて投稿するため、【試したこと】などの記載内容が不適切かもしれません。投稿の方法に不備がある場合はコメントでご指摘いただければ幸いです。

前提

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に書かせた記述を引用しているので、書式の統一されていない箇所があるのはご容赦下さい。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

YellowGreen

2023/11/10 08:19 編集

GASのリファレンスですが、メールのデータの作り方を知りたいということでしょうか。 https://developers.google.com/apps-script/reference/gmail/gmail-app?hl=ja#sendEmail(String,String,String) なお、修正後は、トリガーを更新(設定し直し)するかエディタから実行して Gmailへのアクセス権を許可する必要があると思います。 データの作成方法よりは、データの作成場所ではないでしょうか> row++; } //メール送信機能の予定地B ↓ //メールデータの作成機能の予定地Bを追加(if文の内側でデータを作成) row++; } //メール送信機能の予定地B などのように。シートへの記入の処理と メールデータの作成を一体化させる必要があると思います。
try_Sunlight

2023/11/10 08:14

コメントいただきありがとうございます。 すみません、私の質問の書き方にこのサイトの標準的な質問方法との乖離があり、質問の方法が不適切なように思いましたので、試したコードを正確に再現した上で、もう少し要点を絞って質問をし直させていただきます。 ご案内をいただいたにも関わらず、申し訳ありません。
YellowGreen

2023/11/10 08:20

コメントに追記しましたのでご覧ください。
try_Sunlight

2023/11/10 08:25 編集

追記、確認させていただきました。まずそもそも機能の作成場所が間違っているというご指摘、実際のコードで反映し試行をさせていただきます。ありがとうございます。
guest

回答1

0

自己解決

自己解決しました。
書き込みとメール通知を同時にやろうとしていた為、重複のチェックやら配列の形式やら整合性が取れずにいましたが、「別々のスクリプトで別々に行う」という根本的な仕様変更で、使用上の及第点はクリア出来ましたので、一旦解決とします。
>>YellowGreenさん
コメントをいただきありがとうございました。
『作成を一体化させる必要がある』という指摘をいただいたおかげで、必要な処理の洗い直しをするきっかけとなりました。

投稿2023/11/14 08:08

try_Sunlight

総合スコア6

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問