Custom Functions & Menu

Thời gian đọc: ~30 phút

Custom Functions — Hàm Tự Định Nghĩa

Custom Functions cho phép bạn viết hàm JavaScript rồi dùng trực tiếp trong ô Sheets như =SUM(), =VLOOKUP(). Đây là tính năng rất mạnh để thực hiện logic phức tạp mà các hàm built-in không làm được.

/**
 * Chuyển đổi số tiền VNĐ sang chuỗi có định dạng.
 * @param {number} amount - Số tiền cần định dạng
 * @return {string} Chuỗi định dạng
 * @customfunction
 */
function DINH_DANG_TIEN(amount) {
  if (typeof amount !== 'number') return 'Không hợp lệ';
  return amount.toLocaleString('vi-VN') + ' đ';
}

/**
 * Tính VAT.
 * @param {number} gia - Giá gốc
 * @param {number} tyLe - Tỷ lệ VAT (mặc định 10%)
 * @return {number} Giá sau VAT
 * @customfunction
 */
function TINH_VAT(gia, tyLe) {
  tyLe = tyLe || 10;
  return gia * (1 + tyLe / 100);
}

Sau khi lưu, gõ =DINH_DANG_TIEN(A1) hoặc =TINH_VAT(B2, 10) trong ô bất kỳ — Google Sheets sẽ tự suggest tên hàm.

Lưu ý quan trọng về Custom Functions:
  • Chỉ được dùng SpreadsheetApp ở chế độ đọc (không ghi)
  • Không được gọi MailApp, UrlFetchApp trong custom function
  • Kết quả được cache — nếu dữ liệu không đổi, hàm sẽ không chạy lại
  • Gọi Math.random() hoặc ngày giờ sẽ không tự cập nhật

Xử Lý Mảng Trong Custom Function

/**
 * Tính tổng các ô thỏa điều kiện (custom SUMIF đơn giản).
 * @param {Array} range - Vùng dữ liệu
 * @param {string} dkien - Điều kiện
 * @return {number}
 * @customfunction
 */
function TONG_CO_DIEU_KIEN(range, dkien) {
  if (!Array.isArray(range)) range = [[range]];
  let tong = 0;
  range.forEach(function(row) {
    row.forEach(function(cell) {
      if (cell === dkien) tong += 1;
    });
  });
  return tong;
}

// Dùng: =TONG_CO_DIEU_KIEN(A2:A100, "Đã thanh toán")

Custom Menu

Thêm menu tùy chỉnh vào Google Sheets để người dùng dễ dàng chạy script mà không cần mở editor:

function onOpen() {
  const ui = SpreadsheetApp.getUi();
  ui.createMenu('Cong Cu')
    .addItem('Tinh tong doanh thu', 'tinhTongDoanhThu')
    .addItem('Xuat bao cao PDF', 'xuatBaoCaoPDF')
    .addSeparator()
    .addSubMenu(
      ui.createMenu('Bao cao')
        .addItem('Bao cao tuan', 'baoCaoTuan')
        .addItem('Bao cao thang', 'baoCaoThang')
    )
    .addToUi();
}

onOpen()simple trigger — tự động chạy mỗi khi file được mở. Menu sẽ xuất hiện trên thanh menu của Sheets.

Dialog & Alert

// Alert đơn giản
function showAlert() {
  SpreadsheetApp.getUi().alert('Thao tac hoan thanh!');
}

// Hộp thoại xác nhận Yes/No
function confirmDelete() {
  const ui = SpreadsheetApp.getUi();
  const result = ui.alert(
    'Xac nhan',
    'Ban co chac muon xoa du lieu?',
    ui.ButtonSet.YES_NO
  );
  if (result === ui.Button.YES) {
    SpreadsheetApp.getActiveSheet().getDataRange().clearContent();
    ui.alert('Da xoa!');
  }
}

// Hộp nhập liệu
function promptInput() {
  const ui = SpreadsheetApp.getUi();
  const result = ui.prompt('Nhap ten san pham:');
  if (result.getSelectedButton() === ui.Button.OK) {
    const ten = result.getResponseText();
    SpreadsheetApp.getActiveSheet().appendRow([ten, new Date()]);
  }
}
Thực hành: Tạo menu "Nhap Lieu" với item "Them san pham moi" gọi hàm promptInput(). Khi nhấn menu, người dùng sẽ được hỏi tên sản phẩm và tự động thêm vào sheet.