CONTENT
ここから
生成した企画書をドキュメント化して提出しやすくする
この教材では、Google Apps ScriptのWebアプリで、AIが作った文章をGoogle Docsに書き出す仕組みを作ります。
前回までは、企画書、画像プロンプト、動画台本、LP構成をWeb画面に表示し、スプレッドシートに保存してきました。
今回は、その結果を1つのGoogleドキュメントにまとめます。
企画情報を入力する
↓
AIが提出用まとめを作る
↓
Google Docsを自動作成する
↓
提出しやすいURLができる
AIが作った文章は、画面に出るだけでは少しもったいないです。
Google Docsに書き出せるようになると、提出物として見せやすくなります。
このページで完成するもの
今回作るのは、次のようなアプリです。
| 項目 | 内容 |
|---|---|
| 入力 | 企画タイトル、ターゲット、企画書、画像案、動画案、LP構成 |
| AI生成 | 提出用のまとめ文章 |
| Docs作成 | Google Docsに自動書き出し |
| 保存 | スプレッドシートに履歴保存 |
| 出力 | Google DocsのURLを表示 |
今回のゴールはこれです。
AIで作った内容を、
提出できるドキュメントに変える
1. なぜGoogle Docsに書き出すのか
Web画面に表示されたAIの回答は、その場では便利です。
でも、提出するときには少し困ります。
画面を閉じると見つけにくい
コピーし忘れることがある
先生に共有しにくい
あとから見返しにくい
そこで、Google Docsにまとめます。
Google Docsにする
↓
URLで提出できる
↓
後から編集できる
↓
発表にも使いやすい
AIの結果を「その場の答え」で終わらせず、作品として残すための回です。
2. 今回作るファイル
今回も、使うファイルは2つだけです。
Code.gs
index.html
| ファイル | 役割 |
|---|---|
| Code.gs | Gemini APIを呼び出し、Google Docsを作成する |
| index.html | 入力画面と結果表示を作る |
3. 事前準備
Googleスプレッドシートを作ります。
https://sheets.google.com/
ファイル名は次にします。
AI提出ドキュメントメーカー
スプレッドシートからApps Scriptを開きます。
拡張機能
↓
Apps Script
プロジェクト名も、次にします。
AI提出ドキュメントメーカー
4. APIキーを確認する
前回と同じ GEMINI_API_KEY を使います。
Apps Scriptの左側にある歯車アイコンを開きます。
プロジェクトの設定
↓
スクリプト プロパティ
次の名前で保存されていればOKです。
| プロパティ | 値 |
|---|---|
| GEMINI_API_KEY | 自分のGemini APIキー |
APIキーは人に見せないでください。
コードに直接書かず、スクリプトプロパティに保存します。
5. Code.gsを貼り付ける
Code.gs の中身をすべて消して、次のコードを貼り付けます。
const SHEET_NAME = 'Docs書き出し履歴';
const MODEL_NAME = 'gemini-2.5-flash';
function doGet() {
setupSheet_();
return HtmlService
.createHtmlOutputFromFile('index')
.setTitle('AI提出ドキュメントメーカー')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
function createSubmissionDocument(formData) {
validateFormData_(formData);
setupSheet_();
const prompt = buildSubmissionPrompt_(formData);
const summaryText = callGemini_(prompt);
const docInfo = createGoogleDoc_(formData, summaryText);
saveHistory_(formData, summaryText, docInfo.url);
return {
ok: true,
text: summaryText,
docUrl: docInfo.url,
docTitle: docInfo.title,
message: 'Google Docsを作成しました。'
};
}
function buildSubmissionPrompt_(formData) {
return `
あなたは、学生の提出資料を整えるやさしい編集者です。
次の情報をもとに、授業で提出しやすいドキュメント用の文章を作ってください。
【企画タイトル】
${formData.title}
【ターゲット】
${formData.target}
【企画書】
${formData.plan}
【画像プロンプト・画像案】
${formData.imagePrompt || '未入力'}
【15秒動画台本】
${formData.videoScript || '未入力'}
【LP構成】
${formData.lpPlan || '未入力'}
【今日できるようになったこと】
${formData.reflection || '未入力'}
以下の形式で出してください。
1. 企画タイトル
2. ターゲット
3. 企画のコンセプト
4. 画像制作の方針
5. 15秒動画の流れ
6. LP構成の概要
7. 今日できるようになったこと
8. 発表で使える一言
条件:
・提出用として読みやすく整える
・難しい言葉を使わない
・各項目は短めにする
・学生が自分の成果として説明しやすい文章にする
・できたことを前向きに表現する
・未入力の項目は、無理に作りすぎず自然に補う
`;
}
function callGemini_(prompt) {
const apiKey = PropertiesService
.getScriptProperties()
.getProperty('GEMINI_API_KEY');
if (!apiKey) {
throw new Error('GEMINI_API_KEY が設定されていません。');
}
const url =
'https://generativelanguage.googleapis.com/v1beta/models/' +
MODEL_NAME +
':generateContent?key=' +
encodeURIComponent(apiKey);
const payload = {
contents: [
{
role: 'user',
parts: [{ text: prompt }]
}
],
generationConfig: {
temperature: 0.6,
maxOutputTokens: 1600
}
};
const options = {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify(payload),
muteHttpExceptions: true
};
const response = UrlFetchApp.fetch(url, options);
const statusCode = response.getResponseCode();
const responseText = response.getContentText();
if (statusCode !== 200) {
throw new Error('Gemini APIエラー:' + responseText);
}
const json = JSON.parse(responseText);
const text = json.candidates?.[0]?.content?.parts?.[0]?.text;
if (!text) {
throw new Error('AIの回答を取得できませんでした。');
}
return text;
}
function createGoogleDoc_(formData, summaryText) {
const now = Utilities.formatDate(
new Date(),
Session.getScriptTimeZone(),
'yyyyMMdd_HHmm'
);
const safeTitle = sanitizeTitle_(formData.title);
const docTitle = `提出資料_${safeTitle}_${now}`;
const doc = DocumentApp.create(docTitle);
const body = doc.getBody();
body.clear();
body.appendParagraph('AI企画制作 提出資料')
.setHeading(DocumentApp.ParagraphHeading.TITLE);
body.appendParagraph('企画タイトル')
.setHeading(DocumentApp.ParagraphHeading.HEADING1);
body.appendParagraph(formData.title);
body.appendParagraph('ターゲット')
.setHeading(DocumentApp.ParagraphHeading.HEADING1);
body.appendParagraph(formData.target);
body.appendParagraph('提出用まとめ')
.setHeading(DocumentApp.ParagraphHeading.HEADING1);
appendTextAsParagraphs_(body, summaryText);
body.appendParagraph('元データ')
.setHeading(DocumentApp.ParagraphHeading.HEADING1);
body.appendParagraph('企画書')
.setHeading(DocumentApp.ParagraphHeading.HEADING2);
appendTextAsParagraphs_(body, formData.plan);
if (formData.imagePrompt) {
body.appendParagraph('画像プロンプト・画像案')
.setHeading(DocumentApp.ParagraphHeading.HEADING2);
appendTextAsParagraphs_(body, formData.imagePrompt);
}
if (formData.videoScript) {
body.appendParagraph('15秒動画台本')
.setHeading(DocumentApp.ParagraphHeading.HEADING2);
appendTextAsParagraphs_(body, formData.videoScript);
}
if (formData.lpPlan) {
body.appendParagraph('LP構成')
.setHeading(DocumentApp.ParagraphHeading.HEADING2);
appendTextAsParagraphs_(body, formData.lpPlan);
}
if (formData.reflection) {
body.appendParagraph('振り返り')
.setHeading(DocumentApp.ParagraphHeading.HEADING2);
appendTextAsParagraphs_(body, formData.reflection);
}
doc.saveAndClose();
return {
title: docTitle,
url: doc.getUrl()
};
}
function appendTextAsParagraphs_(body, text) {
const lines = String(text || '')
.split('\n')
.map((line) => line.trim())
.filter((line) => line !== '');
if (lines.length === 0) {
body.appendParagraph('未入力');
return;
}
lines.forEach((line) => {
body.appendParagraph(line);
});
}
function saveHistory_(formData, summaryText, docUrl) {
const sheet = SpreadsheetApp
.getActiveSpreadsheet()
.getSheetByName(SHEET_NAME);
sheet.appendRow([
new Date(),
formData.title,
formData.target,
formData.plan,
formData.imagePrompt || '',
formData.videoScript || '',
formData.lpPlan || '',
formData.reflection || '',
summaryText,
docUrl
]);
}
function getRecentDocuments() {
setupSheet_();
const sheet = SpreadsheetApp
.getActiveSpreadsheet()
.getSheetByName(SHEET_NAME);
const lastRow = sheet.getLastRow();
if (lastRow <= 1) {
return [];
}
const values = sheet.getRange(2, 1, lastRow - 1, 10).getValues();
return values
.map((row) => {
return {
createdAt: formatDate_(row[0]),
title: row[1],
target: row[2],
docUrl: row[9]
};
})
.reverse()
.slice(0, 5);
}
function setupSheet_() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
let sheet = ss.getSheetByName(SHEET_NAME);
if (!sheet) {
sheet = ss.insertSheet(SHEET_NAME);
}
if (sheet.getLastRow() === 0) {
sheet.appendRow([
'作成日時',
'企画タイトル',
'ターゲット',
'企画書',
'画像プロンプト',
'動画台本',
'LP構成',
'振り返り',
'AI提出用まとめ',
'Google Docs URL'
]);
}
}
function validateFormData_(formData) {
if (!formData) {
throw new Error('入力データがありません。');
}
const requiredFields = [
['title', '企画タイトル'],
['target', 'ターゲット'],
['plan', '企画書']
];
requiredFields.forEach(([key, label]) => {
if (!formData[key] || String(formData[key]).trim() === '') {
throw new Error(label + 'を入力してください。');
}
});
}
function sanitizeTitle_(title) {
return String(title || '企画')
.replace(/[\\/:*?"<>|]/g, '')
.replace(/\s+/g, '_')
.slice(0, 40);
}
function formatDate_(date) {
if (!date) return '';
return Utilities.formatDate(
new Date(date),
Session.getScriptTimeZone(),
'yyyy/MM/dd HH:mm'
);
}
6. index.htmlを作る
Apps Scriptの左側にある「+」を押します。
+
↓
HTML
ファイル名は次にします。
index
index.html の中身をすべて消して、次のコードを貼り付けます。
<!doctype html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<base target="_top" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AI提出ドキュメントメーカー</title>
<style>
:root {
--bg: #f8fafc;
--card: #ffffff;
--text: #111827;
--muted: #6b7280;
--line: #dbe3ee;
--primary: #10b981;
--primary-dark: #059669;
--soft: #ecfdf5;
--success: #16a34a;
--danger: #dc2626;
}
* {
box-sizing: border-box;
}
body {
margin: 0;
background: linear-gradient(180deg, #f0fdf4 0%, #eef2f8 100%);
color: var(--text);
font-family:
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif;
line-height: 1.7;
}
.page {
width: min(1120px, calc(100% - 32px));
margin: 0 auto;
padding: 32px 0 48px;
}
.hero {
padding: 28px;
margin-bottom: 20px;
border: 1px solid var(--line);
border-radius: 24px;
background: var(--card);
box-shadow: 0 18px 40px rgba(15, 23, 42, 0.08);
}
.badge {
display: inline-flex;
padding: 6px 12px;
border-radius: 999px;
background: var(--soft);
color: var(--primary-dark);
font-size: 13px;
font-weight: 800;
}
h1 {
margin: 18px 0 8px;
font-size: clamp(28px, 5vw, 44px);
line-height: 1.15;
letter-spacing: -0.04em;
}
.lead {
margin: 0;
color: var(--muted);
}
.grid {
display: grid;
grid-template-columns: 0.9fr 1.1fr;
gap: 20px;
}
.card {
border: 1px solid var(--line);
border-radius: 24px;
background: var(--card);
box-shadow: 0 14px 32px rgba(15, 23, 42, 0.06);
overflow: hidden;
}
.card-header {
padding: 20px 22px;
border-bottom: 1px solid var(--line);
background: #fbfdff;
}
.card-header h2 {
margin: 0;
font-size: 20px;
}
.card-header p {
margin: 4px 0 0;
color: var(--muted);
font-size: 14px;
}
form {
padding: 22px;
}
label {
display: block;
margin-bottom: 14px;
font-weight: 800;
}
.hint {
display: block;
margin: 2px 0 6px;
color: var(--muted);
font-size: 13px;
font-weight: 500;
}
input,
textarea {
width: 100%;
border: 1px solid var(--line);
border-radius: 14px;
padding: 12px 14px;
background: #ffffff;
color: var(--text);
font: inherit;
outline: none;
}
textarea {
min-height: 92px;
resize: vertical;
}
textarea.large {
min-height: 130px;
}
input:focus,
textarea:focus {
border-color: var(--primary);
box-shadow: 0 0 0 4px rgba(16, 185, 129, 0.13);
}
.actions {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 20px;
}
button,
.link-button {
border: 0;
border-radius: 14px;
padding: 12px 18px;
cursor: pointer;
font: inherit;
font-weight: 900;
text-decoration: none;
display: inline-flex;
align-items: center;
justify-content: center;
}
button:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.primary {
background: var(--primary);
color: #ffffff;
}
.primary:hover {
background: var(--primary-dark);
}
.secondary {
background: #eef2f7;
color: #111827;
}
.message {
margin: 0 22px 22px;
padding: 12px 14px;
border-radius: 14px;
display: none;
font-weight: 800;
}
.message.success {
display: block;
background: #ecfdf5;
color: var(--success);
}
.message.error {
display: block;
background: #fef2f2;
color: var(--danger);
}
.loading {
display: none;
padding: 14px;
margin: 0 22px 22px;
border-radius: 14px;
background: #fffbeb;
color: #92400e;
font-weight: 800;
}
.loading.show {
display: block;
}
.result {
padding: 22px;
}
.doc-box {
display: none;
padding: 16px;
margin-bottom: 16px;
border-radius: 18px;
background: #ecfdf5;
border: 1px solid #bbf7d0;
}
.doc-box.show {
display: block;
}
.doc-title {
margin: 0 0 8px;
font-weight: 900;
}
.result-box {
min-height: 360px;
padding: 20px;
border-radius: 18px;
background: #111827;
color: #f9fafb;
white-space: pre-wrap;
overflow-wrap: anywhere;
font-size: 15px;
}
.result-empty {
color: #9ca3af;
}
.recent {
padding: 0 22px 22px;
}
.recent-item {
padding: 14px 0;
border-top: 1px solid var(--line);
}
.recent-item:first-child {
border-top: 0;
}
.recent-title {
margin: 0;
font-weight: 900;
}
.recent-meta {
margin: 2px 0 0;
color: var(--muted);
font-size: 13px;
}
.empty {
color: var(--muted);
font-size: 14px;
}
@media (max-width: 920px) {
.grid {
grid-template-columns: 1fr;
}
.hero {
padding: 22px;
}
}
</style>
</head>
<body>
<main class="page">
<section class="hero">
<span class="badge">6-8 Google Docs書き出し</span>
<h1>AIの結果を<br />提出資料にする</h1>
<p class="lead">
企画書、画像案、動画台本、LP構成をまとめて、Google Docsに書き出します。
</p>
</section>
<section class="grid">
<div class="card">
<div class="card-header">
<h2>提出資料の材料を入力</h2>
<p>必須は、企画タイトル・ターゲット・企画書です。</p>
</div>
<form id="docForm">
<label>
企画タイトル
<span class="hint">例:放課後カフェマップ</span>
<input
id="title"
type="text"
placeholder="企画タイトル"
required
/>
</label>
<label>
ターゲット
<span class="hint">例:学校帰りに寄れる場所を探している学生</span>
<input
id="target"
type="text"
placeholder="誰に届けたいか"
required
/>
</label>
<label>
企画書
<span class="hint">6-4で作った企画書を貼り付けます</span>
<textarea
id="plan"
class="large"
placeholder="企画書を貼り付ける"
required
></textarea>
</label>
<label>
画像プロンプト・画像案
<span class="hint">6-5で作った内容を貼り付けます</span>
<textarea
id="imagePrompt"
placeholder="画像プロンプトや画像案"
></textarea>
</label>
<label>
15秒動画台本
<span class="hint">6-6で作った内容を貼り付けます</span>
<textarea
id="videoScript"
placeholder="動画台本"
></textarea>
</label>
<label>
LP構成
<span class="hint">6-7で作った内容を貼り付けます</span>
<textarea
id="lpPlan"
placeholder="LP構成"
></textarea>
</label>
<label>
今日できるようになったこと
<span class="hint">例:AIで企画を提出資料にまとめられた</span>
<textarea
id="reflection"
placeholder="振り返り"
></textarea>
</label>
<div class="actions">
<button class="primary" type="submit" id="createButton">
Google Docsを作る
</button>
<button class="secondary" type="button" id="sampleButton">
サンプル入力
</button>
<button class="secondary" type="button" id="clearButton">
クリア
</button>
</div>
</form>
<div id="loadingBox" class="loading">
AIが提出用に整え、Google Docsを作成しています。少し待ってください。
</div>
<p id="messageBox" class="message"></p>
</div>
<div class="card">
<div class="card-header">
<h2>作成結果</h2>
<p>DocsのURLを提出に使えます。</p>
</div>
<div class="result">
<div id="docBox" class="doc-box">
<p id="docTitle" class="doc-title">Google Docsを作成しました。</p>
<a id="docLink" class="link-button primary" href="#" target="_blank">
Google Docsを開く
</a>
</div>
<div id="resultBox" class="result-box">
<span class="result-empty">ここに提出用まとめが表示されます。</span>
</div>
<div class="actions">
<button class="secondary" type="button" id="copyButton">
まとめをコピー
</button>
</div>
</div>
<div class="card-header">
<h2>最近作ったDocs</h2>
<p>最新5件を表示します。</p>
</div>
<div class="recent" id="recentDocuments">
<p class="empty">まだ履歴がありません。</p>
</div>
</div>
</section>
</main>
<script>
const form = document.getElementById('docForm');
const createButton = document.getElementById('createButton');
const sampleButton = document.getElementById('sampleButton');
const clearButton = document.getElementById('clearButton');
const copyButton = document.getElementById('copyButton');
const loadingBox = document.getElementById('loadingBox');
const messageBox = document.getElementById('messageBox');
const resultBox = document.getElementById('resultBox');
const docBox = document.getElementById('docBox');
const docTitle = document.getElementById('docTitle');
const docLink = document.getElementById('docLink');
const fields = {
title: document.getElementById('title'),
target: document.getElementById('target'),
plan: document.getElementById('plan'),
imagePrompt: document.getElementById('imagePrompt'),
videoScript: document.getElementById('videoScript'),
lpPlan: document.getElementById('lpPlan'),
reflection: document.getElementById('reflection')
};
form.addEventListener('submit', (event) => {
event.preventDefault();
const formData = getFormData();
setLoading(true);
showMessage('', '');
docBox.classList.remove('show');
google.script.run
.withSuccessHandler((result) => {
setLoading(false);
resultBox.textContent = result.text;
docTitle.textContent = result.docTitle;
docLink.href = result.docUrl;
docBox.classList.add('show');
showMessage(result.message || 'Google Docsを作成しました。', 'success');
loadRecentDocuments();
})
.withFailureHandler((error) => {
setLoading(false);
showMessage(error.message || '作成に失敗しました。', 'error');
})
.createSubmissionDocument(formData);
});
sampleButton.addEventListener('click', () => {
fields.title.value = '放課後カフェマップ';
fields.target.value = '学校帰りに友達と寄れる場所を探している学生';
fields.plan.value =
'放課後に使えるカフェや居場所を分かりやすく紹介する企画。勉強にも休憩にも使える場所を、写真や短い説明で見つけやすくする。';
fields.imagePrompt.value =
'夕方のカフェ、ノート、スマホ、ドリンク、柔らかい自然光、16:9、文字なし、ロゴなし。';
fields.videoScript.value =
'0〜3秒:放課後どこ寄る? 3〜7秒:カフェを探せる 7〜12秒:勉強も休憩もできる 12〜15秒:気になる場所を見てみよう。';
fields.lpPlan.value =
'ファーストビュー、企画説明、魅力3つ、画像・動画、最後の案内で構成する。';
fields.reflection.value =
'AIを使って、企画から提出資料までまとめられるようになった。';
showMessage('サンプルを入力しました。自由に書き換えてください。', 'success');
});
clearButton.addEventListener('click', () => {
form.reset();
resultBox.innerHTML =
'<span class="result-empty">ここに提出用まとめが表示されます。</span>';
docBox.classList.remove('show');
showMessage('', '');
});
copyButton.addEventListener('click', async () => {
const text = resultBox.textContent.trim();
if (!text || text === 'ここに提出用まとめが表示されます。') {
showMessage('コピーする文章がありません。', 'error');
return;
}
try {
await navigator.clipboard.writeText(text);
showMessage('提出用まとめをコピーしました。', 'success');
} catch (error) {
showMessage('コピーできませんでした。手動で選択してコピーしてください。', 'error');
}
});
function getFormData() {
return {
title: fields.title.value.trim(),
target: fields.target.value.trim(),
plan: fields.plan.value.trim(),
imagePrompt: fields.imagePrompt.value.trim(),
videoScript: fields.videoScript.value.trim(),
lpPlan: fields.lpPlan.value.trim(),
reflection: fields.reflection.value.trim()
};
}
function setLoading(isLoading) {
createButton.disabled = isLoading;
createButton.textContent = isLoading
? '作成中...'
: 'Google Docsを作る';
loadingBox.classList.toggle('show', isLoading);
}
function showMessage(text, type) {
if (!text) {
messageBox.textContent = '';
messageBox.className = 'message';
return;
}
messageBox.textContent = text;
messageBox.className = 'message ' + type;
}
function loadRecentDocuments() {
google.script.run
.withSuccessHandler(renderRecentDocuments)
.withFailureHandler(() => {
document.getElementById('recentDocuments').innerHTML =
'<p class="empty">履歴を読み込めませんでした。</p>';
})
.getRecentDocuments();
}
function renderRecentDocuments(docs) {
const container = document.getElementById('recentDocuments');
if (!docs || docs.length === 0) {
container.innerHTML =
'<p class="empty">まだ履歴がありません。</p>';
return;
}
container.innerHTML = docs
.map((item) => {
return `
<div class="recent-item">
<p class="recent-title">${escapeHtml(item.title)}</p>
<p class="recent-meta">
${escapeHtml(item.createdAt)}|${escapeHtml(item.target)}
</p>
<a class="link-button secondary" href="${escapeHtml(item.docUrl)}" target="_blank">
Docsを開く
</a>
</div>
`;
})
.join('');
}
function escapeHtml(value) {
return String(value || '')
.replaceAll('&', '&')
.replaceAll('<', '<')
.replaceAll('>', '>')
.replaceAll('"', '"')
.replaceAll("'", ''');
}
loadRecentDocuments();
</script>
</body>
</html>
7. 保存する
コードを貼り付けたら保存します。
Command + S
Windowsの場合は、
Ctrl + S
です。
8. Webアプリとして公開する
右上の「デプロイ」を押します。
デプロイ
↓
新しいデプロイ
種類は、次を選びます。
ウェブアプリ
設定は次の通りです。
| 項目 | 設定 |
|---|---|
| 説明 | 6-8 AI提出ドキュメントメーカー |
| 次のユーザーとして実行 | 自分 |
| アクセスできるユーザー | 自分のみ |
デプロイ後に表示されるURLを開くと、提出ドキュメントメーカーが表示されます。
9. 権限許可について
今回は、Google Docsを作成するため、初回に権限確認が出ます。
表示されたら、次の流れで進めます。
権限を確認
↓
自分のGoogleアカウントを選ぶ
↓
詳細
↓
安全ではないページに移動
↓
許可
自分で作ったGASなので、この教材では許可して進めます。
不安な場合は、先生に確認してください。
10. 動かしてみる
画面が開いたら、まず「サンプル入力」を押します。
そのあと、次のボタンを押します。
Google Docsを作る
少し待つと、右側に提出用まとめが表示されます。
さらに、Google Docsのリンクが表示されます。
Google Docsを開く
このリンクを開いて、ドキュメントが作成されていれば成功です。
11. 生成結果の見方
作成されたGoogle Docsでは、まずこの3つを確認します。
企画タイトルが入っているか
企画内容が読みやすく整理されているか
提出用として見せられる形になっているか
この回では、完璧な文章を目指さなくて大丈夫です。
大切なのは、AIで作ったものを提出できる形に整えることです。
12. うまくいかない時
Docsが作られない
権限許可ができていない可能性があります。
もう一度、Apps Script側で実行して、権限を許可してください。
エラーが出る
GEMINI_API_KEY を確認してください。
プロジェクトの設定
↓
スクリプト プロパティ
↓
GEMINI_API_KEY
Google DocsのURLが出ない
createGoogleDoc_() の中に DocumentApp.create() があるか確認します。
内容が長すぎる
buildSubmissionPrompt_() の条件に、次を追加します。
・全体を短めにまとめる
・1項目は2〜3行以内にする
13. 今日の提出物
この回の提出物は、次の3つです。
1. WebアプリURL
2. 作成されたGoogle DocsのURL
3. スプレッドシートの履歴スクリーンショット
最低限は、これでOKです。
AIの生成結果をGoogle Docsに書き出せた
14. チェックリスト
| チェック | 内容 |
|---|---|
| スプレッドシートを作った | |
| Apps Scriptを開いた | |
| GEMINI_API_KEYを確認した | |
| Code.gsを貼り付けた | |
| index.htmlを作った | |
| index.htmlを貼り付けた | |
| Webアプリとしてデプロイした | |
| WebアプリURLを開いた | |
| サンプル入力を押した | |
| Google Docsを作るを押した | |
| Google DocsのURLが表示された | |
| Docsを開いて内容を確認した | |
| スプレッドシートに履歴が保存された |
まとめ
今回は、AIで作った内容をGoogle Docsに書き出すアプリを作りました。
これで、AIの結果はただの画面表示ではなくなります。
企画書
↓
画像案
↓
動画台本
↓
LP構成
↓
Google Docs
最後にDocsとして残ると、企画は提出できる資料になります。
AIは、答えを出すだけの道具ではありません。
自分の考えを整理して、誰かに届ける形にするための相棒にもなります。
ここまでできれば、次はいよいよ仕上げです。
作ったツールを使って、今日中に1つの企画を提出できる形にまとめていきます。