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

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

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

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

Q&A

0回答

1454閲覧

「スプレッドシートから フォーム送信時」 トリガー設定で、同時送信されたときのエラーを回避する方法

yoichiyy

総合スコア55

Google Apps Script

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

0グッド

1クリップ

投稿2020/10/06 06:55

編集2020/10/12 06:54

google formに回答があった時に、
スクリプトが実行されるように設定(「スプレッドシートから フォーム送信時」)しています。

自動返信メールを送るスクリプトです。

単にメールを送るだけでなく、
スプレッドシートの値をコピーしたり、
その値をもとにグラフを生成し、それをメールに添付したりするもので、
一回あたりの実行時間が5秒程度かかります。

このスクリプト実行の約5秒間の間に、
次のフォームを受信してしまうと、そのままエラーになってしまいます。

フォームが同時に送信された場合、
現在実行中のスクリプトが完了次第、準備ができるまで待ってもらうようなスクリプトを書く方法があればお教え下さい。

どうぞよろしくお願い致します。

function tillDraft(){ var ss = SpreadsheetApp.openById(SpreadsheetApp.getActiveSpreadsheet().getId()); var sheet = ss.getSheetByName("graph"); var ReferenceCell = sheet.getRange("s1"); //毎回VlookUPのために、値を更新する必要がある。 var EndCell = sheet.getRange("t1"); var ssID = "略"; var sheetID = sheet.getSheetId(); var driveID = "略"; //////////////////// //追加変数と、追加回答処理部分 //////////////////// var DataSheet = ss.getSheetByName("data"); const CValues = DataSheet.getRange('C:C').getValues();  var LastRow_Answered = CValues.filter(String).length;  //返信済み打刻されている最終行。CValues(返信まち最終行)よりも、短い。 const CZValues = DataSheet.getRange('CZ:CZ').getValues();  var LastRow = CZValues.filter(String).length;   //未処理の回答数をカウント var mishori_count = LastRow_Answered - LastRow; Logger.log(mishori_count)  //未処理カウントが1以上の場合、これが0になるまで(1になるまで?)繰り返し処理 if(mishori_count >0){ Logger.log("ifクリア"); for(var i = mishori_count; i >=1; i--){ Logger.log("ループ実行"); var toshibango = DataSheet.getRange(LastRow,1).getValues(); var yokonaga = DataSheet.getRange(LastRow-1,42,LastRow-1, 89).getValues(); DataSheet.getRange(LastRow,1).copyTo(DataSheet.getRange(LastRow+1,1)); //通し番号コピってます DataSheet.getRange(LastRow-1,42,2,48 ).copyTo(DataSheet.getRange(LastRow,42,2, 48));//42列目〜89列目APからCK コピってます。 DataSheet.getRange(LastRow+1,104).setValue(new Date());//打刻 //最終行の回答番号を取得して、開始セルも終了セルもそれにする(つまり1枚のみPDF生成) var LatestAnswer = DataSheet.getRange(LastRow+1,1).getValue(); Logger.log(LatestAnswer); ReferenceCell.setValue(LatestAnswer); EndCell.setValue(LatestAnswer); //////////////////// //以下、PDF生成から下書き作成まで //////////////////// var yourName = sheet.getRange("K1").getValue(); var gmailAddress = sheet.getRange("s3").getValue(); var filename = "結果_" + yourName +"様.pdf" createPDF2(driveID, ssID,sheetID, filename); //下の関数を実行 createDraft2(gmailAddress, yourName, filename); //下の関数を実行 LastRow += 1 LastRow_Answered += 1 } } } function createPDF2(folderid, ssid, sheetid, filename){ // PDFファイルの保存先となるフォルダをフォルダIDで指定 var folder = DriveApp.getFolderById(folderid); // スプレッドシートをPDFにエクスポートするためのURL。このURLに色々なオプションを付けてPDFを作成 var url = "https://docs.google.com/spreadsheets/d/SSID/export?".replace("SSID", ssid); // PDF作成のオプションを指定 var opts = { exportFormat: "pdf", // ファイル形式の指定 pdf / csv / xls / xlsx format: "pdf", // ファイル形式の指定 pdf / csv / xls / xlsx size: "A4", // 用紙サイズの指定 legal / letter / A4 portrait: "true", // true → 縦向き、false → 横向き fitw: "true", // 幅を用紙に合わせるか sheetnames: "false", // シート名をPDF上部に表示するか printtitle: "false", // スプレッドシート名をPDF上部に表示するか pagenumbers: "false", // ページ番号の有無 gridlines: "false", // グリッドラインの表示有無 fzr: "false", // 固定行の表示有無 gid: sheetid // シートIDを指定 sheetidは引数で取得 }; var url_ext = []; // 上記のoptsのオプション名と値を「=」で繋げて配列url_extに格納 for( optName in opts ){ url_ext.push( optName + "=" + opts[optName] ); } // url_extの各要素を「&」で繋げる var options = url_ext.join("&"); // optionsは以下のように作成しても同じです。 // var ptions = 'exportFormat=pdf&format=pdf' // + '&size=A4' // + '&portrait=true' // + '&sheetnames=false&printtitle=false' // + '&pagenumbers=false&gridlines=false' // + '&fzr=false' // + '&gid=' + sheetid; // API使用のためのOAuth認証 var token = ScriptApp.getOAuthToken(); // PDF作成 var response = UrlFetchApp.fetch(url + options, { headers: { 'Authorization': 'Bearer ' + token } }); // var blob = response.getBlob().setName(filename); //} // PDFを指定したフォルダに保存 folder.createFile(blob); } ////////////////////////////////////////// //CREATE DRAFT ////////////////////////////////////////// function createDraft2(gmailAddress, yourName, filename){ //var accessToken = e.messageMetadata.accessToken; //GmailApp.setCurrentMessageAccessToken(accessToken); var attachedPDF = DriveApp.getFilesByName(filename).next(); var body = yourName + "様\n" + "\n"+ "結果をお送りいたします。\n"+ "添付ファイルをご確認くださいませ。\n"+ "\n"+ GmailApp.createDraft(gmailAddress, "結果", body,{attachments:[attachedPDF]}); }

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

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

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

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

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

sawa

2020/10/07 04:17

回数というよりは実行時間なんで、1日 288回でも 1回あたり10秒平均くらいなら問題ないですよ。 https://qiita.com/mitonattou919/items/de415bb9302a52d52e2e ただ、検索もしくは質問すべきは、 > 現在実行中のスクリプトが完了次第、準備ができるまで待ってもらう という方法ではなくて、 >フォームを同時に送信されると、エラーになってしまいます。 を解決する方法だと思うので、どういうコードでどういうエラーが発生してるかを書いて質問した方がよいです。
yoichiyy

2020/10/09 09:05

どうもありがとうございました。 スクリプト実行中には、 その同じスクリプトを実行することはできない」ということで、 これを解決するために「順番待ち」のようなことができるのかどうかという質問に変更致しました。 もしも、そういった方法がないようであれば、 5〜10分おきに、まとめて自動返信を送るようなスクリプトに変更をしようと思います。 アドバイスを、どうもありがとうございました!
papinianus

2020/10/11 14:14

script lock の機能がありますが、起こっている問題を再現させられないことには適切な回答は不可能だと思います。 再現可能なミニマルなコードを提示してくださいませんか?
yoichiyy

2020/10/12 06:55

ご検討くださり、どうもありがとうございます。 只今、コードを追加致しました。 アドバイスをいただけますと幸いです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問