ASCASO社のエスプレッソマシンのマニュアル和訳したり、映画の感想文、たまに恋愛相談。

tomatojuicer222's diary

ASCASO社エスプレッソマシンのマニュアル和訳を進めたり、映画の感想文、たまに恋愛相談

google apps scriptで簡単なwebアプリを作ってみた

googlespreadsheet(つまりいわゆるエクセル的な)にデータベース様のテーブルを作っておき、このシートを開けないスマホやマック環境でも、HTMLフォームから更新できるようにする。

 

tomatojuicer222.hatenablog.com

 

・おおざっぱな流れは以下。
シート上にテーブルのひな形を作成する。
ここではレコードが増えた場合も表示をスムーズにするため、入力規則やセル内の計算式を使用しない。つまり手動ならなんでも書けてしまう様なシートを作っておく。
代わりにHTMLのフォーム側で値チェック等を行い、検索に差し支えるような誤入力を抑止する設計とする。

サーバー側のjavascript処理をコーディング/フォーム側のHTML(CSS,javascript含む)で画面作成し、大枠が完成したらプロジェクトをWEB上に公開する。
公開したURLにアクセスすると、サーバー上ではdoGet()メソッドが呼ばれる。
このdoGet()メソッドに、作成したHTMLで描画するコードをHTMLserviceクラスを使って書いておく。
HTMLからの応答方法としては、html側でinput type="button"のonClickに、google.script.runすればよい。

ここまではググればすぐでてくるので詳細は割愛。

・以降あんまりググっても書いてなかった、どハマりした点メモ。

・引数に設定できる値が限られているので注意。
google.script.runで呼び出す際の引数は種類が限られている。基本はまぁformを渡すんだけど、この場合HTMLのformオブジェクトがそのまま渡るわけではなく、formの各要素の値がneme:valueのマップ形式で通知されてるっぽい。
そのためbuttonなど(一般的なsubmitボタンで渡る)一部の項目についてはvalueがとれないので要注意。
たとえば押したボタンによって参照するデータを区別する、みたいなことをする場合、次に書く通りブラウザ側で処理してから渡さないとダメ。

複数formの取扱い/input要素の取扱い。
複数フォームを用意して、押したボタンによってどちらかのフォームか判定、送信用の抽象フォームに移し替える、みたいな処理。
ググると結構でてくるからメジャーなやり方なんだろうけど、onclick処理に入った時点で各formの値にアクセスする方法は結構嘘ばっかり。まともに通るサンプルソースに出会えなかった。
具体的にはサンプルの「document.formhidden」の時点では認識できてるんだけど、その先の.nameからはブラウザによって動いたり動かなかったり。

<!--うまく動かないダメな例です!!!-->
    <!--送信に使う抽象フォーム-->
    <form name="formhidden">
         <input type="hidden" name="radio" value="">
         <input type="hidden" name="rank" value="">
    </form>
    <!--記入用フォーム1-->
    <form name="forminput1">
         <input type="radio" name="r1" value="1">
         <input type="text" name="rank1" >
         <input type="button" name="b1" onclick="sendForm1(this.parentNode)">
    </form>
    <!-記入用フォーム2-->
    <form name="forminput2">
         <input type="radio" name="r2" value="2">
         <input type="text" name="rank2" >
         <input type="button" name="b2" onclick="sendForm2(this.parentNode)">
    </form>

    <script>
        function sendForm1(form){ //フォーム1からの送信
         document.formhidden.radio = form.r1;
         sendForm(document.formhidden);
        }

        function sendForm2(form){ //フォーム2からの送信
         document.formhidden.radio = form.r2;
         sendForm(document.formhidden);
        }

        sendForm(form){
         //サーバーに送信
         google.script.run.send(form);
        }
    </script>
<!--うまく動かないダメな例ここまで-->

これをまともに動かすは、idとnameの違いをきちんと理解する必要がある。

  • id:全要素で重複があってはいけない
  • name:inputのtype="radio"に代表されるように、重複がある前提

つまりnameは受け取ったサーバー側でvalueを取るためのものであり、本来要素の特定に使うものではない!
「document.name」で値をとってくること自体が(十分に注意して設計した場合に)一部ブラウザのみで使えるおまけ機能であって、基本的にNGと思っとけばよさそう?
個別に特定可能な要素には全てidを振っておき「document.getElementById("id")」で取得する。
ラジオボタンみたいなnameまでしか特定できないものは「document.getElementsByName("name")」で一度同じnameグループの要素リストを取得する。
このリストには配列の添え字でアクセス可能なので、具体的には以下の例のようにやれば選択した(checkedな)値をとることができる。

    var i;
    var selectedval;
    var elements = document.getElementsByName("name");
    for (i=0; i<elements.length; i++){
     if(elements[i].checked){
      selectedval = elements[i].value;
     }
    }

このへんをちゃんとやらずに.nameでアクセスしようとすると、
1.配列の先頭が取れる
2.undefinedな値でエラーになる(これがHTML標準なのかな?)
3.選択したラジオボタンのvalueがとれる(一部ブラウザのみのおまけ機能、一見ただしく動いて見える)
あたりが環境によってまちまちに動く。このへんが冒頭の不具合の原因。

同じ理屈はselectにもいえて、やっぱりID指定や.nameでselect要素自体を指定しても、配下option要素のvalueはとれない。
ここもselect要素をidで取得したら、「.options」プロパティで配下optionリストを取得する。
このリストには配列の添え字でアクセス可能かはよくわからん。ちょっと複雑だが以下。
何番目のoptionが選択されたかという情報を「.selectedIndex」プロパティで取得し、
options側で持ってるアクセサメソッド「.item()」にこのselectedIndexを指定する。
これで選択した(selectedな)option要素の値をとることができる。

    var select = document.getElementById("selectid");
    var options = document.getElementById("selectid").options;
    var selectedvalue = options.item(select.selectedIndex).value;

・spreadSheetAppのスプレッドシート特定方法
スプレッドシートを操作する方法はググればでてくるので割愛。
ただしwebアプリ的に使う場合、シートと連携しているGASであってもactivecheetではとれない。
openByIdみたいなメソッドを使って明示的に開く必要がある。
ここでいうIDはシートのURLのうち、aaa/d/XXXXXX/aaa のXXXXXX部分。
とりあえずグローバル変数に固定値で保持しておく。
動的に指定のシートを取れるよなうまい取り方がないものか模索中。(公開することを想定して)


・その他
この辺のうまくいかなかった点は、ググってもわからなかった項目で、何度も試行を繰り返すなかでなんとか解決してきた。
そんなことをやってたら「一秒当たりのスクリプト実行回数が多すぎます」みたいなエラーがでたよ。
おそらくこの24時間で500~1000くらいの回数実行してるから、その辺のどっかに実行回数の制限ポイントがあるんだろうな。ググっても出てこなかったけど。