この記事は、「Google Apps Script Advent Calendar 2018」の8日目の記事です。
GASでAPI配信して、スプレッドシートからwebページを更新できるようにしてみました!
みなさんは、webページのnews更新にCMSを導入したり、直接HTMLを更新したりしていませんか?
webページを更新する担当者が、PCを触る程度のスキルだとどうでしょうか?CMS導入を選択して投稿フォームで入力もありですが、静的なwebページだとその機能のためにCMSを入れるのもオーバースペックな気がします。
手軽な静的サイトジェネレータでも、スキルによってはコマンド(黒い画面)が使えなかったりもすると思います。
そんな中、Excelのような表計算ソフトを利用できる人は結構いると思います。webページ更新時に、みんなが使いやすいツールを利用すると良いかもなんてことを考えていました。
全体の構成です。できるだけシンプルに。
フロントエンド
- bootstrap4-starter
※利用方法は「Bootstrap4とwebpackを組み合わせたビルド環境を公開してみた」を参照して頂ければと思います。
バックエンド
- スプレッドシート
- Google Apps Script
バックエンド
まずは、バックエンドを構築してみます。
お好きな名前でスプレッドシートを新規作成し、A列にnews情報を記入します。1行目が題名で、2行目から表示文章です。
次に、ツール → スクリプトエディタをクリック
次に、GASで配信用のAPIを構築してみます。
script.gs
//スプレッドシートの値をAPI配信
function doGet() {
//スプレッドシート取得
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
//シートを取得
var sheet = spreadsheet.getActiveSheet();
//値の最終行を取得
var lastrow = sheet.getLastRow();
//JSON変数初期化
var json = [];
//セルの一覧を取得
for (var i = 2; i <= lastrow; i++) {
//セルの値を取得
var value = sheet.getRange("A" + i).getValue();
//値を格納
var name_obj = {
news: value
};
//JSONを追加
json.push(name_obj);
}
//JSONP形式に変換
var jsonp = "apicallback(" + JSON.stringify(json) + ")";
//JSONPで配信
return ContentService
.createTextOutput(jsonp)
.setMimeType(ContentService.MimeType.JAVASCRIPT);
}
上記のコードを、GASのエディタにコピーし保存します。
次に、公開 → ウェブアプリケーションとして導入をクリック
バージョン: 好きな値
ユーザー: 自分
アクセスユーザー: 全員(匿名ユーザーを含む)
設定したら導入をクリック
許可を確認をクリック
自分のアカウントをクリック
許可をクリック
API配信先のURLが作成されたら、コピーしておきます。
フロントエンド
最後に、フロントエンドを構築してみます。
bootstrap4-starterの「index.html」と「script.js」を修正します。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>bootstrap4 Starter</title>
</head>
<body>
<!--ナビバー-->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="./">menu</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Dropdown
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="#content1">content1</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#content2">content2</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#content3">content3</a>
</div>
</li>
</ul>
</div>
</nav>
<!--題名-->
<div class="jumbotron text-center">
<h2>bootstrap4 Starter</h2>
</div>
<!--本文-->
<div class="container">
<br><br>
<!--news部分追加-->
<div class="row" id="news">
</div>
<br><br>
<div class="row" id="content1">
<div class="col-sm-12">
<div class="mx-auto">
<p>content1-1</p>
<img class="img-thumbnail" src="./img/img01.jpg" />
</div>
</div>
<div class="col-sm-12">
<div class="mx-auto">
<p>content1-2</p>
<img class="img-thumbnail" src="./img/img02.jpg" />
</div>
</div>
</div>
<br>
<div class="row" id="content2">
<div class="col-sm-6">
<div class="mx-auto">
<p>content2-1</p>
<img class="img-thumbnail" src="./img/img03.jpg" />
</div>
</div>
<div class="col-sm-6">
<div class="mx-auto">
<p>content2-2</p>
<img class="img-thumbnail" src="./img/img04.jpg" />
</div>
</div>
</div>
<br>
<div class="row" id="content3">
<div class="col-sm-4">
<div class="mx-auto">
<p>content3-1</p>
<img class="img-thumbnail" src="./img/img05.jpg" />
</div>
</div>
<div class="col-sm-4">
<div class="mx-auto">
<p>content3-2</p>
<img class="img-thumbnail" src="./img/img06.jpg" />
</div>
</div>
<div class="col-sm-4">
<div class="mx-auto">
<p>content3-3</p>
<img class="img-thumbnail" src="./img/img07.jpg" />
</div>
</div>
</div>
</div>
<script src="./app.js"></script>
</body>
</html>
script.js
//JSONPのAPI取得
var url = "ここに配信したAPIのURLを入れる";
$.ajax({
type: "GET",
url: url,
dataType: 'jsonp',
contentType: 'application/javascript',
jsonpCallback: 'apicallback',
})
.then(
//取得
function (data) {
//取得したJSONをHTMLに追加
for (var i = 0; i < data.length; i++) {
//HTML作成
var newsall =
'<div class="col-sm-12">' +
'<div class="mx-auto">' +
'<p>' + data[i].news + '</p>' +
'</div>' +
'</div>';
//HTMLに追加
$('#news').append(newsall);
}
},
//取得失敗
function () {
alert("取得に失敗しました。");
});
本来はJSONでGETしたいのですが、GASではCROSではじかれてしまいます。今回はあえてJSONPで取得しています。
実行環境
node v10.0.0
npm v6.4.1
パッケージインストール
npm install
ビルド
npm run build
開発用
npm run dev
開発用で確認してみます。
スプレッドシートの値がNewsに表示されます。
試しに、スプレッドシートの値を追加してみます。
ブラウザをリロードすると、反映されます。