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

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

ただいまの
回答率

88.32%

(GAS)メール本文に記載したURLリンクの押下をトリガにしてスプレッドシートに値を入力したい。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 4,222

hkagesb

score 13

 前提・実現したいこと

Google Apps Scriptで物品の購入申請、承認フローを作成したいと考えております。
(以下のようなフローです)

1.物品を購入したい人がフォームで申請(物品の種類、数量、金額、など)
2.フォームで申請した内容をスプレッドシートに自動で記載。承認者に申請内容を自動でメール。
3.承認者へのメール内容は、本文に申請内容(物品の種類、数量、金額、など)を記載し、「承認」「否認」のURLリンクも記載する。
4.承認者が「承認」若しくは「否認」のURLリンクを押すと、『承認しました』若しくは『否認しました』と記載したHTMLを表示。更にこのタイミングで、該当の申請に対し、スプレッドシート上の新たな列に【承認】or【否認】と入力したい。


【更新】
回答でご指摘頂いた内容について本文にも追記します。
・書き込むスプレッドシートはidで特定して、その中のシート『フォームの回答』に書き込みを行う。
・『フォームの回答』シートには、フォームから申請された情報が入力されている。
タイトル行(A1~I1)には以下のタイトルが記入済み(タイムスタンプ、メールアドレス、氏名、部門、
機材種別、購入希望日、商品名、商品URL、個数)。
2行目以下はフォームからの申請内容が入力されている。

・『承認』の場合はJ列に"〇"を、『否認』の場合はJ列に"×"を入力したい。
(タイムスタンプが一致する行に対して。)

【再更新】
フォームの入力内容を追加する必要が出たので、
『承認』『否認』の結果入力をJ列ではなく、N列(14列目)に変更したいです。
N列に"〇"、"×"を入力したい。

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

実現したいことの4.の途中までは出来ました。
『更にこのタイミングで、該当の申請に対し、スプレッドシート上の新たな列に【承認】or【否認】と入力したい。』の部分が出来ていません。

メール本文に記載したURLリンクの押下をトリガにしてスプレッドシートに値を入力する事は出来るのでしょうか。
フォームから申請すると、スプレッドシート上にタイムスタンプが自動で入力されるので、
タイムスタンプを検索して、該当の申請に対して【承認】【否認】を入力したいと思っています。

 該当のソースコード

●send_email.gs

function sendHtmlMail(e) {

var answer1 = e.namedValues['購入者 氏名']; //フォーム作成時に設定した項目名
var answer2 = e.namedValues['部門']; //フォーム作成時に設定した項目名
var answer3 = e.namedValues['商品名']; //フォーム作成時に設定した項目名
var answer4 = e.namedValues['数量']; //フォーム作成時に設定した項目名
var answer5 = e.namedValues['単価(税込み)']; //フォーム作成時に設定した項目名
var answer6 = e.namedValues['購入理由']; //フォーム作成時に設定した項目名
var answer7 = e.namedValues['購入先(URL等)']; //フォーム作成時に設定した項目名
var answer8 = e.namedValues['優先度']; //フォーム作成時に設定した項目名

var subject = '備品購入申請のお知らせ'; //件名
var body = 'htmlメールが表示できませんでした'; //本文(表示不可時)

var timeStamp=e.namedValues["タイムスタンプ"];

/* メール本文 */
var html = "備品購入申請がありますので承認をお願い致します。<br><br>";
html += "申請内容<br><br>";

html += "購入者 氏名:" + answer1 + "<br>";
html += "商品名:" + answer3 + "<br>";
html += "数量:" + answer4 + "<br>";
html += "単価(税込み):" + answer5 + "<br>";
html += "購入理由:" + answer6 + "<br>";
html += "購入先(URL等):" + answer7 + "<br>";
html += "優先度:" + answer8 + "<br>";

html += "タイムスタンプ:" + timeStamp + "<br>";

html += "承認しますか?<br><br>";

/* 承認・否認 */    
html += '<a href="https://script.google.com/***/exec?p=ok&t='+timeStamp+'">承認</a><br>';
html += '<a href="https://script.google.com/***/exec?p=ng&t='+timeStamp+'">否認</a><br>';

/* メールを送信 */
if
(answer2 == '1課') {
GmailApp.sendEmail(
'メールアドレス1',
subject, 
body,
{
htmlBody: html
}
);
}

else if
(answer2 == '2課') {
GmailApp.sendEmail(
'メールアドレス2',
subject, 
body,
{
htmlBody: html
}
);
}

else
{
GmailApp.sendEmail(
'メールアドレス3',
subject, 
body,
{
htmlBody: html
}
);
}
}


●ok.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1>備品購入申請を承認しました</h1>
あなたは備品購入申請を承認しました
</body>
</html>


●ng.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1>備品購入申請を否認しました</h1>
あなたは備品購入申請を承認しませんでした
</body>
</html>


