エンジニアでもなく理系でもないですが、フリーターからIT企業に入りプログラミングに触れて面白さを知りました。
独学でgasについて学び、ネット上の先輩方のコードを参考にしながら、自分の家計のやりくりに使えないかと家計簿を作りました。
前提条件
- google formは使わない
- UIはgasで表現
- シンプルにその月のカード利用額と無駄遣い額を入力するだけ
- なんとかレスポンシブ対応(だけどほぼスマホで入力することを考えたUI)
基本的には上記の通り、シンプルにgasだけで家計簿アプリを作りました。
cssなども独学で調べながら作ったため、ところどころ変な記述してるかもしれません・・・
(brを多用していたりとか)
画面構成
基本的には下記の通り2画面構成
- トップページ
- 入力ページ
トップページ
誰が使ったか(リーマン、リーマン妻)、カード利用金額、無駄遣い額(カード利用額の中で無駄遣い額がいくらかを視覚的に出したい)だけをトップページに表示
その他についてはトップページの最初に家計簿アプリというアプリ名を書くくらいで他はなし
入力ページ
入力ページも基本的にシンプルに、日付、使用者、カード利用金額、無駄遣い額の入力欄を用意
日付、使用者については選択式
準備
二枚のシートを新規で作成
- 家計簿(アプリトップページに表示
- ▲家計簿データ(こちらにアプリからのデータが入る
家計簿シートの方で、▲家計簿データを集計するように関数を入れる
▲家計簿データのA列にB列に入力された日付を1日に固定するように関数を入れる
(2022年5月27日なら2022年5月1日)
具体的なコード
アプリの裏側
コード.gs
function doGet(e) {
var page=e.parameter["p"];
if(page == "index" || page== null){
var htmlOutput = HtmlService.createTemplateFromFile("index").evaluate();
htmlOutput
.addMetaTag('viewport', 'width=device-width, initial-scale=1,maximum-scale=1')
return htmlOutput;
return HtmlService.createTemplateFromFile('index').evaluate();
}
else if(page =="index2"){
var htmlOutput = HtmlService.createTemplateFromFile("index2").evaluate();
htmlOutput
.addMetaTag('viewport', 'width=device-width, initial-scale=1,maximum-scale=1')
return htmlOutput;
return HtmlService.createTemplateFromFile('index2').evaluate();
}
}
function processForm(formObject) {
var val1 = formObject.date;
var val2 = formObject.user;
var val3 = formObject.card;
var val4 = formObject.gluttony;
var ss = SpreadsheetApp.openById("自分のスプレッドシートのID");
var sh = ss.getSheetByName("▲家計簿データ");
var lr = sh.getLastRow();
var arrdata = [[val1,val2,val3,val4]];
sh.getRange(lr+1,2,1,arrdata[0].length).setValues(arrdata);
Logger.log(arrdata)
}
index.html
<!DOCTYPE html>
<html>
<head>
<title>家計簿</title>
<base target="_top">
<script>
function resizeHtml(){
var w = document.body.clientWidth;
var h = document.body.clientHeight;
var scale = 980 / w;
var transX = (scale - 1) * w / 2 / scale;
var transY = (scale - 1) * h / 2 / scale;
document.body.style.webkitTransform = "scale("+scale+") translate("+transX+"px, "+transY+"px)";
}
</script>
<style>
h1{
background: linear-gradient(#0000cc,#0099ff);
color: #fff;
}
h2{
background: linear-gradient(#0099ff,#0099ff);
color: #fff;
}
font1{
color: #000000;
}
font2{
color: red;
}
.square_btn2{
height: 10rem;
text-align: center;
padding: 0.5em 3em;
text-decoration: none;
background: #265ab9;/*ボタン色*/
color: #FFF;
border-bottom: solid 4px #0B2161;
border-radius: 3px;
}
.square_btn2:active {/*ボタンを押したとき*/
-ms-transform: translateY(4px);
-webkit-transform: translateY(4px);
transform: translateY(4px);/*下に動く*/
box-shadow: 0px 0px 1px rgba(0, 0, 0, 0.2);/*影を小さく*/
border-bottom: none;
}
body{
margin: 8px;
background-size: cover;
background-position:50% 50%;
border: solid 1px gray;
}
table {
display: table;
border-collapse: separate;
border-spacing: 2px;
border-color: #000000;
}
</style>
</head>
<body>
<div style="text-align:center;">
<h1>家計簿アプリ</h1>
<a href="ウェブアプリケーションとして公開した際の「入力ページ」のURL" class="square_btn2">家計簿入力</a>
<br>
<br>
<table align=center border=”2”>
<h2>家計簿サマリ</h2>
<tr>
<th><font1>使用者</font1></th>
<th><font1>カード使用額</font1></th>
<th><font1>無駄遣い額</font1></th>
</tr><p>
<?
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('家計簿');
var range = sheet.getRange(2,2,2,3).getDisplayValues();
for(var i = 0, l = range.length; i < l; i++) {
output.append('<tr>');
output.append('<td>' + range[i][0] + '</td>');
output.append('<td>' + range[i][1] + '</td>');
output.append('<td>' + range[i][2] + '</td>');
output.append('</tr>');
}
?>
</table>
</div>
</body>
</html>
index2.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
window.onload = function () {
var date = new Date();
var yyyy = date.getFullYear();
var mm = ("0"+(date.getMonth()+1)).slice(-2);
var dd = ("0"+date.getDate()).slice(-2);
document.getElementById("today").value=yyyy+'-'+mm+'-'+dd;
}
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener('load', preventFormSubmit);
function handleFormSubmit(formObject) {
google.script.run.withSuccessHandler().processForm(formObject);
}
function OnButtonClick() {
target = document.getElementById("output");
target.innerHTML = "complete!";
target.style.color = '#000000';
}
</script>
<style>
font1{
color: #000000;
}
font2{
color: red;
}
p.border {
border-bottom: solid 1px #000000;
}
form {
/* フォームをページの中央に置く */
margin: 0 auto
width: 250px;
/* フォームの範囲がわかるようにする */
padding: 0.5em;
border: 1px solid #CCC;
}
form div + div {
margin-top: 1em;
}
label {
/* すべてのラベルを同じサイズにして、きちんと揃える */
display: inline-block;
width: 100%;
text-align: left;
color:#000000;
}
select {
/* すべてのラベルを同じサイズにして、きちんと揃える */
display: inline-block;
width: 100%;
height: 28px;
}
input, textarea {
/* すべてのテキストフィールドのフォント設定を一致させる
デフォルトで、textarea は等幅フォントが設定されている */
font: 0.9em sans-serif;
color:#663399;
background: linear-gradient(#f5f5f5,#cbcbcb);
/* すべてのテキストフィールドを同じサイズにする */
width: 100%;
box-sizing: border-box;
/* テキストフィールドのボーダーの外見を同一にする */
border: 1px solid #999;
height: 28px;
text-decoration:underline;
}
input:focus, textarea:focus {
/* アクティブな要素を少し強調する */
border-color: #000;
}
textarea {
/* 複数行のテキストフィールドをラベルにきちんと揃える */
vertical-align: top;
/* テキスト入力に十分な領域を与える */
height: 1em;
}
.button {
/* ボタンを他のテキストフィールドと同じ場所に置く */
text-align: center;
}
button {
/* このマージンは、ラベルとテキストフィールドの間のスペースと
おおよそ同じスペースを表す */
margin-left: .5em;
height: 28px;
color:#663399;
background: linear-gradient(#f5f5f5,#cbcbcb);
box-sizing: border-box;
/* テキストフィールドのボーダーの外見を同一にする */
border: 1px solid #999;
}
body{
margin: 8px;
background-size: cover;
background-position:50% 50%;
}
h1{
background: linear-gradient(#0000cc,#0099ff);
color: #fff;
}
</style>
</head>
<body>
<h1 align="center">家計簿入力</h1>
<form onsubmit="handleFormSubmit(this)" align="center">
<table>
<tbody>
<div>
<label for="date">日付:</label>
<input type="date" id="today" name="date">
</div>
<p class="border"></p>
<div>
<label for="user">使用者:</label>
<select name="user">
<option value="リーマン" selected>リーマン</option>
<option value="リーマン妻">リーマン妻</option>
</select>
</div>
<p class="border"></p>
<div>
<label for="card">カード使用額:</label>
<input type="text" name="card" >
</div>
<p class="border"></p>
<div>
<label for="gluttony">無駄遣い額:</label>
<input type="text" name="gluttony" >
</div>
<p class="border"></p>
<div class="button">
<input type="submit" style="width: 100px" value="入力" onclick="OnButtonClick();">
<button><a href="ウェブアプリケーションとして公開した際の「入力ページ」のURL">再入力</a></button>
<button type="return"><a href="ウェブアプリケーションとして公開した際の「トップページ」のURL">戻る</a></button>
<div id="output"></div>
<br>
</div>
</tbody>
</table><!-- end table -->
</form>
</body>
</html>
できた画面紹介
トップページ
入力ページ
動作
- トップページにて家計簿入力
- 入力画面に移動
- 入力画面にて、使用者、カード使用額、無駄遣い額を入力
- 入力を押す
※再入力ボタンは入力ページをリロードする
※戻るボタンはトップページに戻る
まとめ
とりあえず形にはなった気がする
コードについての簡単な解説は下記のページでやってみたので、もし見たいかたはどうぞ
解説ページ: スプレッドシートのGoogle Apps Script(GAS)で家計簿アプリ5_「サラリーマンがプログラミングしてみた」