「複数のスプレッドシートの売上管理データや分析シートを定期的に自動でCSVでダウンロードしたい」 「複数のスプレッドシートを合体させて一気にAIに分析してもらいたい」
そんなお悩み、ありませんか?
この記事では、Google Apps Script(GAS)を使って、以下の2つの面倒な作業を「ワンクリック」で完了させる方法を解説します。
プログラミング初心者の方でも大丈夫!今回は、話題の生成AIにGASコードを作成してもらう方法も交えながら、誰でも簡単に実装できるように解説していきます。
※私はGemini PROを利用して作成しております。
関連記事
この結合分析データが役立つサイト分析入門はこちら
この記事はこんな方におすすめ
- 【一括DL】 フォルダ内の複数ファイルを、そのまま個別のCSVとして一気にダウンロードしたい方
- 【結合DL】 複数ファイルの中身を「合体」させ、1つのCSVにまとめてダウンロードしたい方
- GASを使った業務効率化に興味がある方
【配布】コピーしてすぐに使えます
難しい設定は不要です。以下のリンクからスプレッドシートをコピーすれば、すぐに自動化ツールが手に入ります。
GASコードのみ利用する
// メニューを追加
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('CSVエクスポート')
.addItem('1. 【結合】CSVをDL', 'runCsvExport') // 結合用
.addItem('2. 【個別】CSV一括DL', 'runBulkCsvExport') // 個別用
.addToUi();
}
/* ==============================================
機能1:指定したシートをすべて結合して1つのCSVにする
(設定シート名:「【結合】CSVをDL」)
============================================== */
function runCsvExport() {
const ui = SpreadsheetApp.getUi();
// ▼変更点:新しいシート名「【結合】CSVをDL」を指定
const configSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('【結合】CSVをDL');
if (!configSheet) {
ui.alert('エラー', '「【結合】CSVをDL」シートが見つかりません。シート名を確認してください。', ui.ButtonSet.OK);
return;
}
const parentFolderUrl = configSheet.getRange('D2').getValue();
let fileNamePrefix = configSheet.getRange('D4').getValue() || 'combined_export';
if (!parentFolderUrl) {
ui.alert('エラー', 'D2セルに保存先URLがありません。', ui.ButtonSet.OK);
return;
}
let parentFolderId = parentFolderUrl;
if (parentFolderUrl.includes("drive.google.com")) {
const parts = parentFolderUrl.split("/");
parentFolderId = parts[parts.length - 1].split("?")[0];
}
const range = configSheet.getRange('A2:B' + configSheet.getLastRow());
const values = range.getValues().filter(row => row[0] && row[1]);
if (values.length === 0) {
ui.alert('情報', '処理対象がありません。A列・B列を確認してください。', ui.ButtonSet.OK);
return;
}
let combinedData = [];
let headerSkipped = false;
try {
const parentFolder = DriveApp.getFolderById(parentFolderId);
for (const row of values) {
const url = row[0];
const sheetName = row[1];
try {
const targetSpreadsheet = SpreadsheetApp.openByUrl(url);
const targetSheet = targetSpreadsheet.getSheetByName(sheetName);
if (!targetSheet) continue;
const data = targetSheet.getDataRange().getValues();
if (data.length === 0) continue;
if (!headerSkipped) {
combinedData.push(...data);
headerSkipped = true;
} else {
combinedData.push(...data.slice(1));
}
} catch (e) {
Logger.log(`エラー: ${url} - ${e.message}`);
}
}
if (combinedData.length === 0) {
ui.alert('情報', 'データが取得できませんでした。', ui.ButtonSet.OK);
return;
}
const csvString = convertArrayToCsvString(combinedData);
// 日付フォルダ準備
const todayStr = Utilities.formatDate(new Date(), 'JST', 'yyyyMMdd');
const folderIterator = parentFolder.getFoldersByName(todayStr);
let targetFolder = folderIterator.hasNext() ? folderIterator.next() : parentFolder.createFolder(todayStr);
// ファイル保存
const timeStr = Utilities.formatDate(new Date(), 'JST', 'yyyyMMdd_HHmmss');
const fileName = `${fileNamePrefix}_${timeStr}.csv`;
const blob = Utilities.newBlob(Utilities.newBlob(csvString, MimeType.CSV, fileName).getBytes(), MimeType.CSV, fileName);
const file = targetFolder.createFile(blob);
ui.alert('完了', `結合CSVを作成しました。\n${file.getUrl()}`, ui.ButtonSet.OK);
} catch (err) {
ui.alert('エラー', err.message, ui.ButtonSet.OK);
}
}
/* ==============================================
機能2:指定したシートをバラバラのまま一括DLする
(設定シート名:「【個別】CSV一括DL」)
============================================== */
function runBulkCsvExport() {
const ui = SpreadsheetApp.getUi();
const configSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('【個別】CSV一括DL');
if (!configSheet) {
ui.alert('エラー', '「【個別】CSV一括DL」シートが見つかりません。シート名を確認してください。', ui.ButtonSet.OK);
return;
}
const parentFolderUrl = configSheet.getRange('D2').getValue();
let fileNamePrefix = configSheet.getRange('D4').getValue();
fileNamePrefix = fileNamePrefix ? fileNamePrefix + '_' : '';
if (!parentFolderUrl) {
ui.alert('エラー', 'D2セルに保存先URLがありません。', ui.ButtonSet.OK);
return;
}
let parentFolderId = parentFolderUrl;
if (parentFolderUrl.includes("drive.google.com")) {
const parts = parentFolderUrl.split("/");
parentFolderId = parts[parts.length - 1].split("?")[0];
}
const range = configSheet.getRange('A2:B' + configSheet.getLastRow());
const values = range.getValues().filter(row => row[0] && row[1]);
if (values.length === 0) {
ui.alert('情報', '処理対象がありません。A列・B列を確認してください。', ui.ButtonSet.OK);
return;
}
let successCount = 0;
let errorLog = [];
try {
const parentFolder = DriveApp.getFolderById(parentFolderId);
// 日付フォルダ準備
const todayStr = Utilities.formatDate(new Date(), 'JST', 'yyyyMMdd');
const folderIterator = parentFolder.getFoldersByName(todayStr);
let targetFolder = folderIterator.hasNext() ? folderIterator.next() : parentFolder.createFolder(todayStr);
for (const row of values) {
const url = row[0];
const sheetName = row[1];
try {
const targetSpreadsheet = SpreadsheetApp.openByUrl(url);
const targetSheet = targetSpreadsheet.getSheetByName(sheetName);
if (!targetSheet) {
errorLog.push(`シートなし: ${sheetName}`);
continue;
}
const data = targetSheet.getDataRange().getValues();
// Utilities.gsにある関数を呼び出す
const csvString = convertArrayToCsvString(data);
// ▼変更点:ファイル名の末尾に日時を追加
const timeStr = Utilities.formatDate(new Date(), 'JST', 'yyyyMMdd_HHmmss');
const fileName = `${fileNamePrefix}${sheetName}_${timeStr}.csv`;
const blob = Utilities.newBlob(Utilities.newBlob(csvString, MimeType.CSV, fileName).getBytes(), MimeType.CSV, fileName);
targetFolder.createFile(blob);
successCount++;
} catch (e) {
errorLog.push(`エラー(${sheetName}): ${e.message}`);
}
}
let message = `個別保存が完了しました。\n成功: ${successCount} 件\n保存先: ${targetFolder.getName()}`;
if (errorLog.length > 0) message += `\n\n【失敗】\n${errorLog.join('\n')}`;
ui.alert('完了', message, ui.ButtonSet.OK);
} catch (err) {
ui.alert('エラー', err.message, ui.ButtonSet.OK);
}
}
// 共通:CSV変換関数
function convertArrayToCsvString(data) {
let csv = '\uFEFF';
data.forEach(row => {
let rowArray = [];
row.forEach(cell => {
let cellString = String(cell);
if (cellString.includes(',') || cellString.includes('"') || cellString.includes('\n')) {
cellString = '"' + cellString.replace(/"/g, '""') + '"';
}
rowArray.push(cellString);
});
csv += rowArray.join(',') + '\r\n';
});
return csv;
}
そもそもGAS(Google Apps Script)って何?
GASは、Googleが開発したプログラミング言語です。「Googleの様々なサービス(Gmail、スプレッドシート、ドキュメントなど)を自動化・連携が得意なプログラムのことです。GASを生成AIに書いてもらうことができる現在は、アイディアさへあればプログラミングに詳しくなくても、様々な自動化を自分で作ることができます!
もちろんプログラミング知識があればもっと複雑なこともデバックする作業も大幅に削減できるので、これを気にプログラミングの基礎も学ぶこともおすすめします。
GASのベースとなっているJavaScriptは情報も多く、プログラミング初心者でも学びやすい言語です。
関連記事
「AIがコードを書く時代、プログラミングは不要?」そう考えていませんか?実は、AIを真に使いこなすにはプログラミングの基礎知識が不可欠です。この記事では、プログラミングに何度も挫折した筆者が、JavaScriptの基礎を固め、GASで自在に業務を自動化できるようになった具体的な4ステップの学習法を全公開します。
【結合|一括】シートをCSVでダウンロード 使い方マニュアル
このスプレッドシートをコピーして使用する際は、最初に以下の設定を行ってください。
1. 最初にやること(重要)

シートをコピーした直後は、保存先の設定が空欄(またはコピー元のまま)になっています。自分のGoogleドライブに保存できるように設定します。
- 保存先フォルダの作成
- Googleドライブに、CSVを保存するための「新しいフォルダ」を作成してください。
- 作成したフォルダのURLをコピーします。
- 設定シートへの貼り付け
- 以下の2つのシートを開き、D2セルに先ほどコピーしたフォルダURLを貼り付けます。
- シート名:
【結合】CSVをDL - シート名:
【個別】CSV一括DL
- シート名:
- 以下の2つのシートを開き、D2セルに先ほどコピーしたフォルダURLを貼り付けます。
2. データの指定方法
処理したい内容に合わせて、各設定シートの A列・B列 を入力します。
- A列:スプレッドシートURL
- 読み込みたいファイルのURLを貼り付けます。
- B列:シート名
- そのファイルの読み込みたい「タブの名称」を正確に入力します。
- D4セル:ファイル名接頭辞(任意)
- ファイル名の先頭につける文字を指定できます。(例:「売上データ」など)
3. ツールの実行手順

- スプレッドシートのメニューバーにある 「CSVエクスポート」 をクリックします。
- 実行したい機能を選択します。
- 【結合】CSVをDL: データを縦につなげて1つのファイルにします。
- 【個別】CSV一括DL: バラバラのまま一括保存します。
初回実行時の注意(承認画面)
初めてスクリプトを実行すると「承認が必要です(このアプリはGoogleで確認されていません)」という画面が表示されます。これは自作ツールを使う際の標準的な仕様です。以下の手順で進んでください。
- 「権限を確認」 をクリック
- 自分のGoogleアカウントを選択
- 警告画面が出たら、左下の 「詳細」 をクリック
- 展開された下部の 「(安全ではないページ)に移動」 をクリック
- 「許可」 をクリック
4. 出力結果について
D2セルで指定したフォルダの中に 「実行日のフォルダ(例: 20251125)」 が自動作成され、その中にCSVファイルが保存されます。
ファイル名には自動で日時(秒まで)が付与されるため、何度実行しても上書きされる心配はありません。
【メイキング】生成AI×GASで完全自動化ができるまで
Geminiを使って、GASとスプレッドシートのテンプレートを作っていく過程をレポートいたします。chatGPTなど他の生成AIツールでも代用可能ですが、Googleスプレッドシートやドライブと互換性があるのはやっぱりGoogle産のGeminiが一番簡単に作成できるので私はGeminiをお勧めします。
ふわっとした指示からスタート
最初は具体的なイメージが固まっていなかったので、ざっくりとした要望を投げました。人間の部下にやると怒られそうですね。(笑)
スプレッドシート指定してまとめてCSVでダウンロードできるシート作りたい
これだけで、Geminiは基本的なコードを作成してくれます。

Googleドライブに保存してくれるみたいですね。最近ではGoogleドライブのツール自体にGeminiが搭載されているのでドライブにアップするだけで、データ分析や保存データの管理・要約が一気に容易になりそうで楽しみです。


スプレッドシートはこのように作ってねという指示が来てるのでその通りシートを作成します。


GASの設定をしてねと来ていたので、スプレッドシートの【拡張機能】→【Apps Script】を開き設定します。

コードが問題なく実行することを確認したら、スプレッドシートに戻るとメニューに【CSVエクスポート】が新しく加わってい他ので、こちらから実行すると無事Googleドライブにデータが保存されました。

具体的な要望を追加
動くものはできましたが、「保存先が選べない」という問題に気づきました。そこで追加の相談をします。
このコードをどこのファイルに保存するか指定したい
保存先のドライブURLはシートで指定したい


「保存先のドライブURLはシートで指定したい」と指示したので、D2にドライブのURLを指定するだけでその場所にデータほ保存できるようになりました。
さらに、定期的にダウンロードしたときに、どのデータがいつのデータのかわかり易くなるように次のような相談をしました。
ダウンロードしたときに新規の今日の日付が書いたフォルダ作って、その中に保存して欲しい

ファイル名もシートで指定できるようにしたい
任意名(シートで指定)_年月日時分秒




完成!
これで、スプレッドシートから指定した複数のシートをCSVエクスポートすると結合されたCSVデータが指定のGoogleドライブの保存場所に【今日の日付】フォルダを作って、指定した【任意名(シートで指定)_年月日時分秒】でダウンロードできる仕組みができました。
別のパターンの作成
「結合して保存」ができたので、「バラバラに保存」も欲しくなりました。
同じ感じのシートのテンプレートで別のGAS作って欲しい
指定したバラバラのシートを結合しないで、指定した保存先に、フォルダを作りその中にCSVを一括ダウンロードできるもの


先ほどのシートを複製して、シート名を「【個別】CSV一括DL」に変更、新たに作成してもらったGASを設定して完成です。

スプレッドシートのメニュー画面から、結合or個別選べるようになり、これで今回の2つの機能が完成しました!
まとめ:プログラミングは「AI」に任せる時代へ
これまでプログラミング知識が必要だった業務効率化も、生成AIを使えば、アイデア一つで実現できるようになりました。
- コピペで時短: まずは今回のシートを使って、面倒なCSV作業から解放されましょう。
- 次は自分で: 「ここを少し変えたいな」と思ったら、ぜひGeminiに相談してみてください。
GASのベースとなっているJavaScriptは情報も多く、初心者でも学びやすい言語です。AIを使いこなすための基礎知識として、少しずつ学んでみるのもおすすめですよ。

