見出し画像

【GAS】直近2週間の支出がリンク付き棒グラフで自動表示される家計簿アプリ・・・クリックすると日別の帳票が開いて便利!(実装編)実装用のスプレッドシートとGASのコード

GoogleスプレッドシートをうまくGoogle Apps Script(GAS)と組み合わせると簡易なWEBアプリになります。

WEBアプリは、ブラウザさえあれば作動するので、スマートフォンで操作するソフトウェアとして使えます。さらに、インストールが不要なため、グループ使用する際にも、URLを共有するだけで始められる手軽さがあります。

----------------

WEBアプリは、環境整備や必要なプログラム知識が煩雑で、アマチュアには敷居が少々高いものでしたが、Google Apps Script(GAS) を使い、データベース代わりにスプレッドシートを利用することで、アマチュアにも比較的簡単にWEBアプリを作成できます。

WEBアプリを簡易に作成するパッケージサービスもありますが、自分だけの発想で自由にプログラムを作成できる魅力は捨てがたいものです。

そんな素朴ながらユニークなWEBアプリとして、以下の様な家計簿アプリを作ってみました。

これは、帳票から読み取った直近2週間の支出額を、棒グラフで表示させる家計簿アプリです。


WEBページにアクセスすると目次代わりの棒グラフ表示されます。このグラフは、直近の2週間の支出額を示しているとともに、日別の帳票ページにジャンプできる目次にもなっています。

目次代わりの2週間の支出グラフ


棒グラフの下にある、リンク文字になった日付けをクリックすると、該当日の帳票が開き、記帳がおこなえます。


記帳した内容は、データベース代わりのスプレッドシートに記録されます。

合計額の一つをクリックして帳簿を開く

WEBページを介してスプレッドシートにアクセスするサービスにGoogleフォームがありますが、Googleフォームは、行x列の様な二次元のデータ配列には対応していません。

この様な、テーブル形式の見たままの形式で、スプレッドシートと双方向で書き込み・読み出しができる仕様は、GASを利用してこそ可能です。

----------------

過去の解説記事はこちらです。

----------------

今回の記事では、このアプリを実装するための、GASのコードと、データベース変わりのスプレッドシートのひな形をご紹介します。

本記事では実装コードをご紹介していますが、様々な理由により、この説明通りにいかない場合がしばしばあります。こうした場合の対応は、申し訳ありませんが、自己責任・自己解決でお進めくださるよう、お願いいたします。 

GASによるプログラムはの内容は、個人や小規模なグループ内での利用を想定しており、規模の大きなグループや商用での利用は想定しておりませんのでご注意下さい。

『動的2週間グラフ目次付き・どこでも家計簿アプリ』のシステム構成


システム概要

このWEBアプリのシステムは、1つのスプレッドシートと2つのGASプロジェクトファイルとから構成されています。

スプレッドシート

データベースとして利用し、スクリプトを介して適宜読み書きされます。以下のシートが格納されています。

・グラフ表示に使うデータを表示したシート
・各日の帳票シート
・帳票シートを新規追加する際の書式(ひな型)シート

GASプロジェクトファイル(その1)

日別の帳票を表示するプログラム用です。スクリプトとテンプレートが各1つずつ入っています。

GASプロジェクトファイル(その2)

目次兼グラフを表示するプログラム用です。ここにもスクリプトとテンプレートが1つずつ入っています。

プロジェクトを1つのファイルにまとめていないのは、それぞれ別のURLでアクセスする必要があるためです。(GASの場合、アクセス用のURLは、1つのプロジェクトファイルに1つしか付与できません)

WEBページの表示プロセス

WEBページを表示するプロセスをご説明しておきます。

動的2週間グラフ目次の表示プロセス

スプレッドシート内のグラフ表示用のシートにあるデータをGASで読み取ってテンプレートに反映し、表示させています。

スクリプトがグラフ表示用のデータを集計シートから参照し、これを元にテンプレートからWEBページを生成してレスポンスします。WEBページには帳票へアクセスするためのリンク文字が埋め込まれています。

