GoogleAppsScriptを使ってGoogleフォームの画面を自由にカスタマイズする!

GoogleAppsScript
スポンサーリンク

今回の目的

Googleフォームを使って大人数のイベントの企画や、会社等で管理台帳を作成するときに、関係者に必要事項を入力してもらうことがあると思います。しかし、Googleフォームで作成した画面は作りやすくシンプルな分少し物足りなさを感じるかもしれません。そういったときに、自作のオシャレな画面をGoogleフォームの入力画面の代わりに使用できるといいと思いませんか?

今回はGASとGoogleフォームを使って簡単にお問い合わせフォームの作成をします。

簡単といってもHTMLとCSSの知識は必要ですが・・・(汗)

またGoogleフォームに入力した内容はGoogleスプレッドシートでまとめるためその方法や、Googleドライブに配置した画像を画面の背景に使用する方法など、G Suiteをフル活用して進めていきます。

実際に作ったフォーム画面

実際に私が日常で使えるモノを作ってみようと思い、光熱費申請フォームを作ってみましたのでご紹介します。

まずこちらはGoogleフォームで作ったデフォルトのフォームです。

入力する項目は支払い年月、金額、申請内容の3つでシンプルにしています。少し物足りない感じがします。

では次にGASを使って作った自作のフォームです。

項目は同様に支払い年月、金額、申請内容の3つです。

どうでしょうか?だいぶオシャレになったと思います。

Googleのアカウントを持っていて1度許可すれば、だれでもURLを打つだけで使えるので、複数人で使うこともできます。もちろんスマホでも使えます。

Googleフォームと自作のフォームのどちらのフォームで送信しても同じスプレッドシートに集計されます。

背景に使っている画像はカフェで働いている友人に「いい感じの写真ちょうだい。」といってもらいました(^^)

背景もだいぶ明るくなって入力するときにワクワク感がでるのでオススメです。

①Googleフォームでフォームの作成

GASの実装は次回にするので、その下準備としてGoogleフォームの作成をします。

Googleフォーム画面の作成

まずGoogleドライブを開き、「新規」>「その他」>「Googleフォーム」を選択します。

これで新規のGoogleフォーム画面が開きます。

この画面で項目を1つずつ作成します。

上からタイトルと3項目を入力してください。

  • タイトル:光熱費申請フォーム
  • 支払い年月:日付
  • 金額:記述式
  • 申請内容:ラジオボタン
    • 項目:電気、ガス、水道

ここまで出来たら右上の「プレビュー」を押すと別タブでフォームが表示されます。このURLを使うことで次回からもこのフォームを入力することができるようになります。

Googleスプレッドシートと紐づける

Googleフォームが出来上がったらフォームの入力内容をスプレッドシートに自動で書きこむように紐づけを行います。

上の方の「回答」を選択します。そうすると画面が切り替わるので、緑のスプレッドシートの作成アイコンをクリックします。

新しいスプレッドシートを作成に選択して作成をクリックすると、新しく作成したGoogleスプレッドシートにこちらのフォームが紐づけられます。

②GASの準備

GASでHTMLとCSSを使えるようにします。まずはGASで自分で書いたHTMLを公開します。

以下の記事の内容を前提として進めていきます。

まずはファイルを用意します。ファイルは大きく3つです。

デフォルトであるコード.gsに加えform.htmlとform.css.htmlを新規で作成します。

管理しやすいようにHTMLはform.htmlに記載し、CSSはform.css.htmlに記載します。

コード.gs

コード.gsはサイトを開いたときに一番に呼ばれます。

ここにform.htmlを返す処理とform.css.htmlを読み込み処理を書きます。

これはこのままコピペで問題ないです。

//URLをたたいたときに呼ばれる
function doGet(req) {
  const template = 'form';
  return HtmlService.createTemplateFromFile(template).evaluate();
}
// CSSを読み込む関数
function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename).getContent();
}

form.html

