Googleスプレッドシートをデータベースとして扱い、スプレッドシートの値をWebサイト上に表示したくなるときありますよね(?)
今回は次のようなアプリを作ってみました!
- 会社情報をスプレッドシートで管理する
- 会社情報が追加(行の追加)されるとページを生成する
- Next.jsのDynamic Routesで動的にページを生成する
http://XXXXXX/company/a-company
にアクセスすると各社の情報が見れるようになります。
Googleスプレッドシートの用意
次にGASに下記のコードを追加します。
function readData() {
const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
const sheet1 = spreadsheet.getSheetByName('シート1');
const lastRow = sheet1.getLastRow();
const data_range = sheet1.getRange(`A2:D${lastRow}`);
const data_values = data_range.getValues();
const return_data = data_values.map(data_row => {
return {
id: data_row[0], // スプレッドシートのA列の値を追加
companyName: data_row[1], // スプレッドシートのB列の値を追加
companyLogo: data_row[2], // スプレッドシートのC列の値を追加
sales: data_row[3], // スプレッドシートのD列の値を追加
}
});
console.log(return_data)
return return_data;
}
function doGet() {
const data = readData();
const response = ContentService.createTextOutput();
response.setMimeType(ContentService.MimeType.JSON);
response.setContent(JSON.stringify(data));
return response;
}
こちらのコードは下記の記事を参考にしております。
readData
関数でスプレッドシート内のデータを取得してjson形式でデータを返しています。
return_data
の中身がこちらになります。
[ { id: 'a-company',
companyName: 'A農業',
companyLogo: '',
sales: 300
},
{ id: 'b-company',
companyName: 'B工業',
companyLogo: '',
sales: 400
},
{ id: 'c-company',
companyName: 'C Tech Inc',
companyLogo: '',
sales: 1000
}
]
doGet
関数内のContentService
でGASで表示されるURLでテキストを確認できるようになります。
右上の「デプロイ」のボタンを押します。
新しいデプロイをすると、URLが発行されてそのURLにアクセスすると先程確認したJSON形式のデータがブラウザで確認できるようになります。
あとは、Next.jsでそのURLからデータをフェッチして画面に表示させることができれば完成です。
Next.jsで動的にページを生成する
プロジェクトの作成
Next.js
のプロジェクトを作成します。
プロジェクトの作り方は公式ドキュメントを参考にしてもらえば問題ないかなと思うのでここでは、省略します。
公式ドキュメント - Next.js Getting Started Installation
動的ページの作成
まずは、動的ページのテンプレートを作成します。下記のようにページを作成します。
公式ドキュメント - Next.js / Dynamic Routes
src
└ app
└ company
└ [slug]
└ page.tsx
page.tsx
には一旦下記のように記述しておきましょう。
export default function Page({ params }: { params: { slug: string } }) {
return <div>Company Name: {params.slug}</div>
}
この構成でページを作成することで下記のようなURLにアクセスしたときにページを表示させることができます。
http:XXXX.com/company/a-works
http:XXXX.com/company/b-works
次にGoogleスプレッドシートからデータを取得してくる処理を記述します。
// src/app/company/[slug]/page.tsx
'use client'
import React, { useState, useEffect } from 'react';
export default function Page({ params }: { params: { slug: string } }) {
useEffect(() => {
fetch('発行されたURL')
.then(response => response.json())
.then(data => {
console.log(data);
})
.catch(err => {
console.log(err);
});
}, []);
return (
<section>
<div>Company Name: {params.slug}</div>
</section>
)
}
console.log(data);
で確認するとデータが入ってきているのがわかります。
useState
で会社情報をさせます。
また、今回は会社情報の詳細ページを表示させたいのでfindで検索しています。
'use client'
import React, { useState, useEffect } from 'react';
export default function Page({ params }: { params: { slug: string } }) {
const [company, setCompany] = useState(null);
useEffect(() => {
fetch('発行されたURL')
.then(response => response.json())
.then(data => {
const selectedCompany = data.find(c => c.id === params.slug);
setCompany(selectedCompany);
})
.catch(err => {
console.log(err);
});
}, [params.slug]);
if (!company) {
return <div>Loading...</div>;
}
return (
<section>
<div>Company Name: {params.slug}</div>
</section>
)
}
あとはreturn
文の中にcompany
に保持されている情報を出力させます。
tailiwindで適当にスタイリングしています。
'use client'
import React, { useState, useEffect } from 'react';
export default function Page({ params }: { params: { slug: string } }) {
const [company, setCompany] = useState(null);
useEffect(() => {
fetch('https://script.google.com/macros/s/AKfycbz7ZSP4g9roCTeTOYpL7RjWHO2E2oFo48bVT-4SdHk8ak8IIoyXbu9DK6FBN2iVTyqi/exec')
.then(response => response.json())
.then(data => {
const selectedCompany = data.find(c => c.id === params.slug);
setCompany(selectedCompany);
})
.catch(err => {
console.log(err);
});
}, [params.slug]);
if (!company) {
return <div>Loading...</div>;
}
return (
<section className="">
<div className="max-w-md rounded overflow-hidden shadow-lg p-4 bg-white shadow-lg">
<h1 className="font-bold text-2xl mb-2 text-gray-700">会社名:{company.companyName}</h1>
<div className="flex justify-center">
<img className="w-96" src={company.companyLogo} alt={`${company.companyName} logo`} />
</div>
<p className="font-bold text-2xl mb-2 text-gray-700 mt-4">売上: {company.sales}円</p>
</div>
</section>
)
}
こんな形で各ページを作成することができました。(左から下記のURLにアクセスしたときの表示)
まとめ
意外と簡単にできたし、アイディア次第ではわざわざ大掛かりな開発をしなくても、少工数でやりたいことを実現できることがありそうだなと感じました。
ちなみに、今回使った会社のロゴはChatGPTに生成してもらいました。