表示されるWEBページの例を再掲しておきます。


各帳票へは、このページ内のリンク文字からアクセスします。

各日の帳票の表示プロセス

アクセスする際のマクロコード※から、指定された日付のシートにあるデータを読み込み、帳票ページに反映させます。

※補足)アクセスする際に、URLに続けて付加する「?・・・」で始まるテキストを「マクロコード」と言います。


表示されるWEBページの例を再掲しておきます。



このWEBページには「書込み」「読込み」ボタンがあり、WEBページ上で編集したデータをスプレッドシートに記入したり、逆にスプレッドシートのデータを参照してWEBページに反映できる様になっています。

GASで作るWEBアプリについて(再掲)


この記事でご紹介するGASで作るWEBアプリは、以下の要素で構成されます。

スプレッドシート

データベース代わりになります。Googleドライブ内に作成します。

スクリプト

Googleドライブ内で稼働するマクロ言語です。「プロジェクト」というファイルをGoogleドライブ内に作成し、その中で記述します。

「デプロイ」と呼ばれる処理をするとURLが付与され、外部からのアクセスにより稼働する「WEBアプリ」とすることが出来ます。

テンプレート

スクリプト同様に「プロジェクト」の中で記述します。

テンプレートにはHTMLコードとJavaScriptコードを記述でき、スクリプトでレスポンスすることで、ユーザにWEBページとして表示させることができます。

(註:JavaScriptはGoogleスクリプトとよく似ているのですが別物です)

スクリプトにアクセスするとテンプレートが表示される様にしておくと、アクセスするとWEBページが表示される様になり、WEBアプリ用のページとして使うことができます。

GASによるWEBアプリでは、以上3つが必要となります。以下は各要素が動く様子を表しています。

WEBアプリの細かい実装手順は、以下にまとめました。ネットで情報を得ることもできますが、まとまった資料で見たい方はどうぞ。(手間代程度の値段ですが、Amazon読み放題で無料で読めると思います)

デプロイなど詳しい手順は上記を参考にしてください。


『動的2週間グラフ目次付き・どこでも家計簿アプリ』実装用のスプレッドシートとコード


前置きが長くなりましたが、実装用する手順とデータをご紹介します。

①スプレッドシートの作成とシートのインポート


以下がグラフ描画用のデータ生成、および帳票のデータベースに用いるスプレッドシートのひな形です。


Googleドライブ内にスプレッドシートを新規作成し、上記をダウンロードしたもの(エクセル形式です)を、スプレッドシートのファイルメニューからインポートしてください。

ダウンロードしたファイルをエクセルで開くと循環参照など警告が出る場合がありますが、スプレッドシートに取り込んだ後はエラーは出ません。

インポートが済むと、「日毎集計」「書式」および「D20240101_月」などいくつかの日別シートが追加された状態になるはずです。

日毎集計」シートはこんな外観です。

書式」や日別シートはこんな外観です。

スプレッドシートの名前は何でも結構ですが、これらのシート名はスクリプトで参照するので変えないでください。

以上でスプレッドシートの準備は終了です。

最後にブラウザのヘッダからURLを参照し、表示している時のURLおよびスプレッドシートIDを控えておいてください。

スプレッドシートIDは、URLでspreadsheets/d/と/editに挟まれた部分です。
~/spreadsheets/d/★スプレッドシートID★/edit

なお、WEBページに配置したリンクから、スプレッドシートを直接参照できる様にする場合、上記のスプレッドシートは公開設定しておいてください。(Googleログインしてなくて参照できる様にするため)

重要:「日別集計」シートのQ5セル、Q8セルの訂正

日別集計」シートのQ5セルQ8セルには、ここで新規作成したスプレッドシートのIDおよび、後述する日別の帳票表示用のGASのデプロイIDを記述するセルがあります。

GASのデプロイまで済んだら、上の黄色いセル部のデータを各自で打ち替え下さい。

以上で、データベース用のスプレッドシートが実装されました。

