勉強したことのメモ

webプログラマが勉強したことのメモ。

GASで祝日一覧(年月日と祝日名)データをJSON出力するAPIを作成

   

PHPのシステム案件で祝日を取得し、処理を行う箇所があった。GoogleカレンダーのAPIに接続してどうこうしようかと考えたが、カレンダーAPIを使ったことが無いのと、GoogleMapsAPIみたいにAPIキーが必須だった場合、クライアント様にキーを発行いただく必要がありその辺りが面倒だった。結局のところ他所様のAPIを使用して実装したが、よくよく考えればこういった時こそGoogle Apps Scriptの出番じゃないかと思った。以下に祝日APIの作成方法をメモ。

 

やりたいこと

今年と来年の祝日一覧(年月日と祝日名)をJSON出力するAPIを作成したい。

APIリクエスト時にGoogleログイン認証は不要だが、GoogleMapsAPIのAPIキーのようにGETパラメータをつけることで認証させたい。もちろんキーが無い場合はデータを返さない。

法改正等による祝日の変更を考慮し、1日に1回Googleカレンダーから祝日データを引っ張ってきてスプレッドシートに保存・更新したい。

 

GAS側の作業

必要な作業はプログラムの作成、トリガーの設定、デプロイになる。

プログラムの作成

//スプレッドシートに祝日データを書き込む関数
function setHoliday(){

	//開始年月日と終了年月日の指定
	const now = new Date();
	const start = now.getFullYear() + '-01-01';
	const end = (now.getFullYear() + 1) + '-12-31';

	//Googleカレンダーから祝日取得
	const calendar = CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com').getEvents(new Date(start), new Date(end));

	//祝日データを整形して配列に格納
	const result = [];
	for( var i = 0; i < calendar.length; i++ ){
		result[i] = [
			Utilities.formatDate(calendar[i].getStartTime(), 'JST', 'yyyy-MM-dd'), 
			calendar[i].getTitle()
		];
	}

	//正常にデータが取得できた場合、スプレッドシートに書き込み
	if( result.length ){

		//スプレッドシートの読み込み
		const sheet = SpreadsheetApp.getActiveSpreadsheet();

		//シートを指定
		const holidaySheet = sheet.getSheetByName('holiday');

		//シートにまとめて書き込み
		holidaySheet.getRange(1, 1, result.length, result[0].length).setValues(result);
	}
}

//祝日データをJSON出力
function getHoliday(){

	//スプレッドシートの読み込み
	const sheet = SpreadsheetApp.getActiveSpreadsheet();

	//シートを指定
	const holidaySheet = sheet.getSheetByName('holiday');

	//シートのデータを取得
	const holidaySheetVal = holidaySheet.getDataRange().getValues();

	//年月日の整形
	for( let i = 0; i < holidaySheetVal.length; i++ ){
		holidaySheetVal[i][0] = Utilities.formatDate(holidaySheetVal[i][0], 'JST', 'yyyy-MM-dd');
	}

	//データをJSON化
	const payload = JSON.stringify(holidaySheetVal);

	//Textoutputオブジェクトを生成
	const output = ContentService.createTextOutput();

	//Mime TypeをJSONに設定
	output.setMimeType(ContentService.MimeType.JSON);

	//データ出力
	output.setContent(payload);

	return output;
}

//API呼び出し時に動作する関数
function doGet(e){
	const key = e.parameter.key;
	const apiKey = 'xxxxxxxxxxxxxxxx';

	if( key != apiKey ){
		return ContentService.createTextOutput('アクセスできませんでした。');
	}

	return getHoliday();
}

カレンダーデータ取得部分のエラー

「CalendarApp.getCalendarById('ja.japanese#holiday@group.v.calendar.google.com')」の部分が動かず、以下のようなエラーメッセージが表示された。

TypeError: Cannot find function getEvents in object

GASで使うGoogleアカウントが最近取得したばかりでGoogleカレンダーを作成していなかった。Googleカレンダーを作成することで上記エラーが改善された。

