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

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

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

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

Q&A

解決済

2回答

5589閲覧

Google Apps ScriptでHTMLフォームを利用した際の、リロード等による二重送信を防ぐ方法について

ploxolq.tt

総合スコア16

Google Apps Script

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

0グッド

0クリップ

投稿2020/03/25 08:40

編集2020/03/26 02:10

GASを使用して、
HTML上のフォームから入力した内容をスプレッドシートに記録したいと思い、
以下のようなものを(見よう見まねで)作りました。

function doGet() { let template = HtmlService.createTemplateFromFile('index'); return template.evaluate(); } function doPost(postdata) { let title = String(postdata.parameters.title); let content = String(postdata.parameters.content); let sheet = SpreadsheetApp.getActiveSheet(); sheet.appendRow([title, content]); let template = HtmlService.createTemplateFromFile('index'); return template.evaluate(); }

html

1<!DOCTYPE html> 2<html> 3 <head> 4 <base target="_top"> 5 </head> 6 <body> 7 <div class="main"> 8 <form method="post" action="公開用URL"> 9 <input type="text" name="title" required="required" /> 10 <textarea name="content" required="required"></textarea> 11 <input type="submit" value="送信する" /> 12 </form> 13 </div> 14 </body> 15</html>

幸い、フォームの内容を問題なくスプレッドシートに残すことができ、
それ自体は満足しているのですが、

ひとつ、
「リロードをすると、同じ内容のものがふたたび送信されてしまう」
という二重送信の悩みがあります。

POSTの内容が残ってしまっているからだということは何となく分かるのですが、
プログラミングの知識が乏しく、
どのように解決したらよいのか分かりません。

二重送信を防ぐための、なにか良いアイデアはございますでしょうか?

希望としては、
同一フォームから連続してデータを入力したいので、
送信後にサンクスページ等へ遷移するのではなく、
同じページに戻りたいと考えています(少なくとも見た目的には)。

もし解決策がありそうでしたら、
ご教示いただけますと幸いでございます。

何卒よろしくお願い申し上げます。


【追記】

  1. 「ユーザーに直接スプレッドシートを触ってもらいたくない」という理由で、スプレッドシート以外(フォームなど)の送信方法を探しています。

  2. 「データ入力だけでなく、入力データの表示等、複数の操作を行いたい」、また「見栄えや仕様感的に、HTML+CSSでページを作りたい」ため、できればGoogleフォームを使用しない方法を探しています。

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

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

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

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

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

papinianus

2020/03/25 10:19

google form や スプレッドシートを利用できない理由を教えて下さい
ploxolq.tt

2020/03/26 02:14

ご連絡ありがとうございます。 たしかに、Googleフォームを使えば簡単ですよね・・・。 素人の私にもピッタリの方法だと思います。 ただ、もし可能であれば、個人的な理想や興味もありつつ、できればGoogleフォームを使用しないで済む方法を探しています。 わがまま、かつ実現が難しいことかもしれませんが、もし方法をご存知でしたら、ご教示いただけますと幸いでございます。 疑似的な手法も含め、そもそも実現不可能ということであれば、別途Googleフォームを使用した方法を検討したいと思います。
guest

回答2

0

ベストアンサー

doGetはウェブアプリケーションの表示のために必要ですが

doPostを使わずにgoogle.script.run.withSuccessHandlerを使って入力内容を取得して普通にGAS側へ送れば良いのでは?と思います。

自分もGoogle Formは低機能なので、よくHTMLでフォーム作ってましたよ。ですが、その際には入力内容の精査なども含めて、そういった作りにしています。(殆どGoogle Form使わなくなりました))

Google Formは限界が非常に低いのでわかります。

当方で、業務で使ってる「ならでは」の事例をサンプル付でアップしてあるので良かったら使ってください。

参考:Google Apps Scriptで複数データを送信出来るフォームを作る

投稿2020/03/26 02:39