②日別の帳票ページ表示用のGASのプロジェクトファイル作成とコードの記述

2つのプロジェクトファイルの内、日別の帳票ページ表示用のGASからご説明します。

Googleドライブ内で、「新規」⇒「その他」⇒「GoogleAppsScript」を選んで「プロジェクト」ファイルを作成します。


②-1:スクリプトのコード記述

プロジェクトファイルを開くと、デフォルトで「コード.gs」ファイルがあるので、コードエディタでこれを開いてこの中にスクリプトを記述します。


元のコードを削除した上で、以下のコードをコピー&ペーストし、「★スプレッドシートID★」部分を、上記で用意したスプレッドシートのものに書き換えてください。

//----かんたん家計簿(発展版)--マクロコード付きURLで日別帳票を開きます --

/* --作成者:ParticleMethod----
-- --作成日:2023.12.28--- 
-- --無断複製・転載・配布を禁じます--- */

/*-- --個人使用でご利用ください。(ノー・クレームでお願いします)
------著作権は作成者に帰属します。------
------参考note記事(https://note.com/prog_article5/n/nda6825314197)----*/

/*-- デプロイしたら、デプロイIDをスプレッドシートのQ8セルに反映ください----*/
/*-- また、スプレッドシートのQ5セルに、スプレッドシート自身のIDを記入する必要があります----*/


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

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

  //日付tDateを取得してシート名 myDateにする
  var tDate = new Date();
  var mNames = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
  var mWeeks = ['日', '月', '火', '水', '木', '金', '土'];
  var myDate = "D" + tDate.getFullYear() + mNames[tDate.getMonth()]+ String(100+Number(tDate.getDate())).substring(1)+"_" + mWeeks[tDate.getDay()];

  //★★★対象シートをプロジェクトのURLから指定して取得★★★
  if(e.parameter.SheetName!=null){
    var mySheet = myApp.getSheetByName(e.parameter.SheetName);
    myDate=e.parameter.SheetName;
  } else { 
     //対象シートをシートの名前を指定して取得
    var mySheet = myApp.getSheetByName(myDate);
  }
  
  //対象シートが無ければ書式シートをコピーして帳票を追加
  var myFrmSheet = myApp.getSheetByName('書式');
  if(!mySheet){
    var mySheet = myFrmSheet.copyTo(myApp);
    mySheet.setName(myDate);
    myApp.setActiveSheet(mySheet);//210730追記(アクティブ化)
    myApp.moveActiveSheet(4);//210730追記(4番目に移動化)
  }

  //データ記録範囲として、行数と列数を記載
  var nRow=11;
  var nCol=7; //210829 列追加 6→7

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

  //HTMLファイルのテンプレートをファイル名を指定して取得
  var myHTML = HtmlService.createTemplateFromFile('INDEX');
  
  //★★テンプレートに埋め込む変数値を指定する★★  
  myHTML.myMSG ='ボタンをクリックしてください';   
  myHTML.myCells = myCells.getValues();
  myHTML.myRows = nRow;
  myHTML.myCols = nCol;
  myHTML.myDate = myDate;


  
  //HTMLファイルをホスティング|メタタグを指定してスマホ表示に対応
  return myHTML.evaluate().addMetaTag("viewport", "width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0");
}


//★★★★テンプレートから呼び出されて実行する関数★★★★

//HTMLテーブルから受けた配列値myCellsをスプレッドシートに書き込む関数
function SetSheet(myCells, myRows, myCols, myDate0){

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

  //対象シートをシートの名前を指定して取得
  var myDate =myDate0  
  var mySheet = myApp.getSheetByName(myDate);
  
  //データ記録範囲として、行数と列数を記載
  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 == 0 || iCol == 6)){
         mySheet.getRange(iRow + 1,iCol + 1,1,1).setValue(myCells[iRow][iCol]);
	     }
      }
    }
  
 
 //返り値を保存する配列を定義 
 var myTotal = new Array(2) ;

  myTotal[0] = 0 ;
  myTotal[1] = 0 ;
  
  //ループを回して6列目を取得(シートの列数は0から始まるので数字は5) 
  for (var iRow = 2; iRow <= nRow ;iRow++){

      //値が数字なら実行) 
     if(typeof mySheet.getRange(iRow,6,1,1).getValue() == 'number'){
        //個数カウント 
        myTotal[0]++;

        //合計値加算
         myTotal[1]+= mySheet.getRange(iRow,6,1,1).getValue();
     }
  } 
  
  //結果テンプレートに返す 
  return myTotal;

}

