Google Apps Script

Tự Động Backup Google Sheets Lên Drive Theo Lịch Với Apps Script

Tuân HoangTuân Hoang
14 tháng 5, 2026
5 phút đọc
Ảnh minh họa bài viết: Tự Động Backup Google Sheets Lên Drive Theo Lịch Với Apps Script

Tại Sao Cần Tự Động Backup Google Sheets?

Google Sheets có lịch sử chỉnh sửa (Version History), nhưng không có tính năng backup tự động sang file mới. Khi ai đó vô tình xóa dữ liệu lớn và Save, hoặc script chạy lỗi ghi đè dữ liệu — bạn cần backup riêng để khôi phục nhanh.

Script dưới đây tự động tạo bản sao file Google Sheets mỗi ngày/tuần, lưu vào folder theo năm/tháng, và gửi email xác nhận sau khi backup xong.

Script Backup Cơ Bản

function backupSpreadsheet() {
  try {
    const ss = SpreadsheetApp.getActiveSpreadsheet();
    const ssId = ss.getId();
    const ssName = ss.getName();

    // Tạo tên file backup với timestamp
    const now = new Date();
    const dateStr = Utilities.formatDate(now, 'Asia/Ho_Chi_Minh', 'yyyy-MM-dd_HH-mm');
    const backupName = ssName + '_backup_' + dateStr;

    // Lấy hoặc tạo folder backup
    const backupFolder = getOrCreateBackupFolder();

    // Tạo bản sao
    const originalFile = DriveApp.getFileById(ssId);
    const backupFile = originalFile.makeCopy(backupName, backupFolder);

    console.log('Backup created: ' + backupFile.getName() + ' | ID: ' + backupFile.getId());

    // Gửi email xác nhận
    sendBackupNotification(backupFile, backupFolder);

    // Dọn backup cũ hơn 30 ngày
    cleanOldBackups(backupFolder, 30);

  } catch (error) {
    console.error('Backup failed: ' + error.toString());
    MailApp.sendEmail(
      Session.getActiveUser().getEmail(),
      '[ALERT] Backup thất bại - ' + new Date().toLocaleDateString('vi-VN'),
      'Lỗi: ' + error.toString()
    );
    throw error; // Re-throw để Apps Script ghi log lỗi
  }
}

Tạo Folder Theo Cấu Trúc Năm/Tháng

function getOrCreateBackupFolder() {
  const now = new Date();
  const year = now.getFullYear().toString();
  const month = Utilities.formatDate(now, 'Asia/Ho_Chi_Minh', 'MM-yyyy');

  // Folder gốc: "Backups"
  let rootFolder;
  const rootFolders = DriveApp.getFoldersByName('Backups_SheetStore');
  if (rootFolders.hasNext()) {
    rootFolder = rootFolders.next();
  } else {
    rootFolder = DriveApp.createFolder('Backups_SheetStore');
  }

  // Sub-folder theo năm
  let yearFolder;
  const yearFolders = rootFolder.getFoldersByName(year);
  if (yearFolders.hasNext()) {
    yearFolder = yearFolders.next();
  } else {
    yearFolder = rootFolder.createFolder(year);
  }

  // Sub-folder theo tháng
  let monthFolder;
  const monthFolders = yearFolder.getFoldersByName(month);
  if (monthFolders.hasNext()) {
    monthFolder = monthFolders.next();
  } else {
    monthFolder = yearFolder.createFolder(month);
  }

  return monthFolder;
}

Xóa Backup Cũ Tự Động

function cleanOldBackups(folder, daysToKeep) {
  const cutoffDate = new Date();
  cutoffDate.setDate(cutoffDate.getDate() - daysToKeep);

  const files = folder.getFiles();
  let deletedCount = 0;

  while (files.hasNext()) {
    const file = files.next();
    const createdDate = file.getDateCreated();

    if (createdDate < cutoffDate) {
      file.setTrashed(true); // Chuyển vào Trash thay vì xóa vĩnh viễn
      deletedCount++;
      console.log('Deleted old backup: ' + file.getName());
    }
  }

  console.log('Cleaned ' + deletedCount + ' old backup(s)');
}