他には以下のような場合もある模様。

https://teratail.com/questions/189134

http://syasuda.com/d/blog/2016/11/googleid.html

API呼び出し時

「const apiKey = 'xxxxxxxxxxxxxxxx';」の部分は適宜変更する。

年月日のフォーマット

「Utilities.formatDate(年月日データ, 'JST', 'yyyy-MM-dd')」でフォーマットする。フォーマット指定文字は以下の通り。

https://sites.google.com/site/gasgaidobukku/utilities/formatdate

APIリクエスト時のGETパラメータ取得

APIリクエスト時はdoGet関数が動作する。GETパラメータを取得したい場合は「e.parameter.パラメータのキー」で取得できる。リファレンスは以下の通り。

https://developers.google.com/apps-script/guides/web

トリガーの設定

setHoliday関数が1日1回動作するようトリガーを設定しておく。

デプロイ

「右上のデプロイボタン→新しいデプロイ」に進み「説明」は適当、「種類の選択」はウェブアプリ、「次のユーザーとしての実行」を自分、「アクセスできるユーザー」を全員で設定する。何故か初回デプロイ時は「アクセスできるユーザー」に全員の選択肢が無かった。「デプロイを管理→アーカイブ」で削除すると2回目以降からは全員を選択できた。

デプロイが完了するとURLが発行されるのでブラウザから開いてみると正常に動作した。尚、APIキーをGETパラメータとして付与するのを忘れないよう注意する。

 

API利用時の注意

GASの利用制限や上限にひっかからないよう、API利用時はデータを取得後にファイル化するのが良さそう。データとは別にファイルの有効期限を設定しておき、有効期限が切れていれば再度APIからデータを取得するような形が望ましいかと思われる。ざっくりとだけど以下のような形。

//祝日APIにリクエスト
$api = file_get_contents('http://api.com/');
$holiday = json_decode($api, true);

//JSONファイル用の制限時間
$holiday['limit'] = date('Y-m-d H:i:s', strtotime('+1 day'));

//JSONファイル上書き保存
file_put_contents('./holiday.json', json_encode($holiday));

 

所感

GASはイマイチ業務での使いどころが思いつかないなぁ、とか考えながら勉強していたがやっと役に立ちそうなケースが出てきて嬉しい。

 - Google Apps Script, Google

  関連記事

GoogleMapAPIでヒートマップを表示する方法

GoogleMapAPIで花粉状況や雨量を可視化しやすいようなヒートマップ的なも ...

GASでGoogleカレンダーと連携してイベントの取得・追加・削除

Google Apps Scriptの勉強としてGoogleカレンダーと連携させ ...

Google map APIでマーカー(アイコン)を好きな画像に変える

Googleマップでユーザーにマーカー画像をアップロードさせて、それをマップ表示 ...

google map apiとPHPを組み合わせて複数マーカーとウィンドウを連携させる

やりたかった事は、 mysqlから経度緯度、マーカー名、マーカーIDを持ってきて ...

GoogleMapAPIで住所・経度緯度入力後にマーカーを移動させる

フォーム内に住所・経度・緯度のテキストボックスを設置し、住所を入力後にボタンを押 ...

GoogleMapで都道府県の中心地と県庁所在地

GoogleMapで都道府県の中心地もしくは県庁所在地にマーカーを立てたかった。 ...

GoogleスプレッドシートとPHPの連携

GoogleスプレッドシートとPHPプログラムを連携させたいという案件をたまに見 ...

GoogleMapで半径●メートルを範囲表示

GoogleMapでマーカーを立てて、そこから範囲●mもしくは●kmを円で表示さ ...

GASを使ってみて感じたメリットとデメリット

Google Apps Scriptを色々勉強した中で感じたメリットとデメリット ...

GoogleMapでマーカーをまとめる

GoogleMapAPIでマーカーを複数表示し、近隣のエリアごとにまとめて表示さ ...