詳細な内容は後ほど記載するので今は大枠だけ記載します。

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <meta charset="utf-8">
    <!-- form.cssの読み込みはコード.gsに作成した関数で行う -->
    <?!=include('form.css');?>
    <title>光熱費申請フォーム</title>
  </head>
  <body>
  <main>
    <!-- ここにフォームの内容を記載する -->
  </main>
    <!-- jQueryのCDNを読み込んで使えるようにする -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script>
      <!-- jQueryの処理はここに記載 -->
    </script>
  </body>
</html>

CSSとjQueryをそれぞれ読み込みます。jQueryは簡易的なバリデーションチェックに使用するので、特にチェックがいらない場合は使わなくても問題ありません。

form.css.html

CSSも大枠だけ記載しておきます。GASでcssの拡張子は使えないのであくまでhtmlファイルであることは覚えておきましょう。

<style>
* {
    font-family: 'Montserrat', Arial, Helvetica, sans-serif;
}

main {
    width: 100vw;
    margin: auto;
    color: #fff;
}
</style>

サイトの公開

ここまで作成したら一度公開してURLからページが見れることを確認しましょう。

「公開」>「webアプリケーションとして公開」から公開します。

詳細な方法は先ほどの記事から確認してください。

③自作フォームの作成

次にHTMLで自作のフォームを作り、画面から入力できるようにします。

Googleフォームで作成した項目に合わせてinputタグで項目を作ります。今回は日付と数値とラジオボタンを設置します。

formタグの中にそれぞれinputタグを記載して入力できるようにします。

idとclass属性はcssをコピペしてた時に割と適当に付けているので統一性はないです。

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <meta charset="utf-8">

    <?!=include('form.css');?>
    <title>光熱費申請フォーム</title>
  </head>
  <body>
    <main>
        <div class="container">
            <form id="form" action="" method="POST">
            <h1>光熱費申請フォーム</h1>
                <!-- 支払い日付 -->
                <div class="block">
                    <label for="calendar" class="block-title">支払い年月</label>
                    <input type="date" id="calendar">
                </div>
                <!-- 金額 -->
                <div class="block">
                    <label for="cost" class="block-title">金額</label>
                    <div class="cost-group">
                        <input type="number" name="cost" id="cost"><span>円</span>
                    </div>
                </div>
                <!-- 申請内容 -->
                <div class="block">
                    <label class="block-title">申請内容</label>
                    <div class="radio-wrapper">
                        <input type="radio" id="detail1" name="detail" class="radio-inline__input" checked>
                        <label for="detail1" class="radio-inline__label">電気</label>
                        <input type="radio" id="detail2" name="detail" class="radio-inline__input">
                        <label for="detail2" class="radio-inline__label">ガス</label>
                        <input type="radio" id="detail3" name="detail" class="radio-inline__input">
                        <label for="detail3" class="radio-inline__label">水道</label>
                    </div>
                </div>
                <div class="button-wrapper">
                    <span class="submit">送信</span>
                </div>
            </form>
        </div>
     </main>
    <!-- jQueryのCDNを読み込んで使えるようにする -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script>
      <!-- jQueryの処理はここに記載 -->
    </script>
  </body>
</html>

ここからがとても重要です。

このフォームの送信先(action属性)と送信する値(name属性)をGoogleフォームに合わせる必要があります。

なのでGoogleフォームで開発者ツールを開き、formタグのaction属性とそれぞれのinputタグのname属性をメモします。開発者ツールはGoogle ChromeならF12で開けます。

name属性の見つけ方は、Googleフォームのname属性は「entry.」から始まるようになっているため、entry.で検索すると出てくると思います。

また画面の項目以外のentry.と付くname項目もありますが、別になくても動くので最小限画面に必要なものだけ使います。

入力項目のname属性の値が間違っていると送信してもスプレッドシートに登録されないので気をつけましょう。

また最近仕様が変わったらしく、今までは入力項目のinputタグのname属性に直接設定されていましたが、入力項目に直接ではなくhidden項目を用意してまとめられているみたいです。ここちょっとハマりました(-_-;)

