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

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

新規登録して質問してみよう
ただいま回答率
85.31%
Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google フォーム

Google フォームは、 Google社が提供しているアンケートフォーム作成および集計ができる無料のツール。Googleアカウントがあれば利用が可能です。集計データは、スプレッドシートに収集され、データ分析もできます。

Gmail

GmailとはGoogleによって提供されているウェブメールのサービスのことです。

Google Apps Script

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

Q&A

解決済

1回答

2556閲覧

【GAS】Googleフォーム回答後、承認者に送られる「承認用」と「否認用」のURLをクリックするとエラー

julie___

総合スコア1

Google スプレッドシート

Google スプレッドシートは、フリーで利用できる表計算ソフト。Webアプリのためインターネットに接続することで利用できます。チャートやグラフの作成のほか、シートを他のユーザーと共有したり、同時に作業を進めることも可能です。

Google フォーム

Google フォームは、 Google社が提供しているアンケートフォーム作成および集計ができる無料のツール。Googleアカウントがあれば利用が可能です。集計データは、スプレッドシートに収集され、データ分析もできます。

Gmail

GmailとはGoogleによって提供されているウェブメールのサービスのことです。

Google Apps Script

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

0グッド

1クリップ

投稿2023/07/06 09:34

編集2023/07/06 09:36

実現したいこと

GoogleフォームとGASを使って休暇申請承認フローを組もうと考えています。

  1. Googleフォームで休暇申請
  2. Gmailで承認者にメッセージが送信される
  3. 同時に、スプレッドシートの最終列「ステータス」には「確認中」と入力される
  4. 承認者が承認/否認いずれかのURLを押す
  5. 同時に、承認者のWebページに承認/否認のいずれかが表示される
  6. 同時に、承認/否認の結果がスプレッドシートに反映される
  7. 同時に、申請者にも承認/否認の結果がメールで送信される

前提

もともと作ったことのあるGASや、調べたものを組み合わせながら作成していました。
参考にした主なサイトは以下の通りです。
https://tonari-it.com/gas-workflow-url-parameter/
https://solutions.system-exe.co.jp/appremo/blog/self-workflow

「実現したいこと」の3.まではうまくいくのですが4.でリンクを押すと以下のエラーメッセージが表示されます。
承認/否認いずれのリンクを押しても同じ表示です。どなたかお力添えいただけますと幸いです。

補足情報

  • 2.について、HTMLメールの書き方がわからなかったのでプレーン版のみです。
  • 2.について、メール本文の作成にあたっては別件で作ったものを使用&こちらのサイトを参考にさせていただいています。https://tonari-it.com/gas-form-autoreply/
  • 2.について、セルの値を取得に際して「values」などは使えていません。そのためかなり冗長なスクリプトとなっています。
  • スプレッドシート、URL名などは伏せてあります。
  • 事情により一部タイ語併記しております。

発生している問題・エラーメッセージ

ReferenceError: sheet is not defined(行 21、ファイル「doGet」)

試したこと

「sheet is not defined」とのことなので、「doGet」のほうではIDとシート位置でスプレッドシートを指定しましたが、エラーは解消されませんでした。

該当のソースコード

GAS

