02_意見集約アプリ

【02_意見集約アプリ】意見集約アプリ〔実装編〕スプレッドシートおよびコードのご紹介

記事概要

こちらでご紹介の。意見集約アプリで使っているスプレッドシート、およびGASのスクリプトとテンプレートのコードを記載しています。宜しければ自己責任でご利用ください。

プログラムの著作は著者に帰属します。また、自己責任でご利用ください。何か上手く行かない場合も自力で解決してみてください・・・(公開設定の方法が適切でないとアクセスできない場合があります)。

これをひな型として、列を増やしたり、パスワードの管理方法を変えたりと自由にアレンジしてみて頂ければと思います。

情報漏えいの恐れがあるのでくれぐれもセキュリティーにかかわる情報管理には利用しない様にしてください。

インポートするスプレッドシート

まず、スプレッドシートのひな型をインポートしてください。式を含めたサンプルデータが入っています。

エクセルのシートをGoogleスプレッドシートにインポートして、シートの見出しを確認しておきます。

「集約」シートは、以下の様なシートが

画像6

「パスワード」シートは、以下の様なシートが入っています。

GASの初期画面のスクリプトファイルとテンプレートファイルの作成

以下の初期画面を呼び出すコードです。「初期画面.gs」と「OpenForm.html」とが必要です。

画像1

GASのプロジェクトから「初期画面.js」ファイルを作成し、以下のコードを貼り付けてください。

画像8

初期画面.gs

//★★★★doGet関数はURLから呼び出された時に実行する関数|1つだけ定義できます★★★★
function doGet(e){

//初期画面であるOpenFoam.HTMLをWEB表示先として取得
  var myOpenHTML = HtmlService.createTemplateFromFile('OpenForm');
  return myOpenHTML.evaluate().addMetaTag("viewport", "width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=10.0");
  
}

 

上記は、doGET関数が含まれており、最初に初期画面を表示させるためのスクリプトです。呼び出されると冒頭の画面が表示されます。

次に上記コードで呼び出す「OpenForm.html」テンプレート(以下の下から2番目)を作成し、以下のコードを貼り付けてください。

☆各自のGASの実行URL☆ のところは、一度プロジェクトをデプロイすると、URLした後に、各自でGASをデプロイした時のリンク先コードを貼り付けてください。

OpenForm.HTML

<!DOCTYPE html>
<html>
<head>
<!---著作:particlemethod------------>
<!---無断複製・転載・配布を禁じます---->
<base target="_top">
</head>

<body>
  <h1>意見集約表読み込みフォーム</h1>
  <p>
    書き込みパスワードを入力ください
  </p>

  <!---POST送信します。自分自身のリンクへaction【↓ここから】--->
  <form method="post" action="https://script.google.com/macros/s/☆各自のGASの実行ID☆/exec">
    <p>
      <!---相手先では、e.parameter.<name要素名>で取り出せます--->
      <label>パスワード:<input type="text" name="PW"></label>
    </p>
    <p>
      <input type="submit" value="送信する">
    </p>
  </form>
  <!---POST送信します【↑ここまで】--->
</body>
</html>

 

GASのテーブル形式フォームのスクリプトファイルとテンプレートファイルの作成

次に初期画面から呼び出す以下の画面のためのコードです。

画像2

「コード.js」を作成し、以下のコードを貼り付けてください。