//★★★★テンプレートから呼び出されて実行する関数2★★★★

//スプレッドシートの値をテンプレートに返す関数
function GetSheet(myRows, myCols, myDate0){

  //アプリケーションの取得|★スプレッドシートID★は各自のものを記入
  var myApp = SpreadsheetApp.openById('★スプレッドシートID★');
  
  //対象シートをシートの名前を指定して取得
  var myDate =myDate0  
  var mySheet = myApp.getSheetByName(myDate);
  
  //対象シートが無ければ書式シートをコピーして帳票を追加
  var myFrmSheet = myApp.getSheetByName('書式');
  if(!mySheet){
    var mySheet = myFrmSheet.copyTo(myApp);
    mySheet.setName(myDate);
  }
  
  

  //データの取得範囲として行数、列数を設定
  var nRow=myRows;
  var nCol=myCols;

  //スプレッドシートの値を返り値として渡す
  var myCells = mySheet.getRange(1,1,nRow,nCol).getValues();

  return myCells;
}

書き換える「★スプレッドシートID★」は3ヵ所あります。

作業が済んだら保存します。


②-2:テンプレートのコード記述

さきほどのスクリプトと同じプロジェクト内に、「INDEX.html」というテンプレートファイルを追加します。

ヘッダの「+」をクリックし、


「HTML」を選択し、

テンプレート名を「INDEX.html」として追加します。(この名称はスクリプト中で利用していますので、変えないでください)

元のコードを削除した上で、以下のコードをコピー&ペーストし、「★スプレッドシートID★」部分を、上記で用意したスプレッドシートのものに書き換えてください。

<!DOCTYPE html>

<!-- -かんたん家計簿(発展版)--マクロコード付きURLで日別帳票を開きます-- --

 --作成者:ParticleMethod----
-- --作成日:2023.12.28--- 
-- --無断複製・転載・配布を禁じます---

