Quản Lý Công Việc

Tự Động Hóa Quản Lý Công Việc Với Google Sheets & Apps Script: Hướng Dẫn Từ A-Z

Tuân HoangTuân Hoang
22 tháng 3, 2026
15 phút đọc

Tự động hóa hoàn toàn quy trình quản lý công việc với Google Sheets và Apps Script — không cần lập trình phức tạp.

Từ gửi email nhắc deadline tự động, cập nhật trạng thái task, đến thông báo Telegram cho team — tất cả đều làm được với Google Apps Script miễn phí. Bài viết này hướng dẫn từng bước với code mẫu copy-paste ngay.

1. Tại Sao Cần Tự Động Hóa Quản Lý Công Việc?

Một team 10 người thường mất trung bình 4-6 giờ mỗi tuần cho các công việc lặp đi lặp lại liên quan đến quản lý task: gửi reminder, cập nhật trạng thái, tổng hợp báo cáo, thông báo cho team. Nhân 52 tuần, đó là 200-300 giờ lãng phí mỗi năm — tương đương 12-18 tuần làm việc của một nhân viên.

Với Google Apps Script — hoàn toàn miễn phí và tích hợp sẵn trong Google Workspace — bạn có thể tự động hóa phần lớn những công việc này mà không cần kỹ sư phần mềm.

Chi phí Apps Script

Miễn phí hoàn toàn với Google account

6h/tuần

Thời gian tiết kiệm

Trung bình cho team 10 người

30 phút

Thời gian setup

Copy-paste code, chạy ngay

2. Google Apps Script Là Gì? Cách Bắt Đầu

Google Apps Script là nền tảng scripting dựa trên JavaScript, cho phép bạn tự động hóa và mở rộng các sản phẩm Google (Sheets, Gmail, Calendar, Drive, Forms...). Không cần server, không cần deploy — chạy trực tiếp trên Google Cloud.

Cách mở Apps Script Editor

  1. 1 Mở Google Sheets của bạn (file task management)
  2. 2 Vào menu ExtensionsApps Script
  3. 3 Apps Script Editor sẽ mở ra trong tab mới — đây là nơi bạn viết và chạy code
  4. 4 Copy code từ bài viết này, paste vào editor, nhấn Save rồi Run

Cấu trúc Google Sheets cho task management

Trước khi viết automation, hãy đảm bảo Sheets của bạn có cấu trúc chuẩn. Các automation dưới đây giả định file có cấu trúc sau:

// Cột A-H trong sheet "Tasks"

A: Task ID | B: Tên task | C: Người phụ trách

D: Deadline | E: Trạng thái | F: Ưu tiên

G: Email người phụ trách | H: Ghi chú

// Trạng thái: "Chưa làm" | "Đang làm" | "Chờ duyệt" | "Hoàn thành" | "Trễ hạn"

3. Automation #1: Gửi Email Nhắc Deadline Tự Động

Automation quan trọng nhất: tự động gửi email cho người phụ trách khi deadline còn 1-3 ngày. Không cần ai nhớ, không cần ai nhắc thủ công.

// === AUTOMATION #1: Email nhắc deadline ===

function