1function autoSend() { 2 var sheet = SpreadsheetApp.getActiveSheet(); 3 var row = sheet.getLastRow(); 4 var url 5 = "https://script.google.com/a/macros/●●●●●/exec" //Released Web Application 6 + `?row=${row}&answer=`; 7 8 var timestamp = sheet.getRange(row, 1).getValue(); 9 var mail = sheet.getRange(row, 2).getValue(); 10 var name = sheet.getRange(row, 3).getValue(); 11 var leavedate = sheet.getRange(row, 4).getValue(); 12 var returndate = sheet.getRange(row, 5).getValue(); 13 var days = sheet.getRange(row, 6).getValue(); 14 var ampmall = sheet.getRange(row, 7).getValue(); 15 var hour = sheet.getRange(row, 8).getValue(); 16 var type = sheet.getRange(row, 9).getValue(); 17 var reason = sheet.getRange(row, 10).getValue(); 18 var document = sheet.getRange(row, 11).getValue(); 19 20 sheet.getRange(row,13).setValue("confirming_กำลังยืนยัน"); 21 22 // Specify date format 23 timestamp = Utilities.formatDate(timestamp, "GMT+7", 'E MMM dd yyyy HH:mm'); 24 leavedate = Utilities.formatDate(leavedate, "GMT+7", 'E MMM dd yyyy'); 25 returndate = Utilities.formatDate(returndate, "GMT+7", 'E MMM dd yyyy'); 26 // Display formatted date and time in run log 27 console.log(timestamp) 28 29 var Recipient = sheet.getRange(row, 12).getValue();//destination 30 var title = "[Request for approval] Request for leave";//emailtitle 31 var options = { 32 from:"●●●●●@●●●●●.com", 33 cc:mail 34 };//sender and cc 35 36 // Content of Email 37 var mail_body 38 = "Hello,\n" 39 + "You have received a new request with the following information.\n" 40 + "Please approve or deny this request.\n" 41 + "คุณได้รับคำขอใหม่พร้อมข้อมูลต่อไปนี้\n" 42 + "โปรดอนุมัติหรือปฏิเสธคำขอนี้\n\n" 43 + "If you approve, please click the URL below.(หากคุณอนุมัติ โปรดคลิก URL ด้านล่าง)\n" 44 + url + "ok\n" 45 + "If you deny, please click the URL below.(หากคุณปฏิเสธ โปรดคลิก URL ด้านล่าง)\n" 46 + url + "ng\n" 47 + "--------------------------------------\n" 48 + "Date of request\n" 49 + timestamp + "\n\n" 50 + "1) Full Name (ชื่อ-สกุล)\n" 51 + name + "\n\n" 52 + "2) Leave date (วันที่ต้องการลา)\n" 53 + leavedate + "\n\n" 54 + "3) Return date (วันที่กลับเข้าทำงาน)\n" 55 + returndate + "\n\n" 56 + "4) Number of leave day(s) (จำนวนวันที่ลา)\n" 57 + days + "\n\n" 58 + "5) AM/ PM/ All day/ Hour (ช่วงเวลาที่ลา: ทั้งวัน/ เช้า/ บ่าย/ ชั่วโมง)\n" 59 + ampmall + "\n\n" 60 + "6) The actual time for Hour leave (เวลาจริงสำหรับการออกจากชั่วโมง)\n" 61 + hour + "\n\n" 62 + "7) Type of leave (ประเภทการลา)\n" 63 + type + "\n\n" 64 + "8) Reason for leave (เหตุผลการลา)\n" 65 + reason + "\n\n" 66 + "9) Documents for evidence (เอกสารหลักฐาน)\n" 67 + document + "\n\n" 68 + "---------------------------------------\n\n" 69 + "Regards,\n" 70 + "HR Department"; 71 72 GmailApp.sendEmail(Recipient,title,mail_body,options);//sendmail 73} 74 75function doGet(e) { 76 let spreadSheetId = "●●●●●"; 77 let spreadsheet = SpreadsheetApp.openById(spreadSheetId); 78 let sheet = spreadsheet.getSheets()[0]; 79 let row = e.parameter.row; 80 let answer = e.parameter.answer; 81 let result = { 82 ok: "approved_ที่ได้รับการอนุมัติ ", 83 ng: "denied_ปฏิเสธ" 84 }; 85 86sheet.getRange(row, 13).setValue(result[answer]); 87 88let html = "<h1>${result[answer]}</h1>"; 89 90var timestamp = sheet.getRange(row, 1).getValue(); 91var name = sheet.getRange(row, 3).getValue(); 92var leavedate = sheet.getRange(row, 4).getValue(); 93var returndate = sheet.getRange(row, 5).getValue(); 94var days = sheet.getRange(row, 6).getValue(); 95var ampmall = sheet.getRange(row, 7).getValue(); 96var hour = sheet.getRange(row, 8).getValue(); 97var type = sheet.getRange(row, 9).getValue(); 98var reason = sheet.getRange(row, 10).getValue(); 99var document = sheet.getRange(row, 11).getValue(); 100var approver = sheet.getRange(row, 12).getValue(); 101 102let recipient = sheet.getRange(row, 2).getValue();//destination 103let subject = "Request for leave $[result[answer]]"; 104let options = { 105 from:"●●●●●@●●●●●.com", 106 cc:approver 107} 108 109let mail_body 110= "Hello,\n" 111+ "Your request for leave has been $[result[answer]] with the following information.\n" 112+ "คำขอลาของคุณ $[result[answer]]โดยมีข้อมูลดังต่อไปนี้\n" 113+ "--------------------------------------\n" 114+ "Date of request (วันที่ขอ)\n" 115+ timestamp + "\n\n" 116+ "1) Full Name (ชื่อ-สกุล)\n" 117+ name + "\n\n" 118+ "2) Leave date (วันที่ต้องการลา)\n" 119+ leavedate + "\n\n" 120+ "3) Return date (วันที่กลับเข้าทำงาน)\n" 121+ returndate + "\n\n" 122+ "4) Number of leave day(s) (จำนวนวันที่ลา)\n" 123+ days + "\n\n" 124+ "5) AM/ PM/ All day/ Hour (ช่วงเวลาที่ลา: ทั้งวัน/ เช้า/ บ่าย/ ชั่วโมง)\n" 125+ ampmall + "\n\n" 126+ "6) The actual time for Hour leave (เวลาจริงสำหรับการออกจากชั่วโมง)\n" 127+ hour + "\n\n" 128+ "7) Type of leave (ประเภทการลา)\n" 129+ type + "\n\n" 130+ "8) Reason for leave (เหตุผลการลา)\n" 131+ reason + "\n\n" 132+ "9) Documents for evidence (เอกสารหลักฐาน)\n" 133+ document + "\n\n" 134+ "---------------------------------------\n\n" 135+ "Regards,\n" 136+ "HR Department"; 137 138GmailApp.sendEmail(recipient,subject,mail_body,options) 139 140return HtmlService.createHtmlOutput(html); 141} 142

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

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

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

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

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

bebebe_

2023/07/07 02:30

エディタのほうから直接「doGet」を実行しても同じエラーがでますか?
julie___

2023/07/07 04:08

コメントありがとうございます。不勉強ですみません!エディタは、「スクリプトエディタ」のことですよね。そこでスクリプトを作成して、デプロイ>新しいデプロイ>歯車マーク>ウェブアプリの順にクリックして「デプロイ」しました‥!
bebebe_

2023/07/07 05:02

コードを記入しているところですね。記入欄の上のほうに「実行」「デバッグ」「(関数名)」「実行ログ」とあるので関数名の「doGet」を選択して実行した場合にsheetのエラーはどうなるのか
julie___

2023/07/07 09:44

丁寧にご説明いただきありがとうございます。「doGet」のエディタで「実行」を押すと以下のエラーが実行ログに表示されました。 TypeError: Cannot read properties of undefined (reading 'parameter') doGet @ doGet.gs:5
bebebe_

2023/07/10 00:29

それならば、ほかのコードが実行されているかデプロイが更新していないことはないですか?
julie___

2023/07/10 02:53

ほかのコードが実行されているか➡実行されている様子はありません。 デプロイが更新していないか➡スクリプト更新のたびに、デプロイ>デプロイを管理>編集>新バージョンとしてデプロイしていました。 勤務先の企業が契約しているGSuiteなので、どこかで制限がかけられている可能性もありますかね‥? 何度もすみません、そしてありがとうございます。
bebebe_

2023/07/10 04:48 編集

となると原因が掴めないですね・・・ 地道にやるなら function doGet(e) { let spreadSheetId = "シートID"; let spreadsheet = SpreadsheetApp.openById(spreadSheetId); let sheet1 = spreadsheet.getSheets()[0]; let html = ""; if (e.parameters.answer == "approve") { html = "<h1>承認しました。</h1>"; sheet1.getRange(e.parameters.row, 11).setValue('承認'); } else { html = "<h1>否認しました。</h1>"; sheet1.getRange(e.parameters.row, 11).setValue('否認'); } return HtmlService.createHtmlOutput(html); } ぐらいの簡単な状態で [https://script.google.com/macros/s/[シートID]/exec?row=1&answer=approve]にアクセスして 動作するか確認して少しずつ追加していってどの段階でエラーになるか試してみてはどうでしょう。
julie___

2023/07/12 02:56

遅くなりまして申し訳ございません。「autoSend」のほうのurlは本当は「"https://script.google.com/a/macros/勤務先会社名.com/s/●●●●●/exec"」となっていたのでまるっと伏せてしまった形です!「勤務先会社名.com」を除くと全く一緒かと思います。 ご提案いただいた簡単なものから試してみて、またご報告させていただきます!よろしくお願いいたします。
julie___

2023/07/12 07:02

いただいたスクリプトでdoGetのほうを試してみましたが、早速エラーになりました。ただ、前に出たエラーとは文言が異なります。 「Google ドキュメント内でエラーが発生しました。このページを再読み込みするか、数分後にこのページをもう一度開いてみてください。Google ドキュメント エディタの詳細については、ヘルプセンターをご参照ください。」といった画面が表示されます。 そういえば、別件(Googleドライブ内のファイル名・URLを一覧で取得)について勤務先のIT担当者に問い合わせた際に「Drive APIのご利用が必要ですが、当社ではDrive APIのご利用を許可しておりません。」と回答をもらっていたことを思い出しました。今回のフローで、Drive APIは関係しそうですか?
bebebe_

2023/07/13 00:19

動作確認のURLはデプロイ管理のウェブアプリのURLの末尾に「?row=1&answer=approve」を追加したものにしてみてください。 DriveAPIはドライブのアクセスに関するものなので関係ないとは思いますが他に制限のようなことがされているのかもしれないですね。
bebebe_

2023/07/18 04:37

後は根本的な所ですが「doGet」というファイル名の21行目に問題があるという表示ではあるんですが関数名が「doGet()」が複数あったりしませんか?
julie___

2023/07/18 07:19

お返事ありがとうございます。初歩的な質問で大変恐縮ですが、関数名「doGet()」が複数あるかどうか、はどこで確認できますでしょうか‥?
bebebe_

2023/07/18 07:26

ファイル毎にCtrl+Fで「doGet」を検索するしかないかもしれません。 確認用のコードを入力しているファイル名は「doGet.gs」ですよね?
julie___

2023/08/16 07:58

お返事が遅くなりまして大変申し訳ございません‥!ファイル毎にCtrl+Fで「doGet」を検索しましたが、ファイル名「doGet.gs」の function doGet(e) { の1か所でしか引っかからなかったです。 ちなみに勤務先の情報通信部門にも問い合わせてみたところ、doGet関数については、制限をかけておらず、GASについて制限をかけているのはDrive APIに関する関数のみとのことです。 情報通信部門への問合せを通して新たに知った情報ですが、Googleドライブの標準機能として、承認機能があるとのことです。今回は残念ですがGASを書くのは諦めて、標準機能を活用しようと思います。 いろいろとご尽力いただいたにもかかわらず申し訳ございません‥。
guest

回答1

0

自己解決

自己解決しました!初歩的なミスでした。
あらためて見直したところ、クリックするとdoGet関数が動作するURL自体が間違っていました‥。
ウェブアプリケーションのURLからコピペし直したら正しく動きました。大変お騒がせしました。
それ以外にも少し手直しした部分があるので、正しいソースコードを貼ります。ご参考になれば幸いです。

GAS

1function autoSend() { 2 var sheet = SpreadsheetApp.getActiveSheet(); 3 var row = sheet.getLastRow(); 4 var url 5 = "https://script.google.com/a/macros/●●●●●/exec" //Released Web Application 6 + `?row=${row}&answer=`; 7 8 var timestamp = sheet.getRange(row, 1).getValue(); 9 var mail = sheet.getRange(row, 2).getValue(); 10 var name = sheet.getRange(row, 3).getValue(); 11 var leavedate = sheet.getRange(row, 4).getValue(); 12 var returndate = sheet.getRange(row, 5).getValue(); 13 var days = sheet.getRange(row, 6).getValue(); 14 var ampmall = sheet.getRange(row, 7).getValue(); 15 var hour = sheet.getRange(row, 8).getValue(); 16 var type = sheet.getRange(row, 9).getValue(); 17 var reason = sheet.getRange(row, 10).getValue(); 18 var document = sheet.getRange(row, 11).getValue(); 19 20 sheet.getRange(row,13).setValue("confirming_กำลังยืนยัน"); 21 22 // Specify date format 23 timestamp = Utilities.formatDate(timestamp, "GMT+7", "E MMM dd yyyy HH:mm"); 24 leavedate = Utilities.formatDate(leavedate, "GMT+7", "E MMM dd yyyy"); 25 returndate = Utilities.formatDate(returndate, "GMT+7", "E MMM dd yyyy"); 26 // Display formatted date and time in run log 27 console.log(timestamp) 28 29 var Recipient = sheet.getRange(row, 12).getValue();//destination 30 var title = "[Request for approval] Request for leave";//emailtitle 31 var options = { 32 from:"●●●●●@●●●●●.com", 33 cc:mail 34 };//sender and cc 35 36 // Content of Email 37 var mail_body 38 = "Hello,\n" 39 + "You have received a new request with the following information.\n" 40 + "Please approve or deny this request.\n" 41 + "คุณได้รับคำขอใหม่พร้อมข้อมูลต่อไปนี้\n" 42 + "โปรดอนุมัติหรือปฏิเสธคำขอนี้\n\n" 43 + "If you approve, please click the URL below.(หากคุณอนุมัติ โปรดคลิก URL ด้านล่าง)\n" 44 + url + "ok\n" 45 + "If you deny, please click the URL below.(หากคุณปฏิเสธ โปรดคลิก URL ด้านล่าง)\n" 46 + url + "ng\n" 47 + "--------------------------------------\n" 48 + "Date of request\n" 49 + timestamp + "\n\n" 50 + "1) Full Name (ชื่อ-สกุล)\n" 51 + name + "\n\n" 52 + "2) Leave date (วันที่ต้องการลา)\n" 53 + leavedate + "\n\n" 54 + "3) Return date (วันที่กลับเข้าทำงาน)\n" 55 + returndate + "\n\n" 56 + "4) Number of leave day(s) (จำนวนวันที่ลา)\n" 57 + days + "\n\n" 58 + "5) AM/ PM/ All day/ Hour (ช่วงเวลาที่ลา: ทั้งวัน/ เช้า/ บ่าย/ ชั่วโมง)\n" 59 + ampmall + "\n\n" 60 + "6) The actual time for Hour leave (เวลาจริงสำหรับการออกจากชั่วโมง)\n" 61 + hour + "\n\n" 62 + "7) Type of leave (ประเภทการลา)\n" 63 + type + "\n\n" 64 + "8) Reason for leave (เหตุผลการลา)\n" 65 + reason + "\n\n" 66 + "9) Documents for evidence (เอกสารหลักฐาน)\n" 67 + document + "\n\n" 68 + "---------------------------------------\n\n" 69 + "Regards,\n" 70 + "HR Department"; 71 72 GmailApp.sendEmail(Recipient,title,mail_body,options);//sendmail 73} 74 75function doGet(e) { 76 let spreadSheetId = "●●●●●"; 77 let spreadsheet = SpreadsheetApp.openById(spreadSheetId); 78 let sheet = spreadsheet.getSheets()[0]; 79 let row = e.parameter.row; 80 let answer = e.parameter.answer; 81 let result = { 82 ok: "approved_ที่ได้รับการอนุมัติ", 83 ng: "denied_ปฏิเสธ" 84 }; 85 86sheet.getRange(row, 13).setValue(result[answer]); 87 88let html = "<h1>" + result[answer] + "</h1>"; 89 90var timestamp = sheet.getRange(row, 1).getValue(); 91var name = sheet.getRange(row, 3).getValue(); 92var leavedate = sheet.getRange(row, 4).getValue(); 93var returndate = sheet.getRange(row, 5).getValue(); 94var days = sheet.getRange(row, 6).getValue(); 95var ampmall = sheet.getRange(row, 7).getValue(); 96var hour = sheet.getRange(row, 8).getValue(); 97var type = sheet.getRange(row, 9).getValue(); 98var reason = sheet.getRange(row, 10).getValue(); 99var document = sheet.getRange(row, 11).getValue(); 100var approver = sheet.getRange(row, 12).getValue(); 101 102let recipient = sheet.getRange(row, 2).getValue();//destination 103let subject = "Request for leave " + result[answer]; 104let options = { 105 from:"●●●●●@●●●●●.com", 106 cc:approver 107} 108 109// Specify date format 110timestamp = Utilities.formatDate(timestamp, "GMT+7", "E MMM dd yyyy HH:mm"); 111leavedate = Utilities.formatDate(leavedate, "GMT+7", "E MMM dd yyyy"); 112returndate = Utilities.formatDate(returndate, "GMT+7", "E MMM dd yyyy"); 113 114let mail_body 115= "Hello,\n" 116+ "Your request for leave has been " + result[answer] + " with the following information.\n" 117+ "คำขอลาของคุณ " + result[answer] + " โดยมีข้อมูลดังต่อไปนี้\n" 118+ "--------------------------------------\n" 119+ "Date of request (วันที่ขอ)\n" 120+ timestamp + "\n\n" 121+ "1) Full Name (ชื่อ-สกุล)\n" 122+ name + "\n\n" 123+ "2) Leave date (วันที่ต้องการลา)\n" 124+ leavedate + "\n\n" 125+ "3) Return date (วันที่กลับเข้าทำงาน)\n" 126+ returndate + "\n\n" 127+ "4) Number of leave day(s) (จำนวนวันที่ลา)\n" 128+ days + "\n\n" 129+ "5) AM/ PM/ All day/ Hour (ช่วงเวลาที่ลา: ทั้งวัน/ เช้า/ บ่าย/ ชั่วโมง)\n" 130+ ampmall + "\n\n" 131+ "6) The actual time for Hour leave (เวลาจริงสำหรับการออกจากชั่วโมง)\n" 132+ hour + "\n\n" 133+ "7) Type of leave (ประเภทการลา)\n" 134+ type + "\n\n" 135+ "8) Reason for leave (เหตุผลการลา)\n" 136+ reason + "\n\n" 137+ "9) Documents for evidence (เอกสารหลักฐาน)\n" 138+ document + "\n\n" 139+ "---------------------------------------\n\n" 140+ "Regards,\n" 141+ "HR Department"; 142 143GmailApp.sendEmail(recipient,subject,mail_body,options) 144 145return HtmlService.createHtmlOutput(html); 146}

投稿2023/08/18 04:14

julie___

総合スコア1

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問