-- --個人使用でご利用ください。(ノー・クレームでお願いします)
------著作権は作成者に帰属します。------
------参考note記事(https://note.com/prog_article5/n/nda6825314197)---->

<html>

<head>
  <base target="_top">

  <!---- JQuery導入↓---->
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

</head>

<!---スタイル--↓-->
<style>
    input[type="number"] { width: 15em; }

    tr th { border:#aaa solid 1px; padding:5px; 
         background-color:#999; color:white; }
    tr td { border:#aaa solid 1px; padding:5px; }
</style>
<!---スタイル--↑-->

<!---★★★★★★★★ 【セレクトボックスの挙動を記述】 ★★★★★★★★--->
<script>

//JQueryで記述する無名関数
$(function() {
 
  //セレクトボックスが切り替わったら発動
  $('.myDate').change(function() {
  
  var tDate = new Date($("#mY").val(),$("#mM").val()-1,$("#mD").val());
  var tNames = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
  var tWeeks = ['日', '月', '火', '水', '木', '金', '土'];
  var newDate = "D" + tDate.getFullYear() + tNames[tDate.getMonth()]+ String(100+Number(tDate.getDate())).substring(1)+"_" + tWeeks[tDate.getDay()];
  
    //選択したvalue値をp要素に出力
    $('#myrDate').text(newDate);
  });
});
</script>


<!---★★★★★★★★ 【WEBページのテーブルの値を取得してスクリプトに渡す】 ★★★★★★★★--->
<!---- JavaScriptの記述-【↓ここから】---->
<script>
 //関数の宣言
 function doWriteSheet(myRows, myCols){
 
  //テーブルの取得
  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列目のセルのテキスト値を取得
        if(iCol == 1){
           //---- JQuery記述-【↓ここから】---->

            //IDに追応じてテキスト値を取得し変数に代入
            var myID = "#R"+ iRow;
            myCells[iRow][iCol] =$(myID).closest('tr').find('select.s1').val();
         
           //---- JQuery記述-【↑ここまで】----> 
            } else if(iCol == 2){
           //---- JQuery記述-【↓ここから】---->

            //IDに追応じてテキスト値を取得し変数に代入
            var myID = "#R"+ iRow;
            myCells[iRow][iCol] =$(myID).closest('tr').find('select.s2').val();
         
           //---- JQuery記述-【↑ここまで】----> 
        } else{
        
		myCells[iRow][iCol] = myTable.rows[iRow].cells[iCol].textContent;
        }
	  }
    }

    //---- JQuery記述-日付けを取得--
     var myDate0 = $('#myDate').text();

    //★★テーブルのセルの値をスクリプトのSetSheet関数に渡し、成功したらonSuccessを実行★★
    google.script.run.withSuccessHandler(onSuccess).SetSheet(myCells, nRow, nCol, myDate0);
 }
 
 //スクリプトの関数が成功したら実行する処理
 function onSuccess(res){
 
    //メッセージのテキストを取得する
    var msg = document.getElementById("msg");
      
    //メッセージのテキストの中身を変更する
    msg.textContent = '書き込みました。現在、購入数:' + res[0] + '個、合計金額:' + res[1]+ '円 です。';
  }
</script>
<!---- JavaScriptの記述-【↑ここまで】----> 

<!---★★★★★★★★ 【GASからのデータでテーブルの値を更新】 ★★★★★★★★--->
<!---- JavaScriptの記述-【↓ここから】---->
<script> 
//★★スクリプトのGetSheet 関数を実行してスプレッドシートのセル値を取得|成功したらonSuccess2を実行★★


    
 function doUpdateTable(myRows, myCols){
    <!---- JQuery記述-【↓ここから】-->
     var nDate = $('#myrDate').text();
     $('#myDate').text(nDate);
     var myDate0 = $('#myDate').text();
    <!---- JQuery記述-【↑ここまで】-->
    google.script.run.withSuccessHandler(onSuccess2).GetSheet(myRows, myCols, myDate0);
 }
 
//GASの関数が成功したら実行する|resは関数の返り値
 function onSuccess2(res, myRows, myCols){

      //テーブルの取得      
      var myTable = document.getElementById('TableBody');

      //テーブルの行数、列数の宣言      
      var nRow = myRows;
      var nCol = myCols;

      //テーブルの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列目のセルの値をGASから返されたresで更新
        //1列目のセルの場合
		   if(iCol == 1 ){
               //セルの値を取得           
               var Cell = res[iRow][iCol];
           
               //行数に応じたID名を設定           
               var myID = "#R"+ iRow;
           
           <!---- JQuery記述-【↓ここから】---->

              //行数に応じたID名の選択肢をセルの値をもとに設定  
              $(myID).closest('tr').find('select.s1').val(Cell);
         
           <!---- JQuery記述-【↑ここまで】---->          
           } else if(iCol == 2 ){ //2列目のセルの場合
               //セルの値を取得           
               var Cell = res[iRow][iCol];
           
               //行数に応じたID名を設定           
               var myID = "#R"+ iRow;
           
           <!---- JQuery記述-【↓ここから】---->

              //行数に応じたID名の選択肢をセルの値をもとに設定  
              $(myID).closest('tr').find('select.s2').val(Cell);
         
           <!---- JQuery記述-【↑ここまで】---->          
           } else {
            //セル値に応じた値をテーブルに設定  
           myTable.rows[iRow].cells[iCol].textContent = res[iRow][iCol] ;
	       }
          }
      }

      //コメントの取得 
       var msg = document.getElementById("msg");

       //コメントの更新 
       msg.textContent = '表を更新しました。';
       
 }