上のソースのformタグのaction属性とinputタグのname属性にそのまま設定してもいいですが、今回は以下のようにしました。

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <meta charset="utf-8">

    <?!=include('form.css');?>
    <title>光熱費申請フォーム</title>
  </head>
  <body>
    <main>
        <div class="container">
            <form id="form" action="" method="POST">
            <h1>光熱費申請フォーム</h1>
                <!-- 支払い日付 -->
                <div class="block">
                    <label for="calendar" class="block-title">支払い年月</label>
                    <input type="date" id="calendar">
                </div>
                <!-- 金額 -->
                <div class="block">
                    <label for="cost" class="block-title">金額</label>
                    <div class="cost-group">
                        <input type="number" name="cost" id="cost"><span>円</span>
                    </div>
                </div>
                <!-- 申請内容 -->
                <div class="block">
                    <label class="block-title">申請内容</label>
                    <div class="radio-wrapper">
                        <input type="radio" id="detail1" name="detail" class="radio-inline__input" checked>
                        <label for="detail1" class="radio-inline__label">電気</label>
                        <input type="radio" id="detail2" name="detail" class="radio-inline__input">
                        <label for="detail2" class="radio-inline__label">ガス</label>
                        <input type="radio" id="detail3" name="detail" class="radio-inline__input">
                        <label for="detail3" class="radio-inline__label">水道</label>
                    </div>
                </div>
                <div class="button-wrapper">
                    <span class="submit">送信</span>
                </div>
            </form>
        </div>
        <form id="mG61Hd" action="https://docs.google.com/forms/u/0/d/e/自分のID" method="POST">
            <input type="hidden" id="calendar_year" name="entry.自分のID" value="">
            <input type="hidden" id="calendar_month" name="entry.自分のID_month" value="">
            <input type="hidden" id="calendar_day" name="entry.自分のID_day" value="">
            <input type="hidden" id="detail_val" name="entry.自分のID" value="電気">
            <input type="hidden" id="cost_val" name="entry.自分のID" value="">
        </form>
    </main>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script>
        $(function(){
            //送信ボタンクリック時hedden項目のformをサブミットする
            $('.submit').on('click', function(e){
              $('#mG61Hd').submit();
            });
            //「支払い年月」項目が変更されたときに対応するhidden項目の値も変更
            $('#calendar').on('change', function(e){
                if($(this).val() != ''){
                    $(this).css('color','#000');
                    let calendar = $(this).val();
                    let dt = calendar.split('-');
                    $('#calendar_year').val(dt[0]);
                    $('#calendar_month').val(dt[1]);
                    $('#calendar_day').val(dt[2]);
                } else {
                    $(this).css('color','#999');
                    $('#calendar_year').val('');
                    $('#calendar_month').val('');
                    $('#calendar_day').val('');
                }
            });
            //「申請内容」項目が変更されたときに対応するhidden項目の値も変更
            $('input[name="detail"]').on('change', function(e){
                $('#detail_val').val($(this).next().text());
            }); 
            $('#cost').on('change', function(e){
                $('#cost_val').val($(this).val());
            }); 
        });
    </script>
  </body>
</html>

画面に表示されている項目が入力されたとき、hedden項目の値も変更します。

これで見た目はまだですが、入力して送信するとスプレッドシートに集計されるという最低限の機能が実現できました。

上手く動かない場合はもう一度formタグの属性と各種inputタグのname属性を確認してください。あとは送信しているURLとパラメータが設定したものになっているかを確認しましょう。送信内容はブラウザの開発者ツールの「Network」タブから見れます。

④デザインの変更

今のままだと入力項目と送信ボタンしかないそっけないままなのでCSSで見た目のデザインを変更していきます。

細かいデザイン

1つ1つ説明すると日が暮れてしまいますのでCSSの説明については割愛します。

ボタンやラジオボタンのデザインには力入れました。

