Google Apps Script: Tự Động Tạo Báo Cáo PDF & Gửi Email
Tại Sao Cần Tự Động Hóa Báo Cáo?
Tạo báo cáo thủ công tốn 30–60 phút mỗi tuần. Với Apps Script, quy trình này chạy tự động mỗi thứ Hai lúc 8h sáng, gửi báo cáo đẹp đến đúng người mà không cần can thiệp nào. Đây là một trong những use case phổ biến và có giá trị nhất của Google Apps Script.
Phương Pháp 1: Export Sheet Thành PDF
function exportSheetAsPDF() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('BaoCaoTuan');
const ssId = ss.getId();
const sheetId = sheet.getSheetId();
// URL export PDF của Google Sheets
const pdfUrl = `https://docs.google.com/spreadsheets/d/${ssId}/export`
+ `?format=pdf`
+ `&size=A4`
+ `&portrait=true`
+ `&fitw=true` // Fit to width
+ `&sheetnames=false`
+ `&printtitle=false`
+ `&pagenumbers=false`
+ `&gridlines=false`
+ `&fzr=false` // Không đóng băng hàng/cột
+ `&gid=${sheetId}`; // Chỉ export sheet này
const token = ScriptApp.getOAuthToken();
const response = UrlFetchApp.fetch(pdfUrl, {
headers: { Authorization: `Bearer ${token}` }
});
const pdfBlob = response.getBlob().setName(
`BaoCao_Tuan_${Utilities.formatDate(new Date(), 'Asia/Ho_Chi_Minh', 'dd-MM-yyyy')}.pdf`
);
return pdfBlob;
}
Phương Pháp 2: Tạo PDF Từ Google Docs Template
function createReportFromTemplate() {
const templateId = 'YOUR_GOOGLE_DOC_TEMPLATE_ID';
const template = DriveApp.getFileById(templateId);
// Copy template
const reportName = `Báo Cáo Tuần ${getWeekNumber()} - ${new Date().getFullYear()}`;
const copy = template.makeCopy(reportName);
const doc = DocumentApp.openById(copy.getId());
const body = doc.getBody();
// Lấy dữ liệu từ Google Sheets
const data = getReportData();
// Thay thế placeholders trong template
body.replaceText('{{TUAN}}', getWeekNumber().toString());
body.replaceText('{{DOANH_THU}}', data.doanhThu.toLocaleString() + 'đ');
body.replaceText('{{SO_DON}}', data.soDon.toString());
body.replaceText('{{KHACH_MOI}}', data.khachMoi.toString());
body.replaceText('{{TY_LE_CHUYEN_DOI}}', (data.tyLeChuyenDoi * 100).toFixed(1) + '%');
doc.saveAndClose();
// Export sang PDF
const pdfBlob = copy.getAs('application/pdf');
pdfBlob.setName(reportName + '.pdf');
// Xóa bản copy Docs sau khi tạo PDF
copy.setTrashed(true);
return pdfBlob;
}
Gửi Email Kèm Báo Cáo PDF
function sendWeeklyReport() {
const pdfBlob = exportSheetAsPDF();
const weekNum = getWeekNumber();
const year = new Date().getFullYear();
const recipients = [
'giamdoc@company.com',
'truongphong@company.com',
'ketoan@company.com'
];
const data = getReportData();
const htmlBody = `
Báo Cáo Tuần ${weekNum}/${year}
Chỉ số Tuần này Tuần trước Thay đổi
Doanh thu
${data.doanhThu.toLocaleString()}đ
${data.doanhThuTruoc.toLocaleString()}đ
${data.doanhThu > data.doanhThuTruoc ? '↑' : '↓'} ${Math.abs((data.doanhThu/data.doanhThuTruoc-1)*100).toFixed(1)}%
Chi tiết xem trong file đính kèm.
`;
GmailApp.sendEmail(
recipients.join(','),
`[Báo Cáo] Kết Quả Tuần ${weekNum}/${year}`,
'Vui lòng xem file đính kèm.',
{
htmlBody: htmlBody,
attachments: [pdfBlob],
name: 'Hệ thống báo cáo tự động'
}
);
console.log(`Đã gửi báo cáo tuần ${weekNum} cho ${recipients.length} người`);
}
function getWeekNumber() {
const date = new Date();
const startOfYear = new Date(date.getFullYear(), 0, 1);
return Math.ceil(((date - startOfYear) / 86400000 + startOfYear.getDay() + 1) / 7);
}
Cài Đặt Trigger Tự Động Hàng Tuần
function createWeeklyTrigger() {
// Xóa trigger cũ nếu có
ScriptApp.getProjectTriggers().forEach(t => {
if (t.getHandlerFunction() === 'sendWeeklyReport') {
ScriptApp.deleteTrigger(t);
}
});
// Tạo trigger mới: mỗi thứ Hai lúc 8h–9h sáng
ScriptApp.newTrigger('sendWeeklyReport')
.timeBased()
.onWeekDay(ScriptApp.WeekDay.MONDAY)
.atHour(8)
.create();
}
Câu Hỏi Thường Gặp (FAQ)
PDF xuất ra có giữ được định dạng của Google Sheets không?
Cơ bản là có — màu sắc, font chữ, border. Tuy nhiên một số tính năng phức tạp như sparklines hay hình ảnh nhúng đôi khi render không hoàn hảo. Nên test kỹ trước khi deploy.
Có giới hạn kích thước file PDF đính kèm trong Gmail không?
Gmail giới hạn attachment 25MB/email. File PDF từ Google Sheets thường rất nhỏ (dưới 1MB) nên không phải vấn đề. Nếu báo cáo phức tạp, lưu lên Drive và gửi link thay vì đính kèm.
Script có chạy được khi không đăng nhập vào Google không?
Có. Trigger time-based chạy trên server Google, không phụ thuộc trình duyệt. Tuy nhiên script cần đủ quyền truy cập được ủy quyền trước.
Chia sẻ bài viết:
Tuân Hoang
Đội ngũ SheetStore
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.