</script>
<!---- JavaScriptの記述-【↑ここまで】---->


<body>

<!---- Bodyタグの間にコード記入--【↓ここから】--->

<p>簡単家計簿アプリ<a href= "https://note.com/prog_article5/n/nda6825314197" >説明はこちら</a></p>

<!--シート原本|★スプレッドシートID★各自書き換えください-->
<p>シート原本<a href= "https://docs.google.com/spreadsheets/d/★スプレッドシートID★/edit" >こちらから</a></p>


<p>日付設定<br>
<input type="number" id="mY" class="myDate" value="<?=Number(myDate.substring(1,5)) ?>">年<br>
<input type="number" id="mM" class="myDate" value="<?=Number(myDate.substring(5,7)) ?>">月<br>
<input type="number" id="mD" class="myDate" value="<?=Number(myDate.substring(7,9)) ?>">日<br>

<span>読込みシート名</span>
<span id="myrDate"><?=myDate ?></span>
</p>

<!---- テーブルタイトル----->
 <hr>
 <span>簡単データベース:シート名</span>
 <span id="myDate"><?=myDate ?></span>

 

<!---- ボタンの表記 210829---->
 <BR>
 <button onclick="doWriteSheet(<?=myRows ?>, <?=myCols ?>)">書込み</button>
 <button onclick="doUpdateTable(<?=myRows ?>, <?=myCols ?>)">読込み</button>

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

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

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

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

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

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

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

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

      if (iRow == 0 || iCol == 0 || iCol == 6) { 
               ?><th><?=Cell ?></th><?
                             
      // 他の場合tdタグ記述
      } else {  
           // 6列目は inputmode="numeric" にする
           if (iCol == 5) { 
                ?><td  width="60" contenteditable="true" inputmode="numeric"><?=Cell ?></td><?

           // 1列目は Selet 要素 にする
           } else if (iCol == 1){
                 // td で iD名を 「R行番号」 にする
                ?><td contenteditable="true" inputmode="text" id="R<?=iRow ?>">
                    <select class="s1">
                      <!-- 値に応じて「selected」を設定する -->
                      <option value="" <? if(Cell == ''){ ?> selected <? } ?>>-</option>
                      <option value="現金" <? if(Cell == '現金'){ ?> selected <? } ?>>現金</option>
                      <option value="クレカ" <? if(Cell == 'クレカ'){ ?> selected <? } ?>>クレカ</option>
                    </select>                               
                </td><?                 

           // 2列目は Selet 要素 にする
           } else if (iCol == 2){
                 // td で iD名を 「R行番号」 にする
                ?><td contenteditable="true" inputmode="text" id="R<?=iRow ?>">
                    <select class="s2" >
                      <!-- 値に応じて「selected」を設定する -->
                      <option value="" <? if(Cell == ''){ ?> selected <? } ?>>-</option>
                      <option value="食費" <? if(Cell == '食費'){ ?> selected <? } ?>>食費</option>
                      <option value="雑貨" <? if(Cell == '雑貨'){ ?> selected <? } ?>>雑貨</option>
                      <option value="衣類" <? if(Cell == '衣類'){ ?> selected <? } ?>>衣類</option>
                      <option value="娯楽" <? if(Cell == '娯楽'){ ?> selected <? } ?>>娯楽</option>                      
                      <option value="交通"<? if(Cell == '交通'){ ?> selected <? } ?>>交通</option>
                    </select>                               
                </td><? 
                
           }else{
               ?><td width="70" contenteditable="true" inputmode="text"><?=Cell ?></td><?            
           }
        } 
    } 
}
?>
<!---- JavaScriptのインライン記述-【↑ここまで】---->
</table>


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

<!---- ボタンの表記---->
 <button onclick="doWriteSheet(<?=myRows ?>, <?=myCols ?>)">書込み</button>
 <button onclick="doUpdateTable(<?=myRows ?>, <?=myCols ?>)">読込み</button>

</body>
</html>