画像3
☆各自のスプレッドシートID☆ のところは、各自のスプレッドシートのURLを参照してIDを貼り付けてください。
//★★★★doGet関数ではなくPOST送信での呼び出しに書き換え|1つだけ定義できます★★★★
function doPost(e) {
 
  //★★★POST送信された要素名<PW>のデータを取得★★★
  var myPW = e.parameter.PW;

  //アプリケーションを取得|スプレッドシートのIDは各自のものを記入
  var myApp = SpreadsheetApp.openById('☆各自のスプレッドシートID☆');

  //対象シートをシートの名前を指定して取得
  var mySheet = myApp.getSheetByName('集約');
  
   //◆◆◆パスワード記載シートをシートの名前を指定して取得◆◆◆
  var mySheetPW = myApp.getSheetByName('パスワード');
  
  //データ記録範囲として、行数と列数を記載
  //◆◆◆集約データとして記載範囲を書換え◆◆◆
  var nRow=6;
  var nCol=5;

  //◆◆◆パスワードデータの記載セルを追加◆◆◆
  var nRowPW=2;
  var nColPW=5;

//データ記録範囲を指定して範囲を取得
  var myCells = mySheet.getRange(1,1,nRow,nCol);

//データ記録範囲を指定してパスワードから記載範囲を取得
  mySheetPW.getRange(nRowPW,nColPW).setValue(myPW);
  var InpRow = mySheetPW.getRange(nRowPW,nColPW+1).getValue();
  var InpName = mySheetPW.getRange(nRowPW,nColPW+2).getValue();
  mySheetPW.getRange(nRowPW,nColPW).clearContent();

//HTMLファイルのテンプレートをファイル名を指定して取得
  var myHTML = HtmlService.createTemplateFromFile('INDEX');
  
  //★★テンプレートに埋め込む変数値を指定する★★  
   myHTML.myMSG ='ボタンをクリックしてください';   
   myHTML.myCells = myCells.getValues();
   myHTML.myRows = nRow;
   myHTML.myCols = nCol;
   //◆情報追加◆◆ 
   myHTML.myInpRow = InpRow;
   myHTML.myInpName = InpName;  
   
  //HTMLファイルをホスティング|メタタグを指定してスマホ表示に対応
  return myHTML.evaluate().addMetaTag("viewport", "width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=10.0");
 //return myHTML.evaluate();
}


//★★★★HTMLから呼び出されて実行する関数★★★★

//HTMLテーブルの値myCellsをシートに書き込む関数
 //---◆◆◆引数を追加◆◆----
function SetSheet(myCells, myRows, myCols, myInpRow){

  //アプリケーションを取得|スプレッドシートのIDは各自のものを記入
  var myApp = SpreadsheetApp.openById('☆各自のスプレッドシートID☆');

  //対象シートをシートの名前を指定して取得
  var mySheet = myApp.getSheetByName('集約');

  //◆◆◆パスワード記載シートをシートの名前を指定して取得◆◆◆
  var mySheetPW = myApp.getSheetByName('パスワード');

//データ記録範囲として、行数と列数を記載
  var nRow = myRows;
  var nCol = myCols;

  //スプレッドシートにmyCellsの値を書き込み 
   for (var iRow = 0 ; iRow < nRow; iRow++) {
     for (var iCol = 0 ; iCol < nCol; iCol++) {

        //見出し部分は除外して書き込み 
        //◆◆書き込み範囲の条件を変更◆◆
        if(!(iRow == 0 || iCol != myInpRow-1)){
         mySheet.getRange(iRow + 1,iCol + 1,1,1).setValue(myCells[iRow][iCol]);
	     }
      }
    } 
 
 //返り値の変数を定義 
 //◆◆不要で使わない
 var myInpName =  mySheet.getRange(1,myInpRow).getValue() ;


  //◆◆返す内容を変更◆◆
  return myInpName;
}

上記スクリプトは、doPost関数が含まれており、テンプレートから呼び出されて発動します。

上記コードで呼び出すテンプレートファイル「INDEX.html」を作成し、以下のコードを貼り付けます。画像9

☆スプレッドシートのURLのID部分☆はスクリプト同様にスプレッドシートのIDを貼り付けてください。
 <!DOCTYPE html>
<html>
<head>
<!---著作:particlemethod------------>
<!---無断複製・転載・配布を禁じます---->
<base target="_top">

