こんにちは、イカPOです。
今回は HtmlService.createTemplateFromFile を使うと、テンプレートファイルを使用して HTML をブラウザに表示できます。
テンプレートファイルを作成するとコードの管理が楽になります。GAS で HTML を表示させるなら、前回紹介した HtmlService.createHtmlOutput() よりもおススメです。
HtmlService.createTemplateFromFile()の最小構成
ここでは「とにかく 1 画面出すだけ」の最短サンプルを示します。テンプレ分離のイメージをつかんでください。
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<base target="_top">
</head>
<body>
<h1>WEBアプリだよ</h1>
</body>
</html>
<base target="_top">
… 外部リンクを「親タブ」で開くためのおまじない。必須ではありませんが、Apps Script では入れておくのが通例です。
コード.gs
function doGet(e) {
const template = HtmlService.createTemplateFromFile('index');
const htmlOutput = template.evaluate();
return htmlOutput;
}
処理 | 内容 |
---|---|
createTemplateFromFile('index') | index.html を読み込みテンプレートオブジェクトを生成 |
evaluate() | テンプレートを HtmlOutput に変換 |
return htmlOutput | ブラウザへ返却(doGet / doPost は必ず HtmlOutput を返す) |
手順①:テンプレート HTML を作成する
HTML ファイル(ここでは index.html
)をプロジェクト内に用意します。