テンプレート内にある「★スプレッドシートID★」の部分は、WEBページに原本のスプレッドシートへのリンクを貼るためのものです。
スプレッドシートを直接参照するため、Googleにログインしない状態で参照する場合は、スプレッドシートの公開設定をしておきます。

貼り付けたら、一旦保存します。

②-3:プロジェクトのデプロイ(再掲)

コードを記述して保存後、続いて「デプロイ」と呼ばれる手続き行います。これによって、特定のURLからGASを起動できる様になります。

この記事では概要を以下に示しますが、詳細はネットなどで確認ください。以前の記事でも書いた再掲記事となります。

エディタの上にある「デプロイ」ボタンをクリックし・・・

「新しいデプロイ」をクリックし・・・

ウェブアプリとしてのデプロイを選択します。


アクセス者が「自分」、アクセスできるのは「全員」にします。(これは、Googleへログインしていない場合でも使える設定です)

ここで「デプロイ」をクリックした後、誰がデプロイしているのか(自分のユーザ名をクリック)、デプロイを許可するか(許可、またはArrowをクリック)聞かれた後、最終的に完了します。


最後表示されたURLがアクセス用のURLです。これを控えておき、先のスプレッドシートに反映します。


以上で、帳票を読み書きするWEBアプリのコードが実装されました。

最後に示されたアクセス用URLをクリックしてみてください。当日の帳票が開きましたらデプロイ成功です。

③動的2週間グラフ目次表示用のGASのプロジェクトファイル作成とコードの記述


次に、もう1つGASのプロジェクトファイルを作り、動的2週間グラフ目次表示用のコードを実装します。(手順は全く同じなので、手続きの説明は割愛いたします)

③-1:スクリプトのコード記述

追加したプロジェクトファイルを開くと、デフォルトで「コード.gs」ファイルがあるので、1つめのプロジェクト同様に、コードエディタでこれを開いてこの中にスクリプトを記述します。

元のコードを削除した上で、以下のコードをコピー&ペーストし、「★スプレッドシートID★」部分を、上記で用意したスプレッドシートのものに書き換えてください。

//-- --動的2週間グラフ付き目次-- --

/* --作成者:ParticleMethod----
-- --作成日:2023.12.28--- 
-- --無断複製・転載・配布を禁じます--- */

/*-- --個人使用でご利用ください。(ノー・クレームでお願いします)
------ブラウザやモニタ環境によってグラフの芯ずれがありご了承ください------
------著作権は作成者に帰属します。------
------参考note記事(https://note.com/prog_article5/n/nda6825314197)----*/


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

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

//シートを取得
var mySheet = myApp.getSheetByName('日毎集計');

  //直近2週間の帳票シートの合計値を2週間目次に複写
  for(var iCol=0; iCol<7; iCol++){
    for(var iRow=0; iRow<2; iRow++){

      //参照シート名を取得
      var mySN=mySheet.getRange(3+iRow*3,9+iCol).getValue();
      var myDaySheet=myApp.getSheetByName(mySN.substring(0,11));

      var myDayTotal=0;

      //参照シートが存在すれば日別の帳票シートから合計値を取得
      if(myDaySheet){
        myDayTotal=myDaySheet.getRange(11,7).getValue();
      }

      //日別の帳票シートの合計値を書き込み
      mySheet.getRange(5+iRow*3,9+iCol).setValue(myDayTotal);
    }
  }


  //シートに記載しているCanvasのサイズを取得
  var myCanvas_W = mySheet.getRange(18, 3,1,1).getValue();
  var myCanvas_H = mySheet.getRange(19, 3,1,1).getValue();


  //テンプレートを取得
  var myHTML = HtmlService.createTemplateFromFile('INDEX');

  //テンプレートのHTMLコード中に埋め込む値を渡す
  myHTML.Canvas_W = myCanvas_W;
  myHTML.Canvas_H = myCanvas_H;

  //テンプレートをWEBページとしてホスティング|メタタグを指定してスマホ表示に対応
  return myHTML.evaluate().addMetaTag("viewport", "width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=10.0");
}



