シートの4列をHTMLの画像一覧へ変換します。
画像の配信用URLと、参照元の閲覧URLを別の列にします。
Driveの共有URLを文字列変換するだけでは画像配信や権限の問題を解決できないため、この例では変換しません。
最終確認は2026年10月2日です。
ローカルの模擬検証を行いましたが、Googleへの認可・実シートへの反映・Driveの実ファイル列挙・Webアプリの配備は未検証です。
練習用の入力と設定
ZIPを展開し、使う記事のarticle-347.jsだけをApps Scriptへ保存します。
同名の関数を含むため、別の記事のコードを同じプロジェクトへ混ぜないでください。
| 設定名 | 設定する値 |
|---|---|
| SPREADSHEET_ID | 架空の4列を入力した練習用スプレッドシートID |
| SHEET_NAME | 4列を入力したシート名 |
プロジェクトの設定でスクリプトプロパティを入力します。
まず新規の練習データを使い、要求される認可範囲と操作内容を確認してください。
入力例と実行する関数
架空の名前と備考、画像URLを空欄にしたHTMLを返します。
A1:D1を名前・画像URL・参照元URL・備考の見出しにし、2行目へ練習A、空欄、https://cg-method.com/、<文字として表示>を入力します。
previewHtmlの結果は画像なしと表示され、備考の記号がHTMLタグとして実行されない形になります。
WebアプリではdoGetがHTMLを返します。
まずテスト用の配備で対象ユーザーと実行するアカウントを確認し、意図しない公開範囲へ変更しないでください。
閲覧者へ公開されるHTMLとURLには個人情報や秘密を入れず、シートを読む権限と閲覧者のアクセス条件を実環境で確認します。
// このコードは記事ごとに別のApps Scriptプロジェクトへ保存します。
function required_(key) {
const value=PropertiesService.getScriptProperties().getProperty(key);
if (!value) throw new Error(key+'を設定してください');
return value;
}
function safeCell_(value) {
const s=String(value);
return /^[=+@-]/.test(s) ? "'"+s : s;
}
function escapeHtml_(value) {
return String(value).replace(/[&<>"']/g,c=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[c]));
}
function https_(value) {
const s=String(value).trim();
if (!/^https:\/\/[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?(?::443)?(?:[/?#][^\s<>"'\\]*)?$/i.test(s)) throw new Error('HTTPS URLを確認してください');
return s;
}
function sourceSheet_() {
const sheet=SpreadsheetApp.openById(required_('SPREADSHEET_ID')).getSheetByName(required_('SHEET_NAME'));
if (!sheet) throw new Error('対象シートがありません');
return sheet;
}
function imageListHtml_(rows) {
if(rows.length>1000) throw new Error('1000行以内にしてください');
const body=rows.filter(row=>row.some(v=>v!=='')).map((row,index)=>{
if(row.length!==4) throw new Error('4列にしてください');
const [name,image,link,note]=row;
const src=image==='' ? '' : https_(image);
// Driveの共有ページを画像配信URLへ変換しません。
if(/^https:\/\/(?:drive|docs)\.google\.com(?:[:/?#]|$)/i.test(src)) throw new Error('画像配信用HTTPS URLを指定してください');
const href=link==='' ? '' : https_(link);
return '<tr><td>'+escapeHtml_(name)+'</td><td>'+(src ? '<img loading="lazy" referrerpolicy="no-referrer" src="'+escapeHtml_(src)+'" alt="'+escapeHtml_(name)+'">' : '画像なし')+'</td><td>'+(href ? '<a rel="noopener noreferrer" target="_blank" href="'+escapeHtml_(href)+'">参照元</a>' : 'リンクなし')+'</td><td>'+escapeHtml_(note)+'</td></tr>';
}).join('');
return '<!doctype html><html lang="ja"><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>練習用画像一覧</title><style>body{font-family:sans-serif;margin:16px}.wrap{overflow:auto}table{border-collapse:collapse}td,th{border:1px solid #999;padding:8px;min-width:8em}img{width:150px;height:150px;object-fit:contain}</style><div class="wrap"><table><thead><tr><th>名前</th><th>画像</th><th>参照元</th><th>備考</th></tr></thead><tbody>'+body+'</tbody></table></div></html>';
}
function demoHtml(){return imageListHtml_([['練習A','','https://cg-method.com/','<文字として表示>']]);}
function previewHtml() {
const sheet=sourceSheet_(),last=sheet.getLastRow();
const rows=last<2 ? [] : sheet.getRange(2,1,last-1,4).getDisplayValues();
return imageListHtml_(rows);
}
function doGet(){return HtmlService.createHtmlOutput(previewHtml());}
確認結果と切り分け
| 条件 | 結果 |
|---|---|
| 備考にHTML記号 | エスケープして文字として出力 |
| 不正なURL・Drive共有ページの画像欄 | 生成前にエラー。権限を広げない |
| 空欄 | 空の入力行は除外。画像なし・リンクなしを区別 |
Node.jsの模擬検証は5記事合計69ケースです。
純粋関数の結果と、模擬のGoogleオブジェクトで対象選択・書込先・失敗時停止を確認した範囲であり、実サービスの成功を示すものではありません。
画像は公開してよい配信用HTTPS URLを使います。
URLの形式が正しくてもアクセス制限・配信元の設定・ブラウザーの制限で表示できない場合があり、実際の画像表示は別に確認します。
停止と戻し方
この例は定期トリガーを作成しません。
既存トリガーから呼ぶ変更を加える場合は、まず手動の1回を確認し、停止時にはそのトリガーを止めます。
Webアプリを公開している場合は配備を停止するか、保存した旧版へ戻し、公開ページを再読み込みして確認します。
プロパティの変更は開いたページへ自動反映されません。
公式資料
Driveフォルダの取得と列挙、シート範囲への反映、HTMLへの出力とエスケープ、Apps Scriptの利用上限を参照してください。
関連記事・旧実装の参考資料
従来のコードや外部の参考例は、本稿の練習ZIPと内容が異なる場合があります。
今回のコードは記事ごとに別のプロジェクトへ保存してください。





よくある質問:GASで画像リンク付きHTMLリストを作るときのチェックリスト
このスクリプトは、何をしますか?
シートの4列(名前・画像URL・参照元URL・備考)を読み、画像付きのHTMLリストに変換します。画像の配信用URLと、参照元の閲覧URLは別の列に分けて扱います。
Driveの共有URLをそのまま画像URLに使えますか?
記事の例では使いません。Driveの共有ページのURLは画像そのものではないため、文字列を置き換えるだけでは画像配信や権限の問題は解決しません。画像は、公開してよい配信用のHTTPS URLを使います。
備考欄にHTMLの記号が入っていたら、どうなりますか?
HTMLタグとして実行されず、エスケープされて文字として出力されます。不正なURLやDriveの共有ページが画像欄に入っている場合は、生成前にエラーになり、権限は広げません。
画像URLが空欄の行は、どう扱われますか?
空の入力行は除外されます。画像URLだけが空欄の行は、「画像なし」として表示します。リンクなしとも区別します。
URLの形式が正しければ、画像は必ず表示されますか?
表示されるとは限りません。アクセス制限・配信元の設定・ブラウザーの制限で表示できない場合があるため、実際の表示は別に確認してください。
Webアプリとして公開するときの注意点は?
まずテスト用の配備で、対象ユーザーと実行するアカウントを確認します。意図しない公開範囲へ変更しないでください。公開するHTMLとURLには、個人情報や秘密を入れないでください。
この記事のコードは、動作確認済みですか?
Node.jsの模擬検証(5記事合計69ケース)は行いましたが、実サービスの成功を示すものではありません。Googleへの認可・実シートへの反映・Driveの実ファイル列挙・Webアプリの配備は未検証です。まず新規の練習データで試してください。