その際に
<base target="_top">
を入れておくと、テンプレート内リンクが iframe ではなく親ウィンドウで開くようになります。“GAS で HTML を表示するときのお作法” と覚えておくとラクです。
手順②:doGet / doPost でテンプレートを読み込む
doGet(e)
内で、先ほど作ったテンプレートファイルを読み込みます。
const template = HtmlService.createTemplateFromFile('index');
HtmlService.createTemplateFromFile('ファイル名')
で使用できます。今回作成したファイル名は「index」なので ('index')
と書きます。
const htmlOutput = template.evaluate();
読み込んだ HTML ファイルを HtmlOutput オブジェクト に変換します。doGet()
/ doPost()
では 文字列 ではなく このオブジェクトを return する のが約束事です。
return htmlOutput;
変換したオブジェクトを表示します。
まとめ
“ファイルを読み込む → テンプレートを展開する →return
でブラウザに返す”
これが createTemplateFromFile の基本フローです。
生出力タグで GAS 生成のテーブル HTML をそのまま描画する
<?!= … ?>
をテンプレート内で使用すると、GAS で作った HTML 要素をそのまま出力できます。以下に実例を載せます。
使用例
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<base target="_top">
<title>WEBアプリだよ</title>
<style>
body { padding: 1rem; }
</style>
</head>
<body>
<h1>WEBアプリだよ</h1>
<p>以下のように <table> タグで作成できます。</p>
<div>
<?!= itemTable ?>
</div>
</body>
</html>
<?!= itemTable ?>
… エスケープせずに生 HTML をそのまま挿入します。
コード.gs
function doGet(e) {
const template = HtmlService.createTemplateFromFile('table');
template.itemTable = getItem(); // ← getItem() が返すテーブル HTML を渡す
const htmlOutput = template.evaluate();
return htmlOutput;
}
getItem() ― スプレッドシート → HTML テーブル変換
/**
* 商品一覧シートからデータを取得し、HTML テーブル文字列を返す
*/
function getItem() {
// ① アクティブなスプレッドシートを取得
const ss = SpreadsheetApp.getActiveSpreadsheet();
// ② 「商品一覧」シートを取得
const sheet = ss.getSheetByName('商品一覧');
// ③ シート全体の値を 2 次元配列で取得
// data[0] がヘッダー行、data[1] 以降がデータ行
const data = sheet.getDataRange().getValues();
// ④ 先頭行(ヘッダー)を取り出し、残りをデータとして保持
const headers = data.shift(); // headers = ["商品ID", "商品名", "カテゴリー", "在庫数"]
// ⑤ ヘッダー名 → 列インデックス の対応表を生成
// 例: headerMap["商品名"] === 1
const headerMap = {};
headers.forEach(function(header, index) {
headerMap[header] = index;
});
// ⑥ <thead> 部分 ─ ヘッダー配列を <th> で包み、空文字区切りで連結
const thRow = headers
.map(function(head) { return `<th>${head}</th>`; })
.join('');
// ⑦ <tbody> 部分 ─ 各データ行を <tr><td>…</td></tr> 形式の文字列に変換
const tdRow = data
.map(function(itemData) {
return `
<tr>
<td>${parseInt(itemData[headerMap["商品ID"]], 10) || 0}</td>
<td>${itemData[headerMap["商品名"]]}</td>
<td>${itemData[headerMap["カテゴリー"]]}</td>
<td>${parseInt(itemData[headerMap["在庫数"]], 10) || 0}</td>
</tr>`;
})
.join('');
// ⑧ 最終的な HTML テーブルを組み立て
const html = `
<table id="itemTable" class="table table-striped table-hover align-middle">
<thead class="table-primary">
<tr>${thRow}</tr>
</thead>
<tbody>${tdRow}</tbody>
</table>`;
// ⑨ 呼び出し元へ HTML 文字列を返す
return html;
}
ポイント
- ⑥で
<thead>
、⑦で<tbody>
を個別に組み立てると、後でスタイルを付けやすくなります。- 数値列には
parseInt()
をかませておくと “空セル → 0” のフォールバックが効きます。
まず、前回も使用した 商品一覧シート → HTML テーブル文字列 を返す getItem()
でテーブルを作成します。
template.itemTable = getItem();
その後、doGet
内で itemTable を定義し、テーブルの HTML 要素をテンプレートに渡します。
index.html 内の
<div>
<?!= itemTable ?>
</div>
で itemTable を呼び出しています。
HtmlService.createHtmlOutput() と HtmlService.createTemplateFromFile() のちがいについて
比較項目 | createHtmlOutput() | createTemplateFromFile() |
---|---|---|
目的例 | すぐに “Hello world” を出したい | HTML/CSS/JS を分割管理したい |
HTML の書き方 | JS 文字列で直接書く | 外部 .html をテンプレートとして読み込む |
変数の埋め込み | replace() 等で手動置換 | <?= var ?> / <?!= var ?> でワンタッチ |
保守性 | 長い HTML だと可読性↓ | ファイル分離で可読性◎ |
用途まとめ
- createHtmlOutput() … デバッグ用、ワンライナーで済ませたいとき
- createTemplateFromFile() … 本番 UI、複数ページ、リッチ画面を作るとき
createHtmlOutput()についての記事はこちらも
スタイル & JavaScript の組み込み
以下は Bootstrap + カスタム CSS + JavaScript の例
コードは原文そのまま掲載し、誤記タグのみ訂正しています。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<base target="_top">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Bootstrap 5 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>WEBアプリだよ</title>
<style>
body { padding: 1rem; }
/* ─────────── テーブル全体 ─────────── */
#itemTable {
--bs-table-striped-bg: #f6faff; /* 奇数行色 */
--bs-table-hover-bg: #edf4ff; /* ホバー色 */
border-radius: .5rem;
overflow: hidden;
box-shadow: 0 .125rem .75rem rgba(0,0,0,.05);
}
/* ─────────── ヘッダー ─────────── */
#itemTable thead th {
background: #0d6efd;
color: #fff;
font-weight: 600;
position: sticky; top: 0; z-index: 2;
}
/* ─────────── セルの配置調整 ─────────── */
#itemTable tbody td:nth-child(1){text-align:center;}
#itemTable tbody td:nth-child(4){text-align:right;}
/* ─────────── カテゴリーをバッジ風 ─────────── */
#itemTable tbody td:nth-child(3){
font-weight: 500; padding:.35rem .75rem; border-radius:9999px;
background:#e8f1ff; color:#0d6efd;
}
</style>
</head>
<body>
<h1 class="h4 mb-3">WEBアプリだよ</h1>
<p class="mb-4">以下のように <table> タグで作成できます。</p>
<div class="table-responsive">
<?!= itemTable ?> <!-- テーブルを挿入 -->
</div>
<div class="d-flex gap-2 mt-4">
<button id="addRowBtn" class="btn btn-primary btn-sm">行を追加</button>
</div>
<script>
// デモ用:ダミーデータで行を追加
document.getElementById('addRowBtn').addEventListener('click', () => {
const tbody = document.querySelector('#itemTable tbody');
const newRow = tbody.insertRow();
const idCell = newRow.insertCell();
const nameCell = newRow.insertCell();
const categoryCell = newRow.insertCell();
const stockCell = newRow.insertCell();
const nextId = 1000 + tbody.rows.length;
idCell.textContent = nextId;
nameCell.textContent = 'デモ用品';
categoryCell.textContent = 'テスト';
stockCell.textContent = Math.floor(Math.random() * 10) + 1;
});
</script>
</body>
</html>
テンプレートファイル内に CSS と JavaScript を自由に書けるので、Bootstrap も組み合わせれば簡単にリッチな Web ページが作れます。外部ファイルにまとめて読み込む方法もありますが、それはまた別の記事で!
まとめ
- テンプレートファイルを分離すると、HTML/CSS/JS と GAS ロジックをきれいに分けられる。
createTemplateFromFile()
→evaluate()
→return
の 3 ステップが基本形。<?!= … ?>
タグで GAS から渡した生 HTML をそのまま描画できる。- Bootstrap などの外部ライブラリも普通の HTML と同じ要領で利用可能。