<style>
* {
    font-family: 'Montserrat', Arial, Helvetica, sans-serif;
}
main {
    width: 100vw;
    margin: auto;
    color: #fff;
}
.container {
	min-height: 120px;
	background-color: #f7f7f7;
  background-image: url("https://drive.google.com/uc?id=画像のID");
  background-position:center top;
  background-size: cover; 
  background-repeat: no-repeat;
  text-align: center;
}
h1 {
  position: relative;
  display: inline-block;
  padding:50px 55px;
  font-size: 50px;
}
h1:before, h1:after {
  content: '';
  position: absolute;
  top: 45%;
  display: inline-block;
  width: 45px;
  height: 2px;
  border-top: solid 1px #fff;
  border-bottom: solid 1px #fff;
}
h1:before {
  left:0;
}
h1:after {
  right: 0;
}
.block {
    height: 200px;
    margin: 50px 100px 50px 100px;
    display: flex;
    background: rgb(30,30,30,0.7);
    width: 80%;
    flex-direction: column;
    text-align: left;
}
.block-title {
    font-size: 26px;
    font-weight: bolder;
    margin: 20px;
    border-bottom: 1px solid #eee;
}
.block label {
    height: 30px;
}
.detail_checks input {
    margin: 10px;
}
input {
    font-size: 20px;;
    margin: 20px;
}
.cost-group{
    display:flex;
    align-items: flex-end;
}
.cost-group span{
    font-size: 20px;
    margin: 20px 20px 20px 0;
    font-weight: bolder;
}
input[type="number"] {
    height:30px;
    width: 150px;
}
input[type="date"] {
    height: 40px;
    width: 200px;
    border-radius: 10px;
    color: #999;
}
.radio-wrapper {
    display:flex;
}
.radio-inline__input {
    clip: rect(1px, 1px, 1px, 1px);
    position: absolute !important;
}
.radio-inline__label {
    display: inline-block;
    padding: 10px 50px;
    margin: 10px;
    border-radius: 3px;
    transition: all .2s;
    background: #fff;
    color: #444;
    font-weight: bolder;
    cursor:pointer;  
    font-size: 20px;
}
.radio-inline__input:checked + .radio-inline__label {
    background: #CC6666;
    color: #fff;
    text-shadow: 0 0 1px rgba(0,0,0,.7);
}
.submit {
  width: 100%;
  background:#673ab7;
  border-radius:5px;
  border:0;
  cursor:pointer;
  color:#fff;
  font-size:24px;
  padding:10px 100px;
  transition: all 0.3s;
  margin-top:-4px;
  font-weight:700;
  box-sizing:border-box;
}
.submit:hover {
    color: #fff;
    background: #884EF4;
}
.button-wrapper {
    width: 80%;
    text-align: left;    
    margin: 0px 100px;
    padding-bottom: 30px;
}
.error-message {
    color: #ed4055;
    padding: 5px;
    font-size: 20px;
}
.cost-error,.date-error {
    display:none;
}
</style>

背景にGoogleドライブの画像を使う方法

フォームに画像を使いたいと思ったので調べたところGoogleドライブにある画像を使えることがわかりました。

まずはGoogleドライブに使いたい画像をアップロードします。

アップロードしたら画像を右クリックして、「新しいウィンドウで開く」を選択します。

新しいタブで画像が開くと思うのでその時のURLを確認します。以下のようになっていると思うので{画像のID}の部分をメモします。

https://drive.google.com/file/d/{画像のID}/view

メモしたらCSSに戻り以下の「画像のID」の部分に貼り付けます。

.container {
  background-image: url("https://drive.google.com/uc?id=画像のID");
}

これで背景画像が反映されます。画像のサイズで画面が崩れてします場合があるので、その場合はCSSで設定している横幅を変更してください。

⑤バリデーションチェック

必須で入力してほしい場所は簡単なクライアントサイドのバリデーションチェックだけ入れておきましょう。

CSSは上のソースですでに入っているのでHTMLだけ修正します。

各項目にエラー文言を追記して、jQueryで制御します。

