Notionのデータベースをスプレッドシートへ自動で転記しよう
この記事では、NotionのデータベースをGoogleスプレッドシートへ自動で転記する方法を、初心者向けにカンタンに解説します。
はじめに
今回は以下のようなデータベースを例に進めます。
| タスク | 日付 | 進捗 | 備考 |
|---|---|---|---|
| サンプルA | 2026-04-01 | 完了 | メモ |
| サンプルB | 2026-04-02 | 作業中 | メモ |
全体の流れ(ざっくり理解)
まずは全体像を理解しましょう。
- NotionでAPIキーを取得
- データベースIDを取得
- GASでAPIを呼び出す
- スプレッドシートに書き込む
この4ステップで連携できます。
Notion APIの準備
① インテグレーション作成
- Notionの「My integrations」にアクセス
- 「新しいインテグレーションを作成」をクリック
- 名前を入力して作成
Notionの「My integrations」にアクセスするには「設定」→「コネクト」→「インテグレーションを作成または管理する」をクリック

「新しいインテグレーションを作成」の左の「+」ボタンをクリックして新規作成

「インテグレーション名」にわかりやすい名前を入力する。
「関連ワークスペース」の欄をクリックして使用するワークスペースを選択する。
「作成」ボタンをクリックして作成します。
② APIキー取得
作成後に表示される「Internal Integration Token」をコピー
③ データベースと接続
対象データベース右上の「…」→「接続を追加」から、作成したIntegrationを追加
NotionデータベースIDの取得方法
URLから取得できます。
<https://www.notion.so/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx?v=yyyy>
この「xxxxxxxx」の部分がデータベースIDです。
Google Apps Script(GAS)の準備
- Googleスプレッドシートを開く
- 「拡張機能」→「Apps Script」を開く
- 新規プロジェクト作成
【サンプル①】全項目を転記
データベースの項目をすべてシートに転記するサンプルです。
function notionToSheet_All() {
const token = "YOUR_NOTION_API_KEY";
const databaseId = "YOUR_DATABASE_ID";
const url = `https://api.notion.com/v1/databases/${databaseId}/query`;
const options = {
method: "post",
headers: {
"Authorization": "Bearer " + token,
"Notion-Version": "2022-06-28",
"Content-Type": "application/json"
}
};
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet.clear();
// ヘッダー
sheet.appendRow(["タスク", "日付", "進捗", "備考"]);
data.results.forEach(page => {
const props = page.properties;
const task = props["タスク"].title[0]?.plain_text || "";
const date = props["日付"].date?.start || "";
const status = props["進捗"].select?.name || "";
const note = props["備考"].rich_text[0]?.plain_text || "";
sheet.appendRow([task, date, status, note]);
});
}
【サンプル②】特定の項目のみ転記
以下は「タスク」と「進捗」だけ転記する例です。
function notionToSheet_Selected() {
const token = "YOUR_NOTION_API_KEY";
const databaseId = "YOUR_DATABASE_ID";
const url = `https://api.notion.com/v1/databases/${databaseId}/query`;
const options = {
method: "post",
headers: {
"Authorization": "Bearer " + token,
"Notion-Version": "2022-06-28",
"Content-Type": "application/json"
}
};
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet.clear();
sheet.appendRow(["タスク", "進捗"]);
data.results.forEach(page => {
const props = page.properties;
const task = props["タスク"].title[0]?.plain_text || "";
const status = props["進捗"].select?.name || "";
sheet.appendRow([task, status]);
});
}
【サンプル③】条件に合うデータのみ転記
「進捗」が「完了」のものだけ取得します。
function notionToSheet_Filtered() {
const token = "YOUR_NOTION_API_KEY";
const databaseId = "YOUR_DATABASE_ID";
const url = `https://api.notion.com/v1/databases/${databaseId}/query`;
const options = {
method: "post",
headers: {
"Authorization": "Bearer " + token,
"Notion-Version": "2022-06-28",
"Content-Type": "application/json"
},
payload: JSON.stringify({
filter: {
property: "進捗",
select: {
equals: "完了"
}
}
})
};
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
const sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
sheet.clear();
sheet.appendRow(["タスク", "日付", "進捗"]);
data.results.forEach(page => {
const props = page.properties;
const task = props["タスク"].title[0]?.plain_text || "";
const date = props["日付"].date?.start || "";
const status = props["進捗"].select?.name || "";
sheet.appendRow([task, date, status]);
});
}
【サンプル④】全項目を転記(タイトルも自動で作成する)
データベースの項目をそのままタイトル名として転記するサンプルです。
/**
* スクリプトプロパティから設定を読み込んでNotionデータを転記
*/
function syncNotionToSheetsWithProperties() {
// --- スクリプトプロパティから設定を取得 ---
const props = PropertiesService.getScriptProperties();
const NOTION_API_KEY = props.getProperty('NOTION_API_KEY');
const DATABASE_ID = props.getProperty('DATABASE_ID');
const SHEET_NAME = props.getProperty('SHEET_NAME') || 'シート1'; // 未設定なら'シート1'
// 設定漏れチェック
if (!NOTION_API_KEY || !DATABASE_ID) {
throw new Error('スクリプトプロパティ "NOTION_API_KEY" または "DATABASE_ID" が設定されていません。');
}
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
if (!sheet) {
throw new Error(`シート名「${SHEET_NAME}」が見つかりません。`);
}
const url = `https://api.notion.com/v1/databases/${DATABASE_ID}/query`;
const options = {
method: 'post',
headers: {
'Authorization': `Bearer ${NOTION_API_KEY}`,
'Notion-Version': '2022-06-28',
'Content-Type': 'application/json'
}
};
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
const results = data.results;
if (results.length === 0) {
console.log("Notion側にデータがありません。");
return;
}
// --- 1行目(ヘッダー)とデータの作成 ---
const headerRow = ['タスク', '日付', '進捗', '備考'];
const values = results.map(page => {
const p = page.properties;
return [
p['タスク']?.title[0]?.plain_text || '',
p['日付']?.date?.start || '',
p['進捗']?.select?.name || p['進捗']?.status?.name || '',
p['備考']?.rich_text[0]?.plain_text || ''
];
});
// --- スプレッドシートへの書き込み ---
sheet.clear();
sheet.getRange(1, 1, 1, headerRow.length).setValues([headerRow]);
if (values.length > 0) {
sheet.getRange(2, 1, values.length, headerRow.length).setValues(values);
}
// 書式設定
sheet.getRange(1, 1, 1, headerRow.length).setFontWeight("bold").setBackground("#f3f3f3");
sheet.setFrozenRows(1); // 1行目を固定
console.log("スクリプトプロパティを使用して同期を完了しました。");
}
【サンプル⑤】条件に合うデータのみ転記(タイトルも自動作成)
④のようにタイトルも自動で作成し、さらに条件によって絞り込むサンプルです。
項目を「タスク」と「進捗」に絞り、進捗のデータは「完了」のみを抽出して転記します。
/**
* Notionから「完了」タスクのみを「シート2」へ転記するスクリプト
*/
function syncCompletedTasksToSheet2() {
// --- スクリプトプロパティから設定を取得 ---
const props = PropertiesService.getScriptProperties();
const NOTION_API_KEY = props.getProperty('NOTION_API_KEY');
const DATABASE_ID = props.getProperty('DATABASE_ID');
const SHEET_NAME = 'シート2'; // 今回は直接「シート2」を指定、またはプロパティで管理
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
if (!sheet) {
throw new Error(`シート名「${SHEET_NAME}」が見つかりません。スプレッドシートにシートを作成してください。`);
}
const url = `https://api.notion.com/v1/databases/${DATABASE_ID}/query`;
const options = {
method: 'post',
headers: {
'Authorization': `Bearer ${NOTION_API_KEY}`,
'Notion-Version': '2022-06-28',
'Content-Type': 'application/json'
}
};
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
const results = data.results;
// --- データの絞り込みと抽出 ---
// 1. 進捗が「完了」のものだけをフィルタリング
// 2. 「タスク」と「進捗」の列だけを抽出
const filteredValues = results
.filter(page => {
const progress = page.properties['進捗']?.select?.name || page.properties['進捗']?.status?.name || '';
return progress === '完了'; // ここで絞り込み条件を指定
})
.map(page => {
const p = page.properties;
return [
p['タスク']?.title[0]?.plain_text || '',
p['進捗']?.select?.name || p['進捗']?.status?.name || ''
];
});
// --- スプレッドシートへの書き込み ---
const headerRow = ['タスク', '進捗'];
sheet.clear();
// ヘッダーの書き込み
sheet.getRange(1, 1, 1, headerRow.length).setValues([headerRow]);
// データがある場合のみ2行目以降に書き込み
if (filteredValues.length > 0) {
sheet.getRange(2, 1, filteredValues.length, headerRow.length).setValues(filteredValues);
console.log(`${filteredValues.length}件の完了済みタスクを同期しました。`);
} else {
console.log("「完了」ステータスのタスクは見つかりませんでした。");
}
// 書式設定
sheet.getRange(1, 1, 1, headerRow.length).setFontWeight("bold").setBackground("#e6f4ea"); // 完了っぽく薄い緑
sheet.setFrozenRows(1);
}
よくあるエラーと対処
① 401エラー
→ APIキーが間違っている
② 空データになる
→ Integrationがデータベースに接続されていない
③ プロパティが取得できない
→ プロパティ名(日本語含む)が一致しているか確認
まとめ
今回は、NotionのデータベースをGASでスプレッドシートに転記する方法を解説しました。
やってみると、意外に簡単にできた!と感動するのではないでしょうか。
ポイントはこの3つです。
- Notion APIの設定が最重要
- GASでAPIを呼び出すだけで連携可能
- フィルターや項目選択で柔軟にカスタマイズできる
この仕組みを応用すれば、
- タスク管理の自動集計
- レポート作成
- ダッシュボード化
など、業務効率化に大きく役立ちます。
ぜひ自分の環境に合わせてカスタマイズしてみてください!
