GASでスプレッドシートを
毎日自動でバックアップする方法

大事なスプレッドシートを、makeCopy()による複製と定期トリガーで毎日自動バックアップし、古い世代の自動削除・失敗時のメール通知まで含めて安全に運用する方法を、動くコードで解説します。

|対象: GAS / スプレッドシート / Googleドライブ

Table of Contents

なぜ自動バックアップが必要なのか

Googleスプレッドシートには変更履歴があるため「消えたら終わり」ではありません。 ただし、変更履歴には限界があります。日々の運用では、以下のようなケースで「特定時点の完全なコピー」が欲しくなります。

誤削除・上書き

共有シートを複数人で編集していて、誰かが大量の行を消したり数式を壊したりする

GASの暴走

自作スクリプトのバグで、想定外の範囲にsetValuesしてしまう

月次のスナップショット

月末時点の状態を証跡として丸ごと残しておきたい

外部共有前の保険

取引先に共有する前の状態を、手元に確実に残しておきたい

GAS(Google Apps Script。Googleサービスを自動化できるスクリプト環境)を使えば、こうしたバックアップを人手をかけずに毎日自動化できます。

makeCopyでバックアップする基本コード

バックアップの核はmakeCopy()(ファイルを丸ごと複製するDriveのメソッド)です。元ファイルを日付入りの名前で複製し、指定フォルダに保存します。

function backupSpreadsheet() {
  // バックアップしたいスプレッドシートのID
  const SOURCE_ID = "ここに元ファイルのIDを入れる";
  // バックアップを保存するフォルダのID
  const BACKUP_FOLDER_ID = "ここに保存先フォルダのIDを入れる";

  const sourceFile = DriveApp.getFileById(SOURCE_ID);
  const folder = DriveApp.getFolderById(BACKUP_FOLDER_ID);

  // 例: 売上管理_backup_2026-07-16_0300
  const stamp = Utilities.formatDate(
    new Date(),
    "Asia/Tokyo",
    "yyyy-MM-dd_HHmm"
  );
  const name = sourceFile.getName() + "_backup_" + stamp;

  sourceFile.makeCopy(name, folder);
  Logger.log("バックアップ完了: " + name);
}

Utilities.formatDate()で日付を「Asia/Tokyo」の日本時間に整形しているのがポイントです。これでファイル名に確実に実行日が入り、いつのバックアップかが一目でわかります。

保存先フォルダの指定と自動作成

バックアップは専用フォルダにまとめると管理が楽です。フォルダIDはDriveのURLから取得できます。 毎回IDを調べるのが面倒なら、名前でフォルダを探し、無ければ作る書き方が便利です。

// フォルダIDは、DriveでフォルダのURLを開いたときの
// https://drive.google.com/drive/folders/【この部分】 が該当します。

// フォルダをコードで用意したい場合は、名前で検索して
// 無ければ作る、という書き方も使えます。
function getOrCreateBackupFolder(folderName) {
  const it = DriveApp.getFoldersByName(folderName);
  if (it.hasNext()) {
    return it.next(); // 既にあればそれを使う
  }
  return DriveApp.createFolder(folderName); // 無ければ作成
}

元ファイルとは別のフォルダに保存することで、後述の世代管理(フォルダ内の古いファイルを消す処理)で元ファイルを巻き込む事故を防げます。

古いバックアップを自動削除する世代管理

毎日バックアップを取り続けると、フォルダはコピーで溢れ、Driveの容量も圧迫します。 そこで「直近◯世代だけ残す」ローテーションを入れます。作成日で並べ替え、保持数を超えた古いファイルをゴミ箱へ移動します。

// 古いバックアップを自動削除して世代管理する
// keepCount: 残す世代数(例: 30 なら直近30ファイルを保持)
function cleanupOldBackups(folder, keepCount) {
  const files = [];
  const it = folder.getFiles();
  while (it.hasNext()) {
    const f = it.next();
    files.push({ file: f, date: f.getDateCreated() });
  }

  // 新しい順に並べ替え
  files.sort((a, b) => b.date - a.date);

  // keepCount を超えた古いものをゴミ箱へ
  files.slice(keepCount).forEach((item) => {
    item.file.setTrashed(true);
    Logger.log("削除: " + item.file.getName());
  });
}

setTrashed(true)はゴミ箱に移動するだけで、完全削除ではありません。万一消しすぎても一定期間はゴミ箱から復元できるため、いきなり完全削除するより安全です。

失敗時にメール通知する実運用版

ここまでを1つにまとめ、失敗時のメール通知を加えたのが実運用版です。 トリガー実行はエラーが画面に出ないため、try-catchで囲んで通知する設計にしておくことが重要です。

function dailyBackupJob() {
  const SOURCE_ID = "ここに元ファイルのIDを入れる";
  const BACKUP_FOLDER_ID = "ここに保存先フォルダのIDを入れる";
  const KEEP_COUNT = 30; // 30世代(約1ヶ月分)を保持
  const ADMIN_EMAIL = "admin@example.com";

  try {
    const sourceFile = DriveApp.getFileById(SOURCE_ID);
    const folder = DriveApp.getFolderById(BACKUP_FOLDER_ID);

    const stamp = Utilities.formatDate(
      new Date(),
      "Asia/Tokyo",
      "yyyy-MM-dd_HHmm"
    );
    const name = sourceFile.getName() + "_backup_" + stamp;

    sourceFile.makeCopy(name, folder);
    cleanupOldBackups(folder, KEEP_COUNT);

    Logger.log("バックアップ成功: " + name);
  } catch (e) {
    // トリガー実行の失敗は画面に出ないのでメールで通知する
    MailApp.sendEmail(
      ADMIN_EMAIL,
      "【要確認】スプレッドシートのバックアップに失敗しました",
      "エラー内容:\n" + e.message
    );
    throw e; // 実行ログにも残す
  }
}