Gửi Email Xác Nhận Sau Backup

function sendBackupNotification(backupFile, backupFolder) {
  const fileSize = backupFile.getSize();
  const fileSizeKB = (fileSize / 1024).toFixed(1);

  const emailBody = [
    '<h2>Backup hoàn thành ✓</h2>',
    '<table border="1" cellpadding="8" style="border-collapse:collapse">',
    '<tr><td><strong>File</strong></td><td>' + backupFile.getName() + '</td></tr>',
    '<tr><td><strong>Kích thước</strong></td><td>' + fileSizeKB + ' KB</td></tr>',
    '<tr><td><strong>Thư mục</strong></td><td>' + backupFolder.getName() + '</td></tr>',
    '<tr><td><strong>Thời gian</strong></td><td>' + new Date().toLocaleString('vi-VN') + '</td></tr>',
    '</table>',
    '<p><a href="' + backupFile.getUrl() + '">Mở file backup</a></p>',
  ].join('');

  MailApp.sendEmail({
    to: Session.getActiveUser().getEmail(),
    subject: 'Backup thành công - ' + new Date().toLocaleDateString('vi-VN'),
    htmlBody: emailBody
  });
}

Cài Đặt Time-Based Trigger

  1. Mở Apps Script Editor → Triggers
  2. Add Trigger → Function: backupSpreadsheet
  3. Event source: Time-driven
  4. Time based trigger: Day timerMidnight to 1am (backup lúc nửa đêm)
  5. Hoặc chọn Week timerEvery Monday, 7am–8am (backup hàng tuần)

Backup Sang Định Dạng Excel (.xlsx)

function backupAsExcel() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const ssId = ss.getId();

  // Export dưới dạng Excel
  const exportUrl = 'https://docs.google.com/spreadsheets/d/' + ssId + '/export?format=xlsx';
  const token = ScriptApp.getOAuthToken();

  const response = UrlFetchApp.fetch(exportUrl, {
    headers: { 'Authorization': 'Bearer ' + token },
    muteHttpExceptions: true
  });

  if (response.getResponseCode() !== 200) {
    throw new Error('Export failed: ' + response.getContentText());
  }

  const blob = response.getBlob().setName(ss.getName() + '_' + Utilities.formatDate(new Date(), 'Asia/Ho_Chi_Minh', 'yyyy-MM-dd') + '.xlsx');

  // Lưu vào Drive
  const folder = getOrCreateBackupFolder();
  const savedFile = folder.createFile(blob);

  console.log('Excel backup saved: ' + savedFile.getName());
  return savedFile;
}

Best Practices

  • Backup trước khi chạy script lớn: Gọi backupSpreadsheet() đầu mỗi script xử lý dữ liệu quan trọng.
  • Kiểm tra Drive quota: Google Drive giới hạn 15GB miễn phí. Backup file lớn sẽ tốn nhiều dung lượng.
  • Test trigger đầu tiên: Chạy tay hàm backupSpreadsheet() trước khi cài trigger để đảm bảo không có lỗi.
  • Kết hợp với email alert: Nếu backup thất bại, nhận email ngay để xử lý kịp thời.

Chia sẻ bài viết:

Tuân Hoang

Tuân Hoang

Đội ngũ SheetStore

Google SheetsGoogle Apps ScriptCRMAutomationPhần mềm quản lý doanh nghiệp

Google Workspace Certified, 5+ years experience

Bạn thấy bài viết hữu ích?

Đăng ký nhận thông báo khi có bài viết mới.

Nhận thông báo khi có bài viết mới. Không spam, hứa luôn! 😊

Bình luận (0)

Vui lòng đăng nhập để tham gia thảo luận