Thêm tool phân poi theo team

0 comments0 reviews

Để triển khai Cách 1: Nút bấm 1 chạm tự động hóa (Google Apps Script), tôi đã chuẩn bị sẵn một đoạn mã tối ưu hóa đặc thù cho cấu trúc bảng tính hiện tại của bạn.

Kịch bản này khi chạy sẽ tự động thực hiện 3 công việc trong vài giây:

  1. Đọc danh sách thành viên thực tế từ cột C7:C41 trên sheet Dashboard (bỏ qua các dòng trống).
  2. Chia đều danh sách POI trong sheet Tổng hợp cho số lượng thành viên thực tế và điền vào cột labeled_by (cột BM).
  3. Đổi tên các tab sheet thành viên theo đúng họ tên, sau đó xóa dữ liệu cũ và chép dữ liệu POI mới vào từng tab tương ứng.

#BƯỚC 1: Dán mã vào Tiện ích mở rộng (Apps Script)

  1. Trên thanh công cụ của Google Sheets, bạn vào menu: Tiện ích mở rộng (Extensions) > Apps Script.
  2. Một tab mới sẽ mở ra. Hãy xóa hết các dòng code mặc định đang có (function myFunction() {...}).
  3. Sao chép và dán toàn bộ đoạn mã dưới đây vào trình soạn thảo:
<!-- end list -->
/**
 * TỰ ĐỘNG CHIA POI, ĐỔI TÊN TAB VÀ ĐỒNG BỘ DỮ LIỆU SANG 35 TAB THÀNH VIÊN
 */
function tuDongChiaPOIVaDongBo() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const dashboardSheet = ss.getSheetByName("Dashboard");
  const tongHopSheet = ss.getSheetByName("Tổng hợp");

  if (!dashboardSheet || !tongHopSheet) {
    SpreadsheetApp.getUi().alert("Lỗi: Không tìm thấy sheet 'Dashboard' hoặc 'Tổng hợp'.");
    return;
  }

  // 1. Lấy danh sách thành viên từ Dashboard (C7:C41)
  const memberValues = dashboardSheet.getRange("C7:C41").getValues();
  const members = [];
  for (let i = 0; i < memberValues.length; i++) {
    const name = String(memberValues[i][0]).trim();
    if (name !== "" && !name.toLowerCase().startsWith("thành viên")) {
      members.push(name);
    }
  }

  const numMembers = members.length;
  if (numMembers === 0) {
    SpreadsheetApp.getUi().alert("Không tìm thấy thành viên hợp lệ nào trong cột C7:C41 ở Dashboard!");
    return;
  }

  // 2. Xác định số lượng POI trong sheet Tổng hợp (Dữ liệu từ dòng 4)
  const lastRow = tongHopSheet.getLastRow();
  if (lastRow < 4) {
    SpreadsheetApp.getUi().alert("Sheet 'Tổng hợp' chưa có dữ liệu POI từ dòng 4 trở đi!");
    return;
  }

  const totalPOIs = lastRow - 3;
  const baseCount = Math.floor(totalPOIs / numMembers);
  const remainder = totalPOIs % numMembers;

  // 3. Phân bổ tên thành viên vào cột labeled_by (cột 65 / BM)
  const labeledByCol = 65; // Cột BM
  const assignedNames = [];
  const memberRanges = {};

  let currentStart = 4;
  for (let m = 0; m < numMembers; m++) {
    const count = baseCount + (m < remainder ? 1 : 0);
    const memberName = members[m];
    memberRanges[memberName] = { start: currentStart, count: count };
    
    for (let c = 0; c < count; c++) {
      assignedNames.push([memberName]);
    }
    currentStart += count;
  }

  // Ghi tên vào cột BM của sheet Tổng hợp
  tongHopSheet.getRange(4, labeledByCol, totalPOIs, 1).setValues(assignedNames);

  // 4. Lấy danh sách các tab thành viên hiện có (ngoại trừ các tab hệ thống)
  const excludeSheets = ["Tổng hợp", "Dashboard", "Data Catalog"];
  const allSheets = ss.getSheets();
  const memberSheets = allSheets.filter(s => !excludeSheets.includes(s.getName()));

  // Lấy dữ liệu toàn bộ bảng Tổng hợp (từ dòng 4 đến dòng cuối, từ cột 1 đến 76 - cột BX)
  const totalCols = 76;
  const fullData = tongHopSheet.getRange(4, 1, totalPOIs, totalCols).getValues();

  // 5. Đổi tên sheet và đồng bộ dữ liệu vào từng tab thành viên
  for (let i = 0; i < memberSheets.length; i++) {
    const sheet = memberSheets[i];
    
    if (i < numMembers) {
      const targetName = members[i];
      // Đổi tên tab nếu khác tên
      if (sheet.getName() !== targetName) {
        try {
          sheet.setName(targetName);
        } catch (e) {
          // Tránh lỗi trùng tên tạm thời nếu có
          sheet.setName(targetName + " (" + (i + 1) + ")");
        }
      }

      // Xóa dữ liệu cũ từ dòng 4 trở đi (giữ nguyên 3 dòng tiêu đề)
      const currentLastRow = sheet.getLastRow();
      if (currentLastRow >= 4) {
        sheet.getRange(4, 1, currentLastRow - 3, totalCols).clearContent();
      }

      // Lấy các dòng POI thuộc về thành viên này
      const info = memberRanges[targetName];
      if (info && info.count > 0) {
        const offset = info.start - 4;
        const memberRows = fullData.slice(offset, offset + info.count);
        sheet.getRange(4, 1, info.count, totalCols).setValues(memberRows);
      }
    } else {
      // Đổi tên các sheet còn lại về mặc định và xóa dữ liệu
      const fallbackName = "Thành viên " + (i + 1);
      if (sheet.getName() !== fallbackName) {
        sheet.setName(fallbackName);
      }
      const currentLastRow = sheet.getLastRow();
      if (currentLastRow >= 4) {
        sheet.getRange(4, 1, currentLastRow - 3, totalCols).clearContent();
      }
    }
  }

  SpreadsheetApp.getUi().alert(
    "✅ ĐÃ ĐỒNG BỘ THÀNH CÔNG!\n\n" +
    "- Tổng số POI: " + totalPOIs + "\n" +
    "- Số thành viên: " + numMembers + "\n" +
    "- Số POI/người: " + baseCount + " - " + (baseCount + (remainder > 0 ? 1 : 0)) + " POI\n" +
    "- Đã chia tên trên sheet Tổng hợp và sao chép sang từng tab thành viên."
  );
}

  1. Bấm biểu tượng 💾 Lưu (Save project) trên thanh công cụ Apps Script (hoặc nhấn Ctrl + S).

