月初の貼り付け地獄 — 部署別ファイルの統合をワンクリックで
月初の貼り付け地獄
月初になると、各部署から「今月の集計です」とスプレッドシートが届きます。営業1課、2課、3課、それぞれ別のファイル。
あなたの仕事は、これを1枚にまとめて全社の集計表にすること。
ファイルを1つずつ開いて、データ範囲を選択して、コピー、統合先に切り替えて、貼り付け、次のファイル……。
3部署ならまだしも、5部署、10部署とあると、月初の半日が消えます。
しかも、貼り付け位置が1行ずれるだけで、後の集計が全部おかしくなります。
指定したフォルダ内のスプレッドシートをワンクリックで統合
それなら、GASで自動化しましょ!
指定したフォルダに各部署からのファイルを入れておけば、ボタン1つでスプレッドシートをすべて読み込み、1枚のシートに統合してくれます。
「元ファイル名」も自動で付くので、後からどの行がどの部署由来か一目でわかります。
コード.gs
// コード.gs
/**
* 指定フォルダ内の全スプレッドシートを1枚に縦結合する
* 各ファイルの最初のシートを読み込み、最頻のヘッダーを基準にして揃うものだけ統合
*/
const SETTINGS_SHEET = '設定';
const RESULT_SHEET = '統合結果';
const SOURCE_COL_NAME = '元ファイル名';
function mergeFiles() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ui = SpreadsheetApp.getUi();
const settings = ss.getSheetByName(SETTINGS_SHEET);
const folderId = settings ? String(settings.getRange('B1').getValue() || '').trim() : '';
if (!folderId) {
ui.alert('「' + SETTINGS_SHEET + '」シートのB1にフォルダIDを入力してください。');
return;
}
let folder;
try {
folder = DriveApp.getFolderById(folderId);
} catch (e) {
ui.alert('フォルダが見つかりません。IDを確認してください。');
return;
}
// 1パス目: 全ファイルを読み込んで保持
const files = folder.getFilesByType(MimeType.GOOGLE_SHEETS);
const allFiles = [];
while (files.hasNext()) {
const file = files.next();
if (file.getId() === ss.getId()) continue;
const src = SpreadsheetApp.openById(file.getId());
const values = src.getSheets()[0].getDataRange().getValues();
if (values.length < 2) continue;
allFiles.push({ name: file.getName(), header: values[0], rows: values.slice(1) });
}
if (allFiles.length === 0) {
ui.alert('統合できるファイルが見つかりませんでした。');
return;
}
// ファイル名の昇順でソート(Driveの返却順は不定のため)
allFiles.sort(function(a, b) {
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
});
// 最も多く出現するヘッダーを基準にする(少数派のファイルがスキップ対象)
const counts = {};
allFiles.forEach(function(f) {
const key = f.header.join('\t');
counts[key] = (counts[key] || 0) + 1;
});
let baseKey = null;
let baseCount = 0;
Object.keys(counts).forEach(function(k) {
if (counts[k] > baseCount) {
baseCount = counts[k];
baseKey = k;
}
});
const baseHeader = baseKey.split('\t');
// 基準ヘッダーと一致するファイルだけ統合
const merged = [];
const skipped = [];
let fileCount = 0;
allFiles.forEach(function(f) {
if (f.header.join('\t') === baseKey) {
f.rows.forEach(function(row) {
merged.push([f.name].concat(row));
});
fileCount++;
} else {
skipped.push(f.name);
}
});
const outHeader = [SOURCE_COL_NAME].concat(baseHeader);
const resultSheet = ss.getSheetByName(RESULT_SHEET) || ss.insertSheet(RESULT_SHEET);
resultSheet.clear();
resultSheet.getRange(1, 1, 1, outHeader.length).setValues([outHeader]);
if (merged.length > 0) {
resultSheet.getRange(2, 1, merged.length, outHeader.length).setValues(merged);
}
resultSheet.getRange(1, 1, 1, outHeader.length)
.setBackground('#f3f3f3')
.setFontWeight('bold')
.setHorizontalAlignment('center');
SpreadsheetApp.flush();
let msg = '統合完了。\n\n' +
'ファイル数: ' + fileCount + '\n' +
'データ行数: ' + merged.length;
if (skipped.length > 0) {
msg += '\n\nヘッダーが多数派と異なるためスキップ:\n- ' + skipped.join('\n- ');
}
ui.alert(msg);
}
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('自動ボタン')
.addItem('フォルダ内ファイルを統合', 'mergeFiles')
.addToUi();
}使い方
① 統合先のスプレッドシートを新規作成
統合した結果を書き出すための「マスタ」スプレッドシートを1つ用意します。
② 拡張機能 → Apps Script にコードを貼り付けて保存
③ Driveに統合元ファイルを集めるフォルダを作る
例: `統合元_サンプル` というフォルダを作り、そこに各部署のファイル(営業1課、2課、3課……)を入れておきます。
④ 統合先スプレッドシートに「設定」という名前のシートを用意し、B1セルにフォルダIDを入力
フォルダIDは、DriveでフォルダURLを開いた時の `https://drive.google.com/drive/folders/【ここの部分】` です。
⑤ スプレッドシートをリロード → 「自動ボタン」→「フォルダ内ファイルを統合」を実行
初めて実行すると承認ダイアログが表示されます。手順は第1回と同じです。
実行すると、フォルダ内の全スプレッドシートが読み込まれ、「統合結果」シートに縦結合された状態で書き出されます。
処理したファイル数とデータ行数がポップアップで表示されます。
ワンポイント・レッスン
DriveApp.getFolderById() — フォルダの中身をGASから操作する
コードの中にあるこの3行が、今回の統合処理の心臓部です。
const folder = DriveApp.getFolderById(folderId);
const files = folder.getFilesByType(MimeType.GOOGLE_SHEETS);
while (files.hasNext()) {
const file = files.next();
// ...
}GASは Google Drive を直接操作できます。スプレッドシートだけでなく、フォルダの中身を一覧したり、ファイルを開いたり、移動したりが可能です。
-
`DriveApp.getFolderById(id)` — フォルダIDを指定してフォルダを取得する
-
`folder.getFilesByType(MimeType.GOOGLE_SHEETS)` — フォルダ内のスプレッドシートだけを取り出す。Excelやドキュメントは自動で除外される
-
`files.hasNext()` / `files.next()` — ファイル一覧は配列ではなく「イテレータ」。`hasNext()` で次があるか確認し、`next()` で1つずつ取り出すパターンで回す
DriveApp ← Drive全体への入口
└ getFolderById('1AbC...') ← フォルダを指定
└ getFilesByType(GOOGLE_SHEETS) ← スプレッドシートだけ取り出す
├ 営業1課 ← files.next()
├ 営業2課 ← files.next()
└ 営業3課 ← files.next()スプレッドシートの中だけで完結する処理(第1〜3回)と違い、`DriveApp` を使うと「フォルダの中の全ファイル」を相手にできるようになります。GASならではの強みです。
まとめ
フォルダにファイルを入れておくだけで、ボタン1つで全ファイルを統合。「元ファイル名」が自動で付くので、どの行がどの部署由来か一目瞭然。
月初の貼り付け作業がまるごと消えます。
全ファイルが同じヘッダーとは限らない

部署ごとにシートのヘッダーが一致していないことは珍しくありません。
営業一課は「日付」列から始まるが、営業二課は「担当者」列から始まる。
営業一課は「商品名」「数」だが、営業二課は「商品」「数量」。
営業二課には「備考」があるが、営業一課にはない…
コード.gsはヘッダーの一致が前提で、不一致のファイルはスキップしましたが、拡張コードでは、これらのヘッダー揺れにも対応させましょう。
拡張コードで出来ること
-
ヘッダー揺れ対応統合 — 全ファイルのヘッダーを和集合して列を作り、各行を列名ベースで再配置。列順がバラバラでも、追加列があっても、1枚に統合できる
この記事の続きはnoteで公開しています。