完成版は以下です。

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <meta charset="utf-8">

    <?!=include('form.css');?>
    <title>光熱費申請フォーム</title>
  </head>
  <body>
    <main>
        <div class="container">
            <form id="form" action="" method="POST">
            <h1>光熱費申請フォーム</h1>
                <!-- 支払い日付 -->
                <div class="block">
                    <label for="calendar" class="block-title">支払い年月</label>
                    <input type="date" id="calendar">
                    <span class="error-message date-error">日付を正しく入力してください。</span>
                </div>
                <!-- 金額 -->
                <div class="block">
                    <label for="cost" class="block-title">金額</label>
                    <div class="cost-group">
                        <input type="number" name="cost" id="cost"><span>円</span>
                    </div>
                    <span class="error-message cost-error">金額を入力してください。</span>
                </div>
                <!-- 申請内容 -->
                <div class="block">
                    <label class="block-title">申請内容</label>
                    <div class="radio-wrapper">
                        <input type="radio" id="detail1" name="detail" class="radio-inline__input" checked>
                        <label for="detail1" class="radio-inline__label">電気</label>
                        <input type="radio" id="detail2" name="detail" class="radio-inline__input">
                        <label for="detail2" class="radio-inline__label">ガス</label>
                        <input type="radio" id="detail3" name="detail" class="radio-inline__input">
                        <label for="detail3" class="radio-inline__label">水道</label>
                    </div>
                </div>
                <div class="button-wrapper">
                    <span class="submit">送信</span>
                </div>
            </form>
        </div>
        <form id="mG61Hd" action="https://docs.google.com/forms/u/0/d/e/自分のID" method="POST">
            <input type="hidden" id="calendar_year" name="entry.自分のID_year" value="">
            <input type="hidden" id="calendar_month" name="entry.自分のID_month" value="">
            <input type="hidden" id="calendar_day" name="entry.自分のID_day" value="">
            <input type="hidden" id="detail_val" name="entry.自分のID" value="電気">
            <input type="hidden" id="cost_val" name="entry.自分のID" value="">
        </form>
    </main>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script>
        $(function(){
            $('.submit').on('click', function(e){
                let errorFlag = false;
                //日付チェック
                if($('#calendar_year').val() === '' || $('#calendar_month').val() === '' || $('#calendar_day').val() === ''){
                    errorFlag = true;
                    $('.date-error').show();
                } else {
                    $('.date-error').hide();
                }
                //金額チェック
                if($('#cost_val').val() === '' ){
                    errorFlag = true;
                    $('.cost-error').show();
                } else {
                    $('.cost-error').hide();
                }
                //最終エラー結果
                if(errorFlag){
                    return;
                }
                $('#mG61Hd').submit();
            });
            $('#calendar').on('change', function(e){
                if($(this).val() != ''){
                    $(this).css('color','#000');
                    let calendar = $(this).val();
                    let dt = calendar.split('-');
                    $('#calendar_year').val(dt[0]);
                    $('#calendar_month').val(dt[1]);
                    $('#calendar_day').val(dt[2]);
                } else {
                    $(this).css('color','#999');
                    $('#calendar_year').val('');
                    $('#calendar_month').val('');
                    $('#calendar_day').val('');
                }
            });
            $('input[name="detail"]').on('change', function(e){
                $('#detail_val').val($(this).next().text());
            }); 
            $('#cost').on('change', function(e){
                $('#cost_val').val($(this).val());
            }); 
        });
    </script>
  </body>
</html>

終わりに

長々と最後まで見て頂きありがとうございました。

今回は実用的なものを作ろうということでGoogleフォームの画面をカスタマイズしようと思い作ってみました。

内容はそこまで難しくないのですぐにできるだろうと思って取り掛かったのですが、意外と10時間ぐらいかかってしまいました。

Googleフォームの仕様が変わったことで、詰まったときに昔の情報しか検索しても出てこないのがつらかったですね。あとは画面の横幅をレスポンスデザインにしなくてもPCとスマホで見やすいようにしたかったってことが苦労しました。。。

割とCSSの力をつけるにもってこいな作業だと思ったので皆さんも自分の好きなデザインをしてみてください。

スポンサーリンク
GoogleAppsScript プログラミング
スポンサーリンク
この記事を書いた人
まさき

25歳の社会人3年目のシステムエンジニアです。
未経験からIT企業に入社して業務や、業務外でも学習することでプログラミングが書けるようになりました。
得意なのはHTML,CSS,JavaScript。最近はVue.jsとGASを勉強中です。
本を読むことが好きなのでIT技術書以外にもたくさん読みます。
好奇心旺盛でとりあえずやってみる精神です。
楽しいことが生きがいで、仕事も私生活も楽しくなるように日々奮闘中。

まさきをフォローする
シェアする
まさきのエンジニア図書館
タイトルとURLをコピーしました