バックアップ処理は「動いているつもりで実は数ヶ月止まっていた」が最悪のパターンです。 失敗をメールで拾えるようにしておくだけで、いざという時に守られる確率が大きく変わります。

特定の1シートだけバックアップする

makeCopy()はファイル全体を複製します。特定のシートだけを残したい場合は、新しいスプレッドシートを作り、copyTo()で対象シートだけをコピーします。

// 特定の1シートだけをバックアップしたい場合
function backupSingleSheet() {
  const BACKUP_FOLDER_ID = "ここに保存先フォルダのIDを入れる";
  const ss = SpreadsheetApp.getActive();
  const target = ss.getSheetByName("請求データ");

  // 新しい空のスプレッドシートを作り、対象シートを複製する
  const stamp = Utilities.formatDate(new Date(), "Asia/Tokyo", "yyyy-MM-dd");
  const newSs = SpreadsheetApp.create("請求データ_backup_" + stamp);
  target.copyTo(newSs).setName("請求データ");

  // 自動でできる空の「シート1」を削除
  const blank = newSs.getSheetByName("シート1") || newSs.getSheetByName("Sheet1");
  if (blank) newSs.deleteSheet(blank);

  // 作成したファイルをバックアップ用フォルダへ移動
  const file = DriveApp.getFileById(newSs.getId());
  DriveApp.getFolderById(BACKUP_FOLDER_ID).addFile(file);
  DriveApp.getRootFolder().removeFile(file);
}

個人情報を含むシートだけを分離して保管したい、といった要件で役立ちます。 なお copyTo()は値だけでなく数式や書式もそのままコピーされます。

トリガーで毎日自動実行する

最後に、毎日決まった時刻に自動でバックアップを走らせます。時間主導トリガー(時刻をきっかけに関数を実行する仕組み)を使います。 利用者の少ない深夜帯に実行するのがおすすめです。

// 毎日午前3時にバックアップを実行するトリガーを作成
function createDailyBackupTrigger() {
  // 二重登録を防ぐため、既存トリガーを一度削除
  ScriptApp.getProjectTriggers().forEach((t) => {
    if (t.getHandlerFunction() === "dailyBackupJob") {
      ScriptApp.deleteTrigger(t);
    }
  });

  ScriptApp.newTrigger("dailyBackupJob")
    .timeBased()
    .everyDays(1)
    .atHour(3) // 午前3〜4時の間に実行
    .create();
}

この関数は一度だけ手動で実行すればトリガーが登録されます。冒頭で既存の同名トリガーを削除しているため、何度実行してもトリガーが二重に増えません。 毎週にしたい場合はeveryWeeks(1).onWeekDay(ScriptApp.WeekDay.MONDAY)に差し替えます。

実務での注意点

1. Driveの容量とオーナーを意識する

バックアップはコピーの数だけ容量を消費します。ファイルが大きい場合は保持世代数を絞るか、頻度を毎週に落とします。作成されたコピーは、スクリプトを実行したアカウントの所有物になる点にも注意してください。

2. 大きいファイルは実行時間に注意

巨大なスプレッドシートの複製には時間がかかり、GASの実行時間制限(1回あたり6分)に近づくことがあります。複数ファイルをまとめてバックアップする場合は、対象を分けて別トリガーにすると安定します。

3. 初回実行時に権限承認が必要

DriveやGmailを操作するため、初めて実行する際にGoogleの権限承認画面が表示されます。承認しておかないとトリガーが動きません。設定後は必ず一度手動実行して、承認とバックアップ生成を確認しておきましょう。

まとめ

GASでのスプレッドシート自動バックアップは、makeCopyによる複製・日付入りファイル名・専用フォルダへの保存・世代管理・失敗時のメール通知・定期トリガーの6点を押さえれば、実務レベルで安全に運用できます。 「消えてから後悔する」前に、深夜に静かに走り続ける仕組みを一度作っておけば、大切なデータを人手をかけずに守り続けられます。

よくある質問

DriveApp.getFileById(id).makeCopy(名前, フォルダ) を使うのが最短です。元のスプレッドシートを丸ごと複製し、日付を入れたファイル名でバックアップ用フォルダに保存します。数行のコードで完結し、時間主導トリガーと組み合わせれば毎日自動で実行できます。

世代管理(ローテーション)を入れます。バックアップ用フォルダ内のファイルを作成日順に並べ、指定した保持件数(例: 30世代)を超えた古いものを自動でゴミ箱に移動します。この記事のcleanupOldBackups関数がそのまま使えます。

できます。makeCopyはファイル全体を複製しますが、1枚のシートだけ残したい場合は複製後に不要なシートを削除するか、copyToで対象シートを新規スプレッドシートにコピーする方法があります。記事内でコード例を紹介しています。

try-catchで囲み、失敗したらMailApp.sendEmailで管理者に通知する設計にします。トリガー実行はエラーが出ても画面に表示されないため、通知を入れておかないと「バックアップが止まっていたことに後で気づく」事故につながります。

トリガーの設定を変えるだけです。everyDays(1)を毎日、everyWeeks(1).onWeekDay(ScriptApp.WeekDay.MONDAY)で毎週月曜、onMonthDay(1)で毎月1日に実行できます。頻度に合わせて保持世代数も調整するとよいでしょう。

GAS開発・業務Webシステムを
相談する。

自動バックアップ以外にも、フォーム連携・帳票出力・Gmail自動化など、日々の業務を自動化するGAS開発をご相談いただけます。

GAS開発の対応範囲を見る