sendDeadlineReminders() {

  const sheet = SpreadsheetApp.getActiveSpreadsheet()
                              .getSheetByName('Tasks');
  const data = sheet.getDataRange().getValues();
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  // Bỏ qua hàng tiêu đề (hàng 1)
  for (let i = 1; i < data.length; i++) {
    const taskName   = data[i][1]; // Cột B
    const assignee   = data[i][2]; // Cột C
    const deadline   = new Date(data[i][3]); // Cột D
    const status     = data[i][4]; // Cột E
    const email      = data[i][6]; // Cột G

    // Bỏ qua task đã hoàn thành
    if (status === 'Hoàn thành' || !email) continue;

    deadline.setHours(0, 0, 0, 0);
    const daysLeft = Math.round(
      (deadline - today) / (1000 * 60 * 60 * 24)
    );

    // Nhắc khi còn 3 ngày, 1 ngày, hoặc đã trễ
    if (daysLeft === 3 || daysLeft === 1 || daysLeft < 0) {
      const subject = daysLeft < 0
        ? '[TRE HAN ' + Math.abs(daysLeft) + ' ngay] ' + taskName
        : 'Deadline con ' + daysLeft + ' ngay: ' + taskName;

      const body = 'Xin chao ' + assignee + ',

'
        + (daysLeft < 0
          ? 'Task da TRE HAN ' + Math.abs(daysLeft) + ' ngay!'
          : 'Deadline task sap den!')
        + '

Task: ' + taskName
        + '
Deadline: ' + deadline.toLocaleDateString('vi-VN')
        + '
Trang thai: ' + status
        + '

Vui long cap nhat tien do.

Tran trong';

      GmailApp.sendEmail(email, subject, body);
      console.log('Da gui reminder cho ' + assignee + ': ' + taskName);
    }
  }
}

📌 Cách setup trigger để chạy mỗi ngày:

Vào Apps Script Editor → Triggers (biểu tượng đồng hồ) → Add Trigger → Function: sendDeadlineReminders → Event source: Time-driven → Type: Day timer → Time: 8:00 AM → Save

4. Automation #2: Tự Động Cập Nhật Trạng Thái Và Màu Sắc

Script này tự động đánh dấu task là "Trễ hạn" khi qua deadline và tô màu ô để dễ nhìn thấy ngay lập tức.

// === AUTOMATION #2: Tự động cập nhật trạng thái và màu ===

function autoUpdateTaskStatus() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet()
                              .getSheetByName('Tasks');
  const lastRow = sheet.getLastRow();
  if (lastRow < 2) return;

  const today = new Date();
  today.setHours(0, 0, 0, 0);

  for (let row = 2; row <= lastRow; row++) {
    const deadlineCell = sheet.getRange(row, 4); // Cột D
    const statusCell   = sheet.getRange(row, 5); // Cột E
    const rowRange     = sheet.getRange(row, 1, 1, 8);

    const deadline = new Date(deadlineCell.getValue());
    const status   = statusCell.getValue();
    deadline.setHours(0, 0, 0, 0);

    // Bỏ qua hàng trống hoặc task đã xong
    if (!deadlineCell.getValue() || status === 'Hoàn thành') {
      if (status === 'Hoàn thành') {
        // Tô màu xanh lá cho task hoàn thành
        rowRange.setBackground('#d4edda');
      }
      continue;
    }

    const daysLeft = Math.round(
      (deadline - today) / (1000 * 60 * 60 * 24)
    );

    if (daysLeft < 0 && status !== 'Trễ hạn') {
      // Tự động mark trễ hạn + tô màu đỏ
      statusCell.setValue('Trễ hạn');
      rowRange.setBackground('#f8d7da');
    } else if (daysLeft === 0) {
      // Hôm nay deadline + tô màu vàng cam
      rowRange.setBackground('#fff3cd');
    } else if (daysLeft <= 3) {
      // Sắp deadline + tô màu vàng nhạt
      rowRange.setBackground('#fff9c4');
    } else if (status === 'Đang làm') {
      // Đang làm bình thường + tô màu xanh nhạt
      rowRange.setBackground('#d1ecf1');
    } else {
      // Reset về trắng nếu không có điều kiện nào
      rowRange.setBackground('#ffffff');
    }
  }

  // Cập nhật timestamp lần cuối chạy
  const infoSheet = SpreadsheetApp.getActiveSpreadsheet()
                                  .getSheetByName('Info');
  if (infoSheet) {
    infoSheet.getRange('B1').setValue(
      'Cập nhật lúc: ' + new Date().toLocaleString('vi-VN')
    );
  }
}

