Tự Động Backup Google Sheets Lên Drive Theo Lịch Với Apps Script
14 tháng 5, 2026
5 phút đọc
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
- Mở Apps Script Editor → Triggers
- Add Trigger → Function:
backupSpreadsheet - Event source: Time-driven
- Time based trigger: Day timer → Midnight to 1am (backup lúc nửa đêm)
- Hoặc chọn Week timer → Every 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
Độ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.