<!---スタイル【↓ここから】---->
<style>
    tr th { border:#aaa solid 1px; padding:5px; 
         background-color:#999; color:white; }
    tr td { border:#aaa solid 1px; padding:5px; }
<!---スタイル【↑ここまで】---->
</style>

</head>
<body>

<!---- Bodyタグの間にコード記入--【↓ここから】-->
<h1>意見集約フォーム</h1>

<p><?=myInpName ?>殿(<?=myInpRow ?>列目)の分の編集<a href= "https://docs.google.com/spreadsheets/d/☆スプレッドシートのURLのID部分☆/edit?usp=sharing" >集約結果はこちら</a></p>

<!---★★★★★★★★ 【テンプレートに渡された変数値からテーブルを表示】 ★★★★★★★★--->

<!---- テーブルタグとID名称宣言----->
<table id="TableBody">

<!---- JavaScriptのインライン記述-【↓ここから】---->
<? 

// GsValuesの各行 iRow に対して実行。myCellsはGASから渡される。
for(var iRow in myCells) {

   // 各行を Row に代入
   var Row = myCells[iRow]; 

   // 行頭タグ 「tr」|タグは ?>・・・<?で挟む
   ?><tr><?

   // カレント行の 各列 iCol に対して実行
   for(var iCol in Row) {

      // 該当行の 各列 iCol をCellに代入
      var Cell = Row[iCol];

      // 見出しや末尾の列の場合はthタグ記述
       // ◆◆見出しとなる条件を変更◆◆
         if (iRow == 0 || iCol != myInpRow-1) { 
               ?><th><?=Cell ?></th><?
               
      // 他の場合tdタグ記述
      } else {  
           // ◆◆場合分け条件を変更◆◆
           if (iRow== 4) { 
              ?><td contenteditable="true" inputmode="numeric"><?=Cell ?></td><?            
           } else {
               ?><td contenteditable="true" inputmode="text"><?=Cell ?></td><?            
           }
       } 
    } 
   ?></tr><?
}
?>
<!---- JavaScriptのインライン記述-【↑ここまで】---->
</table>


<!---★★★★★★★★ 【テーブルの値を取得してGASに渡す】 ★★★★★★★★--->
<!---- JavaScriptの記述-【↓ここから】---->
<script>
 //関数の宣言
 //---◆◆◆引数を追加◆◆----
 function doWriteSheet(myRows, myCols, myInpRow){
 
   //テーブルの取得
   var myTable = document.getElementById('TableBody');
   
   //テーブルの行数、列数の宣言
   var nRow = myRows;
  var nCol = myCols;
  
   //テーブルの行数だけ要素のある配列を宣言
   var myCells = new Array(nRow);
   
   //テーブルの列数だけ子要素を宣言
   for (var iRow = 0; iRow < nRow; iRow++){
    myCells[iRow] = new Array(nCol);
  }
   

   //テーブルのrowsコレクションで行数を取得| 各行でループ
   for (var iRow = 0 ; iRow < myTable.rows.length; iRow++) {
   
	  //iRow行のcellsコレクションで列数を取得| 各列でループ
	  for (var iCol=0 ; iCol < myTable.rows[iRow].cells.length; iCol++) {
      
	 	//iRow行目のiCol列目のセルのテキスト値を取得
		myCells[iRow][iCol] = myTable.rows[iRow].cells[iCol].textContent;
	  }
    }
   //★★テーブルのセルの値をGASのSetSheet 関数に渡し、成功したらonSuccessを実行★★
    //---◆◆◆引数を追加◆◆----
   google.script.run.withSuccessHandler(onSuccess).SetSheet(myCells, nRow, nCol, myInpRow);
 }
 
 //GASの関数が成功したら実行する
 function onSuccess(res){
 
      //メッセージのテキストを取得する
      var msg = document.getElementById("msg");
      
      //メッセージのテキストの中身を変更する
      //◆◆メッセージのテキストを変更する
      
      msg.textContent = '書き込みました:' + res + '殿の項目';
 }
</script>
<!---- JavaScriptの記述-【↑ここまで】----> 

<!---- コメント|変数値はdoGET関数からの渡し値---->
 <p id="msg"><?=myMSG ?></p>

<!---- ボタンの表記---->
<!---◆◆◆引数を追加◆◆---->
<button onclick="doWriteSheet(<?=myRows ?>, <?=myCols ?>, <?=myInpRow ?>)">書込み</button>


</body>
</html>

以上になります。デプロイの方法詳細は、以下を参照してみてください。