✅ Kết quả:

  • • Màu đỏ = task trễ hạn (tự động cập nhật status)
  • • Màu vàng cam = hôm nay là deadline
  • • Màu vàng nhạt = còn 1-3 ngày
  • • Màu xanh nhạt = đang làm, còn nhiều thời gian
  • • Màu xanh lá = hoàn thành

5. Automation #3: Gửi Thông Báo Telegram/Slack

Email đôi khi bị bỏ qua. Thông báo qua Telegram/Slack thì không. Script này gửi daily digest vào Telegram group của team mỗi sáng.

5.1 Setup Telegram Bot (5 phút)

  1. 1 Mở Telegram → tìm @BotFather → gõ /newbot
  2. 2 Đặt tên bot (ví dụ: "TaskBot_CtyBan") → lấy Bot Token (dạng: 123456789:ABCdef...)
  3. 3 Add bot vào group Telegram của team → lấy Chat ID bằng cách gọi API: https://api.telegram.org/bot<TOKEN>/getUpdates
  4. 4 Lưu Token và Chat ID vào Apps Script → chạy function bên dưới

// === AUTOMATION #3: Telegram daily digest ===

const TELEGRAM_TOKEN = 'THAY_BANG_BOT_TOKEN_CUA_BAN';
const TELEGRAM_CHAT_ID = 'THAY_BANG_CHAT_ID_CUA_BAN';