●Error.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
URLが正しくありません。ここはエラーページです<br><br>

</body>
</html>


●doGet.gs

function doGet(e){
var page=e.parameter["p"];
var timeStamp=e.parameter["t"];

if(page == "ok" && timeStamp){
setter(timeStamp, "○");
return HtmlService.createHtmlOutputFromFile('ok');
}
else if(page == "ng" && timeStamp){
setter(timeStamp, "×");
return HtmlService.createHtmlOutputFromFile('ng');
}

else{
return HtmlService.createHtmlOutputFromFile('Error');
}

}
function setter(timestamp, str) {
var sh = SpreadsheetApp.openById("スプレッドシートID").getSheetByName("フォームの回答");
var vals = sh.getDataRange().getValues();
var row = -1;
for(var i = 1; i < vals.length; i++) {
if(Utilities.formatDate(vals[i][0], "JST", "yyyy/MM/dd HH:mm:ss") == timestamp) {
row = i + 1;
}
}
if(row != -1) {
sh.getRange(row, 14, 1, 1).setValue(str);
}  
}


 試したこと

1.申請フォーム作成済み。
2.フォームの送信をトリガにして承認者へ承認依頼メールを送信→作成済み。
3.承認者へのメール(申請内容、「承認」「否認」のURLリンクも記載)→作成済み。
4.「承認」若しくは「否認」のURLリンクを押すと、『承認しました』若しくは『否認しました』と記載したHTMLを表示。→作成済み。

「承認」若しくは「否認」のURLリンクを押すことで承認したか否認したかを判断して、その内容をスプレッドシートに記入したい(タイムスタンプでどの申請かを判定)と考えておりますが、そのようなことが可能なのか、どのようにすれば良いか分かりません。

当方GASはおろかプログラミング自体が素人のため、ネットで色々調べてソースをコピペしたりしながらなんとか途中まで作成しました。
その為、ソースのちょっとした修正や、キーワードだけでの説明を理解することが難しい為、ご回答頂ける場合は極力ソースコードなども省略せず記載頂けますと幸いです。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

doGet.gsで、returnする前に、書き込みをすればよいと思います。

ソースコードですが、書き込むべきスプレッドシートはどうやって特定するのか(スプレッドシートのidなのか、driveのフォルダidとスプレッドシートの名前の組み合わせなのか)や、そのスプレッドシートの何というシートのどこのセルに、何と何を書き込むのかを具体的に仕様として示していただかない限り、有意な回答は得られないと思います。

-- 追記
今のままではタイムスタンプが送信されないので

html += '<a href="https://*****/exec?p=ok&t='+timeStamp+'">承認</a><br>';
html += '<a href="https://*****/exec?p=ng&t='+timeStamp+'">否認</a><br>';


のようにしてください。するとクリック時にタイムスタンプが送信できます。

その状態で

function doGet(e){
  var page=e.parameter["p"];
  var timeStamp=e.parameter["t"];

  if(page == "ok" && timeStamp){
    setter(timeStamp, "○");
    return HtmlService.createHtmlOutputFromFile('ok');
  }
  else if(page == "ng" && timeStamp){
    setter(timeStamp, "×");
    return HtmlService.createHtmlOutputFromFile('ng');
  }

  else{
    return HtmlService.createHtmlOutputFromFile('Error');
  }

}
function setter(timestamp, str) {
  var sh = SpreadsheetApp.openById("").getSheetByName("フォームの回答");
  var vals = sh.getDataRange().getValues();
  var row = -1;
  for(var i = 1; i < vals.length; i++) {
    if(Utilities.formatDate(vals[i][0], "JST", "yyyy/MM/dd HH:mm:ss") == timestamp) {
      row = i + 1;
    }
  }
  if(row != -1) {
    sh.getRange(row, 14, 1, 1).setValue(str);
  }  
}


とやると、書き込みができるのではないかと思います。

--- 追記
下記のテスト関数を追加して、関数を実行からテストして書き込まれるか見ていただけますか?

function test() {
var timestamp = "シートにあるタイムスタンプ"; //固定値
var str = "○";
setter(timestamp, str);
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/10/16 15:56

    度々ありがとうございます。
    動作確認させて頂きましたがやはり〇×の書き込みは上手く行きませんでした。
    何か環境による違いもあるのでしょうか。もう少し動作確認させて頂きます。

    キャンセル

  • 2018/10/17 13:02

    何度も紆余曲折させてしまって申し訳なくまたそのことが上手く行かない原因なのは理解しておりますので、
    sendmail.gsとdoGet.gsの最新状態を質問に追記していただくことはできませんでしょうか?

    キャンセル

  • 2018/10/17 13:54

    こちらこそ長らくサポート頂きありがとうございます。
    コードを最新の状態に更新させて頂きました。ご確認の程お願いいたします。

    キャンセル

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

  • ただいまの回答率 88.32%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る