//★★★★テンプレートから呼び出されて実行する関数★★★★

//CANVASオブジェクトの中の図形描画はJavaScriptで記述します。
//JavaScript中で使用する図形描画の為の変数をここで取得しています。

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

  //シートを取得
  var mySheet = myApp.getSheetByName('日毎集計');

  //返り値を入れる配列を用意|要素数は300としています
  var myGraphData = new Array(300) ;
 
  //配列で要素0~には、日別の帳票シートのURL、合計値、日付けを格納します
  //2週間分のデータを各日で要素[0],[1],[2]番、[3],[4],[5]番・・・と0番から詰めて格納
  for(var i=0;i<14;i++){

    //セル範囲A2~C15のデータを順に格納しています

    //指定日の帳票のURLを取得
      myGraphData[i*3+0] =  mySheet.getRange(2+i, 1).getValue();
      
      //指定日の帳票の合計値を取得
      myGraphData[i*3+1] =  mySheet.getRange(2+i, 2).getValue();

      //指定日の帳票の日付を取得
      myGraphData[i*3+2] = mySheet.getRange(2+i, 3).getValue();
  }

  //配列で要素100~には 各日の棒グラフ描画の座標値(8種)を格納
  for(var i=0;i<14;i++){
 
    //指定したシートの棒グラフ(長方形)、合計文字、リンク文字の描画座標を取得
    //2週間分のデータを各日で要素[100]~[109]番、要素[110]~[119]番・・・と10番ずつ格納
    //1の位が8、9番の要素については、[108]、[109]番以外はカラのデータです。
    for(var j=0;j<10;j++){

      //セル範囲D34~M47のデータを格納しています
      //長方形描画の座標、合計値の文字の位置、日付けのリンク文字の位置を示します。
      myGraphData[100+10*i+j] = mySheet.getRange(34+i, 4+j).getValue();
    }
  }

//収集したグラフ用のデータを返す 
return myGraphData; 

  
}

書き換える「★スプレッドシートID★」は2ヵ所あります。


③-2:テンプレートのコード記述


テンプレートのコードを記事の最後の有料部からどうぞ。

③-3:プロジェクトのデプロイ

こちらのプロジェクトも同様にデプロイすれば、アプリの完成です。

後からデプロイした動的2週間グラフ目次表示用のURLからアクセスしてみてください。最初は合計額がゼロなので棒グラフは見えないと思いますが、棒グラフの表示ページが見えたでしょうか。

グラフと文字とは少しズレがあると思います。これはディスプレイのサイズやドット密度に由来するもので、解決方法が見いだせておりません。悪しからずご容赦ください

続いて、適当な日付のリンク文字をクリックしてみてください。記入用の帳票が見えれば成功です。

・コードは実装して稼働することを手元環境で確認しておりますが、環境によっては稼働しない場合もあるかもしれません。こうしたトラブル等をフォローできないため、申し訳ありませんが、不具合時に自己責任・自己解決で対応する事をご了承くださる方だけご利用ください。


・表示させたWEBページからボタンをクリックしても反応しない場合があります。そんな場合は「yahoo!検索」など先にブラウザを開いて、デプロイしたURLを改めて読み込む様にすると、稼働する場合があります。

・個人や小規模なグループ内での利用を想定しており、規模の大きなグループや商用での利用は想定しておりませんのでご注意下さい。

テンプレートのコードからは、以下のノウハウが得られます。

■CANVAS要素を使った、テンプレート上での図形描画のコード事例
■文字要素を、.appendChild関数を使い、位置を指定してCANVAS要素に重ねるコード事例。
■上記で重ねた文字が、CANVAS要素に「絵」として文字を埋め込むのとは異なり、リンクを指摘したりクラスを利用して点滅させたりするコード事例。

万一うまく稼働しなかった場合は、上のノウハウが参照できることでご容赦願いますm(_ _)m。(多くの行に説明をコメントしているので、意味するところは判ると思います)


前の記事

ここから先は

4,853字

¥ 300

この記事が気に入ったらサポートをしてみませんか?