function sendTelegramDailyDigest() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet()
                              .getSheetByName('Tasks');
  const data = sheet.getDataRange().getValues();
  const today = new Date();
  today.setHours(0, 0, 0, 0);

  const overdue   = [];
  const dueToday  = [];
  const dueSoon   = []; // 1-3 ngày

  for (let i = 1; i < data.length; i++) {
    const taskName = data[i][1];
    const assignee = data[i][2];
    const deadline = new Date(data[i][3]);
    const status   = data[i][4];

    if (!taskName || status === 'Hoàn thành') continue;

    deadline.setHours(0, 0, 0, 0);
    const daysLeft = Math.round(
      (deadline - today) / (1000 * 60 * 60 * 24)
    );

    if (daysLeft < 0) {
      overdue.push(`❌ ${taskName} - ${assignee} (trễ ${Math.abs(daysLeft)} ngày)`);
    } else if (daysLeft === 0) {
      dueToday.push(`🔴 ${taskName} - ${assignee}`);
    } else if (daysLeft <= 3) {
      dueSoon.push(`🟡 ${taskName} - ${assignee} (còn ${daysLeft} ngày)`);
    }
  }

  // Tạo nội dung message
  let message = `📊 *DAILY TASK DIGEST*
`;
  message += `📅 ${today.toLocaleDateString('vi-VN')}

`;

  if (overdue.length > 0) {
    message += `*⚠️ TRỄ HẠN (${overdue.length} task):*
`;
    message += overdue.join('
') + '

';
  }

  if (dueToday.length > 0) {
    message += `*🔴 HÔM NAY DEADLINE (${dueToday.length} task):*
`;
    message += dueToday.join('
') + '

';
  }

  if (dueSoon.length > 0) {
    message += `*🟡 SẮP ĐẾN HẠN (${dueSoon.length} task):*
`;
    message += dueSoon.join('
') + '

';
  }

  if (overdue.length === 0 && dueToday.length === 0 && dueSoon.length === 0) {
    message += '✅ Tất cả task đều on track! Tiếp tục cố gắng nhé! 💪';
  }

  // Gửi qua Telegram API
  const url = `https://api.telegram.org/bot${TELEGRAM_TOKEN}/sendMessage`;
  const payload = {
    chat_id: TELEGRAM_CHAT_ID,
    text: message,
    parse_mode: 'Markdown'
  };

  UrlFetchApp.fetch(url, {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify(payload)
  });

  console.log('Đã gửi Telegram digest thành công');
}

5.2 Thông báo Slack (tương tự)

// === Gửi thông báo Slack qua Incoming Webhook ===

const SLACK_WEBHOOK_URL = 'https://hooks.slack.com/services/THAY_BANG_WEBHOOK_CUA_BAN';

function sendSlackNotification(message) {
  const payload = { text: message };
  UrlFetchApp.fetch(SLACK_WEBHOOK_URL, {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify(payload)
  });
}

// Gọi hàm này khi muốn gửi thông báo
// sendSlackNotification('🔔 Task X đã hoàn thành bởi Nguyễn Văn A');

6. Automation #4: Google Form → Task List Tự Động

Khi nhân viên submit một yêu cầu công việc qua Google Form, script tự động tạo task mới trong Sheets và gửi thông báo xác nhận. Không cần ai nhập tay.

Setup Google Form

Tạo Google Form với các trường:

  • Tên công việc cần làm (Short answer)
  • Mô tả chi tiết (Paragraph)
  • Deadline mong muốn (Date)
  • Mức độ ưu tiên: Cao / Trung bình / Thấp (Multiple choice)
  • Email người yêu cầu (Short answer)

// === AUTOMATION #4: Form → Task (chạy khi có Form submission) ===

function onFormSubmit(e) {
  // e.values là mảng dữ liệu từ Form theo thứ tự cột
  const [timestamp, taskName, description,
         deadline, priority, requesterEmail] = e.values;

  // Mở sheet Tasks
  const ss       = SpreadsheetApp.getActiveSpreadsheet();
  const taskSheet = ss.getSheetByName('Tasks');
  const lastRow  = taskSheet.getLastRow();

  // Tạo Task ID tự động
  const taskId = 'TASK-' + String(lastRow).padStart(4, '0');

  // Thêm row mới
  taskSheet.appendRow([
    taskId,              // A: Task ID
    taskName,            // B: Tên task
    '',                  // C: Người phụ trách (chưa assign)
    new Date(deadline),  // D: Deadline
    'Chưa làm',         // E: Trạng thái
    priority,            // F: Ưu tiên
    requesterEmail,      // G: Email
    description          // H: Ghi chú
  ]);

  // Gửi email xác nhận cho người yêu cầu
  GmailApp.sendEmail(
    requesterEmail,
    `✅ Đã nhận yêu cầu: ${taskName}`,
    `Xin chào,

Yêu cầu công việc của bạn đã được ghi nhận:

Task ID: ${taskId}
Task: ${taskName}
Deadline: ${deadline}
Ưu tiên: ${priority}

Chúng tôi sẽ assign người phụ trách và phản hồi trong vòng 24 giờ.

Trân trọng`
  );

  // Gửi thông báo Telegram cho team lead
  const telegramMsg =
    `📥 *YÊU CẦU MỚI*
` +
    `ID: ${taskId}
` +
    `Task: ${taskName}
` +
    `Deadline: ${deadline}
` +
    `Ưu tiên: ${priority}
` +
    `Từ: ${requesterEmail}`;

  sendTelegramDailyDigest(); // Hoặc gọi hàm send riêng
}

⚠️ Quan trọng — Setup trigger cho Form submission:

Trigger này phải được setup từ file Spreadsheet (không phải Form): Apps Script → Triggers → Add Trigger → Function: onFormSubmit → Event source: Spreadsheet → Event type: On form submit

7. Automation #5: Dashboard Auto-Refresh Và Báo Cáo Tuần

Script này tự động tính toán và cập nhật dashboard mỗi giờ, đồng thời tạo báo cáo tuần gửi email cho quản lý mỗi thứ Sáu.

// === AUTOMATION #5: Dashboard refresh + Weekly report ===

function refreshDashboard() {
  const ss        = SpreadsheetApp.getActiveSpreadsheet();
  const taskSheet = ss.getSheetByName('Tasks');
  const dashSheet = ss.getSheetByName('Dashboard');

  if (!dashSheet) {
    console.log('Không tìm thấy sheet Dashboard');
    return;
  }

  const data    = taskSheet.getDataRange().getValues();
  const today   = new Date();
  today.setHours(0, 0, 0, 0);

  // Đếm theo trạng thái
  let stats = {
    total:      0,
    chuaLam:    0,
    dangLam:    0,
    choaDuyet:  0,
    hoanThanh:  0,
    treLan:     0
  };

  let completedThisWeek = 0;
  const weekStart = new Date(today);
  weekStart.setDate(today.getDate() - today.getDay()); // Đầu tuần (Chủ nhật)

  for (let i = 1; i < data.length; i++) {
    if (!data[i][1]) continue; // Bỏ hàng trống
    stats.total++;

    switch(data[i][4]) {
      case 'Chưa làm':   stats.chuaLam++;   break;
      case 'Đang làm':   stats.dangLam++;   break;
      case 'Chờ duyệt':  stats.choaDuyet++; break;
      case 'Hoàn thành': stats.hoanThanh++; break;
      case 'Trễ hạn':    stats.treLan++;    break;
    }

    // Đếm hoàn thành trong tuần này
    const deadline = new Date(data[i][3]);
    if (data[i][4] === 'Hoàn thành' && deadline >= weekStart) {
      completedThisWeek++;
    }
  }

  // Cập nhật Dashboard sheet
  dashSheet.getRange('B2').setValue(stats.total);
  dashSheet.getRange('B3').setValue(stats.dangLam);
  dashSheet.getRange('B4').setValue(stats.hoanThanh);
  dashSheet.getRange('B5').setValue(stats.treLan);
  dashSheet.getRange('B6').setValue(completedThisWeek);
  dashSheet.getRange('B7').setValue(
    stats.total > 0
      ? Math.round((stats.hoanThanh / stats.total) * 100) + '%'
      : '0%'
  );
  dashSheet.getRange('B8').setValue(
    'Cập nhật: ' + new Date().toLocaleString('vi-VN')
  );

  console.log('Dashboard đã được refresh:', JSON.stringify(stats));
}

// Gửi báo cáo tuần mỗi thứ Sáu 17:00
function sendWeeklyReport() {
  const today = new Date();
  if (today.getDay() !== 5) return; // Chỉ chạy vào thứ Sáu

  // Refresh dashboard trước
  refreshDashboard();

  const ss        = SpreadsheetApp.getActiveSpreadsheet();
  const dashSheet = ss.getSheetByName('Dashboard');

  const total            = dashSheet.getRange('B2').getValue();
  const inProgress       = dashSheet.getRange('B3').getValue();
  const completed        = dashSheet.getRange('B4').getValue();
  const overdue          = dashSheet.getRange('B5').getValue();
  const completedThisWk  = dashSheet.getRange('B6').getValue();
  const completionRate   = dashSheet.getRange('B7').getValue();

  const reportBody = `
BÁO CÁO TUẦN - ${today.toLocaleDateString('vi-VN')}
================================================

TỔNG QUAN:
  • Tổng task: ${total}
  • Đang thực hiện: ${inProgress}
  • Hoàn thành: ${completed}
  • Trễ hạn: ${overdue}

TUẦN NÀY:
  • Task hoàn thành tuần này: ${completedThisWk}
  • Tỷ lệ hoàn thành: ${completionRate}

Link Sheets: ${ss.getUrl()}
  `.trim();

  // Gửi cho quản lý (thay email bên dưới)
  GmailApp.sendEmail(
    'manager@company.com',  // ← Thay email quản lý
    `📊 Báo cáo tuần ${today.toLocaleDateString('vi-VN')}`,
    reportBody
  );
}

8. Setup Triggers — Lịch Chạy Tự Động

Sau khi có tất cả 5 automation trên, bạn cần setup triggers để chúng chạy tự động theo lịch. Đây là cấu hình gợi ý:

Function Trigger type Lịch chạy Mục đích
sendDeadlineReminders Time-driven, Daily 8:00 AM mỗi ngày Nhắc email deadline
autoUpdateTaskStatus Time-driven, Daily 7:30 AM mỗi ngày Cập nhật màu sắc
sendTelegramDailyDigest Time-driven, Daily 9:00 AM mỗi ngày Digest sáng cho team
onFormSubmit On form submit Ngay khi có submission Tạo task từ Form
refreshDashboard Time-driven, Hourly Mỗi 1 giờ Cập nhật dashboard
sendWeeklyReport Time-driven, Daily 5:00 PM (chỉ chạy T6) Báo cáo tuần cho manager

📌 Cách tạo trigger trong Apps Script Editor:

  1. 1. Click biểu tượng đồng hồ (Triggers) ở sidebar trái
  2. 2. Click "+ Add Trigger" góc dưới phải
  3. 3. Chọn Function cần chạy
  4. 4. Event source: Time-driven
  5. 5. Type: Day timer / Hour timer / Week timer
  6. 6. Chọn giờ/ngày → Save
  7. 7. Google sẽ yêu cầu cấp quyền — Accept để cho phép gửi email, đọc Sheets

9. SheetStore — Template Có Sẵn Automation, Dùng Ngay

Nếu bạn không muốn tự viết code từ đầu, các template quản lý công việc trên SheetStore đã tích hợp sẵn tất cả các automation trên — đã được test kỹ và có hướng dẫn chi tiết.

Template SheetStore đã bao gồm:

Email reminder tự động

Nhắc deadline 1, 3, 7 ngày trước — có thể tùy chỉnh

Dashboard tự cập nhật

Biểu đồ và số liệu tự động refresh theo dữ liệu thực

Màu sắc trạng thái tự động

Visual rõ ràng — đỏ/vàng/xanh theo deadline và status

Báo cáo tuần/tháng

Export báo cáo PDF hoặc gửi email summary tự động

Telegram notification

Digest sáng cho team, alert ngay khi task trễ hạn

Form → Task tự động

Google Form submit → tạo task ngay, xác nhận email

Xem thêm hướng dẫn: Quản lý công việc cho startup từ 2 đến 50 người để hiểu rõ hơn cách kết hợp automation với quy trình quản lý phù hợp từng giai đoạn.

10. FAQ — Câu Hỏi Thường Gặp

Google Apps Script có miễn phí không?
Hoàn toàn miễn phí với mọi tài khoản Google. Giới hạn miễn phí: 6 phút runtime/lần chạy, 90 phút/ngày, 100 email/ngày, 20.000 UrlFetch/ngày. Đủ cho hầu hết use case của team nhỏ và vừa.
Cần biết lập trình mới dùng được Apps Script không?
Không cần. Các code trong bài viết này có thể copy-paste và chỉnh sửa tên cột, email, token theo hướng dẫn mà không cần hiểu sâu về lập trình. Chỉ cần biết cơ bản về Google Sheets là đủ.
Apps Script có thể tích hợp với Zalo không?
Có thể tích hợp với Zalo OA (Official Account) qua Zalo API nếu doanh nghiệp đã đăng ký Zalo OA. Tuy nhiên phức tạp hơn Telegram. Khuyến nghị dùng Telegram cho internal team notification vì đơn giản hơn nhiều.
Có thể tự động hóa Google Sheets không cần Apps Script không?
Có, bạn có thể dùng Zapier hoặc Make (Integromat) để tạo automation không cần code. Tuy nhiên các tool này có phí (từ $20-50/tháng) và giới hạn số lượng automation. Apps Script miễn phí và linh hoạt hơn nhiều cho người biết một chút JavaScript.

Tự động hóa quản lý công việc ngay hôm nay

Template Google Sheets + Apps Script sẵn sàng dùng — email reminder, Telegram notification, dashboard tự động. Không cần viết code.

Tải Template Ngay Xem Bảng Giá

Chia sẻ bài viết:

Tuân Hoang

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.

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