officeforest

総合スコア412

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

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

ploxolq.tt

2020/03/27 00:34

ご返答誠にありがとうございます。 こちらの要望をしっかりと汲んでいただき、本当にありがとうございます。 officeの杜!すばらしいですね!! 熟読したものの、まだまだ分からないところはあるのですが、 おおむね、流れは理解できました! google.script.runを使ってスプレッドシートに書き込みをしつつ、 Javascript+DOMを使って、フォーム送信したように疑似的に見せるような感じですよね? まさに理想的な形です! 本当にありがとうございます! すみません・・・一点だけお伺いしたいのですが、 ご共有いただいたページでは、 「google.script.run」 を使用しており、 実際にこちらでも試したところ、 うまく稼働したのですが(とくにreturnしたい値もなかったので)、 ご返答にもあったように、 google.script.run.withSuccessHandler を使用したほうがいいのでしょうか? すみません、両者の違いがいまひとつわからなくて・・・。
officeforest

2020/03/27 00:54

google.script.runはGASに処理をぶん投げておしまい。対して、google.script.run.withSuccessHandlerはぶん投げてGAS側からの返り値を受け取れます。 受け取って無事に処理が終わったら、終了画面をdivのdisplay属性でも使って「終わったよ」表示をしてみるとか、再度送信フォームを空にして受け付ける状態にするとかそういった処理が可能です。
ploxolq.tt

2020/03/27 07:41

ありがとうございます! 参考サイト含め、とても助かりました! これからもofficeの杜でいろいろ勉強したいと思います!
guest

0

二重送信対策は難しいんじゃないかなと思ってます。

javascript

1const doGet = () => HtmlService.createTemplateFromFile('249347').evaluate(); 2const processForm = (formObject) => { 3 SpreadsheetApp.getActiveSheet().appendRow([formObject.title,formObject.content]); 4 return; 5}

html

1//249347.html 2<!DOCTYPE html> 3<html> 4<head> 5 <base target="_top"> 6 <script> 7 // Prevent forms from submitting. 8 function preventFormSubmit() { 9 var forms = document.querySelectorAll('form'); 10 for (var i = 0; i < forms.length; i++) { 11 forms[i].addEventListener('submit', function (event) { 12 event.preventDefault(); 13 }); 14 } 15 } 16 17 window.addEventListener('load', preventFormSubmit); 18 19 function handleFormSubmit(formObject) { 20 google.script.run.withSuccessHandler(reset).processForm(formObject); 21 } 22 23 function reset() { 24 document.getElementById("title").value = ""; 25 document.getElementById("content").value = ""; 26 } 27 </script> 28</head> 29<body> 30<div class="main"> 31 <form method="post" onsubmit="handleFormSubmit(this)"> 32 <input type="text" id="title" name="title" required="required" /> 33 <textarea name="content" id="content" required="required"></textarea> 34 <input type="submit" value="送信する"/> 35 </form> 36</div> 37</body> 38</html>

投稿2020/03/26 14:01

papinianus

総合スコア12705

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

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

ploxolq.tt

2020/03/27 00:35

ご返答誠にありがとうございます。 しかも、ご丁寧にコードまでつけていただいて・・・本当に助かります。 知識が浅く、分からない部分もあるので、じっくりと研究させてください。 1点だけ質問があるのですが(ちょうど他の回答者様にも同様の内容を尋ねているのですが・・・)、 google.script.run.withSuccessHandler につきまして、 単にスプレッドシートにデータを書き込むだけであれば、 google.script.run でも同様の動きをしてくれると思うのですが、 google.script.run.withSuccessHandler にした方がよろしいのでしょうか?
papinianus

2020/03/27 03:53

成功したときにフォームをクリアしないと同じデータが入りますよ? まあ、送信連打にも対応してないですが。
ploxolq.tt

2020/03/27 07:43

たしかに、そうですね。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問