#BƯỚC 2: Tạo nút bấm trực quan ngay trên sheet Dashboard

  1. Quay lại tab bảng tính Google Sheets, mở sheet Dashboard.
  2. Trên menu, chọn: Chèn (Insert) > Bản vẽ (Drawing).
  3. Trong cửa sổ vẽ:
    • Chọn biểu tượng Hình dạng (Shape) > Hình chữ nhật bo góc.
    • Vẽ một nút bấm, tô màu xanh dương/xanh lục, nhấp đôi vào gõ chữ:
      🔄 TỰ ĐỘNG CHIA & ĐỒNG BỘ POI
    • Chỉnh chữ in đậm, căn giữa rồi bấm nút Lưu và đóng (Save and Close) ở góc trên bên phải.
  4. Kéo nút vừa tạo đặt vào vị trí thuận tiện trên Dashboard (ví dụ: đặt gần góc trên bên phải, cạnh ô G2:G4).
  5. Gán lệnh cho nút:
    • Nhấp chuột vào nút bấm, bạn sẽ thấy dấu 3 chấm dọc xuất hiện ở góc trên bên phải của nút.
    • Bấm vào dấu 3 chấm > chọn Gán tập lệnh (Assign script).
    • Nhập chính xác tên hàm sau:
      tuDongChiaPOIVaDongBo
    • Bấm OK.

#BƯỚC 3: Cấp quyền chạy (Chỉ cần làm 1 lần duy nhất)

  • Lần đầu tiên bạn bấm vào nút này, Google sẽ hiện thông báo "Cần có ủy quyền" (Authorization Required).
  • Bạn bấm: Tiếp tục > Chọn tài khoản Google của bạn > Bấm Nâng cao (Advanced) > Chọn Đi tới Untitled project (không an toàn) > Bấm Cho phép (Allow).

#🎉 Cách bạn sử dụng sau này:

  • Mỗi khi có đợt mới:
    1. Bạn chỉ cần cập nhật danh sách họ tên các bạn ở cột C7:C41 trên sheet Dashboard.
    2. Dán danh sách POI mới vào sheet Tổng hợp (từ dòng 4).
    3. Bấm nút 🔄 TỰ ĐỘNG CHIA & ĐỒNG BỘ POI. Toàn bộ tên tab, cột labeled_by, dữ liệu 35 tab và số liệu Dashboard sẽ tự động được chia đều và cập nhật ngay lập tức!