#前提
シート名「Origin」が以下のような設定になっているものとします。
【変更前のシート(A1セル〜C3セル)】
/ | A | B | C | D |
---|---|---|---|---|
1 | 項目 | 課題1 | 項目 | 課題2 |
2 | 4/1までの成果 | 4/1までの成果 | ||
3 | 4/8までの目標 | 4/8までの目標 | ||
4 | 4/8までの成果 | 4/8までの成果 | ||
5 | 4/15までの目標 | 4/15までの目標 | ||
6 | 4/15までの成果 | 4/15までの成果 | ||
7 | 4/22までの目標 | 4/22までの目標 |
B列、D列が報告記載列です。
「スプレッドシートを直接操作させたくない」「Webフォームから入力したい」という要望があったものとします。
#結論
doGet()関数でフォーム画面を呼び出しつつ、スプレッドシートから取得したデータをHTML上に展開していきます。
Webフォームの「送信」ボタンがクリックされたらJavascriptで「regData」関数を呼び出し、元のスプレッドシートにデータを上書き保存するというものです。
#動作確認スクリプト
##1. HTMLコンテンツをデータに変換するための関数
sample-code1.gs
function doGet(e) {
//HTMLテンプレートファイルを取得
var html = HtmlService.createTemplateFromFile('form');
//変数idにて対象スプレッドシートを取得
var SS = SpreadsheetApp.openById(id);
var Sheets = SS.getSheets();
var Sheet = "";
//アクセスしたユーザのEmailアドレスがシート名になっているシートを取得
for(i = 0; i < Sheets.length; i++){
if(inputUser == Sheets[i].getSheetName()){
Sheet = Sheets[i];
break;
}
}
//2回目以降のアクセスならシートから値を取得
if(Sheet)
var data = Sheet.getDataRange().getValues();
else{
//1回目ならシート名「Origin」をコピー、シート名変更およびフォーム入力項目を挿入
var source = SS.getSheetByName("Origin");
var Sheet = source.copyTo(SS).setName(inputUser);
}
html.data = data;
try{
return html.evaluate().setTitle("週報提出").setSandboxMode(HtmlService.SandboxMode.NATIVE);
}
catch(e){
errMailSend(e,"doGet");
}
}
###メール本文に使うHTMLテンプレート
form.html
<head>
</head>
<div class='header' id='header'>週報提出</div>
<form id='formstyle' name='applyform' method='post' enctype="multipart/form-data">
<table>
<thead>
<tr>
<th><label><?= data[0][0]?></label></th>
<th><label><?= data[0][1]?></label></th>
<th><label><?= data[0][2]?></label></th>
<th><label><?= data[0][3]?></label></th>
</tr>
</thead>
<tbody>
<? for(var i = 1;i < data.length; i++){ ?>
<tr>
<th align = 'left' scope="row"><label><?= data[i][0]?></label></th>
<td><textarea cols="25" rows='4' name='<?= i ?>_1' id='<?= i ?>_1'><?= data[i][1] ?></textarea></td>
<th align = 'left' scope="row"><label><?= data[i][2]?></label></th>
<td><textarea cols="25" rows='4' name='<?= i ?>_3' id='<?= i ?>_3'><?= data[i][3] ?></textarea></td>
</tr>
<? } ?>
</tbody>
</table>
<input type='button' id='sbmt0' name='sbmt0' value='更新' onClick='return confirmSubmit(this.parentNode)'>
</form>
<div class='inProgress' id="inProgress" style="display: none;">
<!-- Progress starts hidden, but will be shown after form submission. -->
処理中・・・・
</div>
<div id="result" class="center">
</div>
<?!= include('Javascript'); ?>
###form.html中で利用するJavascript
Javascript.html
<script>
//送信ボタンクリック後、内容確認ポップアップ表示用ファンクション//
function confirmSubmit(formValues){
document.getElementById("result").innerHTML = "";
var str = "";
var submit = confirm("+++++情報を送信します+++++\n");
if(submit){
//「処理中」を表示する
toggle_visibility('inProgress','block');
//code.gs内のregData関数へデータを送信する
google.script.run.withSuccessHandler(outputInfo).withFailureHandler(outputFail).regData(formValues);
}
else
outputFail("+++++送信をキャンセルしました+++++\n");
}
// ****************************************
function outputInfo(value){//操作完了ポップアップを表示する
document.getElementById("result").innerHTML = "";
toggle_visibility('inProgress','none');
// alert(value);
if(value){
var span = document.createElement('span');
span.innerHTML = [value].join('');
document.getElementById("result").insertBefore(span,null);
document.getElementById('sbmt').disabled = true;
}
else{
var span = document.createElement('span');
span.innerHTML = ["+++++処理は正常に完了しました+++++<br>\n(このまま連続して登録頂くことも可能です)"].join('');
document.getElementById("result").insertBefore(span,null);
}
}
function outputFail(value){//操作エラーポップアップを表示する
var span = document.createElement('span');
span.innerHTML = [value].join('');
document.getElementById("result").insertBefore(span,null);
}
function toggle_visibility(id,value) {//form.html上の要素を出したり消したりする
var e = document.getElementById(id);
e.style.display = value;
}
</script>
##2. フォームから送信ボタンが押された時に実行する関数
sample-code2.gs
function regData(formValues){
//格納先スプレッドシートを取得
var SS = SpreadsheetApp.openById(id);
var Sheet = SS.getSheetByName(inputUser);
var Range = Sheet.getRange(DataRange);//DataRangeはデータを格納する範囲(例えば"A1:D7"など)
var data = Range.getValues(); //現在のシート内容を二次元配列dataへ格納
var str_1,str_3;
Logger.log("formValues is \n%s",formValues);
//data(=各ユーザーシート)の2行目(i=1)から先の2・4列目にformValuesデータを挿入
for(var i = 1; i < data.length; i++){
//form側から受け取ったデータの中で、idが「i(=行数)_1」のデータを配列data[i][1]へ挿入
str_1 = i + "_1";
data[i][1] = formValues[str_1];
//form側から受け取ったデータの中で、idが「i(=行数)_3」のデータを配列data[i][3]へ挿入
str_3 = i + "_3";
data[i][3] = formValues[str_3];
}
//スプレッドシートへデータをセットする(何が変わったのかは検知せず、端から端まで上書きする)
Range.setValues(data);
//変更をメール通知する
var Title = "【週報】変更が反映されました";
var Message =
"(本メールはシステムにより自動送信されています)\n\n"
+ "いつもお世話になっております。\n"
+ "週報の更新を検知・完了致しました。\n"
+ "<https://〜〜〜>\n\n"
+ "次回更新や内容修正の際は上記URLよりアクセスし「更新」ボタンをクリックしてください。\n"
+ "何卒宜しくお願い致します。\n";
GmailApp.sendEmail(inputUser, Title, Message);
}