Google Apps Script

Apps Script Sidebar: Tạo Ứng Dụng Nội Bộ Trên Google Sheets

Tuân HoangTuân Hoang
1 tháng 5, 2026
5 phút đọc

Sidebar Trong Google Sheets Là Gì?

Sidebar là panel HTML hiển thị bên phải Google Sheets, cho phép tạo giao diện tùy chỉnh mà không cần rời khỏi spreadsheet. Đây là cách mạnh nhất để biến Google Sheets thành một ứng dụng nội bộ thực sự.

Tạo Sidebar Đơn Giản

Bước 1: Tạo file HTML

// File: Sidebar.html
<!DOCTYPE html>
<html>
<head>
  <base target="_top">
  <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
  <style>
    .form-group { margin-bottom: 12px; }
    label { font-weight: bold; display: block; margin-bottom: 4px; }
    input, select, textarea {
      width: 100%; padding: 6px;
      border: 1px solid #ddd; border-radius: 4px;
    }
    .btn-primary {
      background: #4285f4; color: white;
      border: none; padding: 8px 16px;
      border-radius: 4px; cursor: pointer; width: 100%;
    }
    .status { padding: 8px; border-radius: 4px; margin-top: 8px; }
    .status.success { background: #d4edda; color: #155724; }
    .status.error { background: #f8d7da; color: #721c24; }
  </style>
</head>
<body>
  <h2>Thêm Khách Hàng Mới</h2>

  <div class="form-group">
    <label>Họ tên *</label>
    <input type="text" id="hoTen" placeholder="Nguyễn Văn A">
  </div>

  <div class="form-group">
    <label>Email</label>
    <input type="email" id="email" placeholder="email@example.com">
  </div>

  <div class="form-group">
    <label>Điện thoại *</label>
    <input type="tel" id="phone" placeholder="0901234567">
  </div>

  <div class="form-group">
    <label>Phân loại</label>
    <select id="loai">
      <option value="Lead">Lead</option>
      <option value="Prospect">Prospect</option>
      <option value="Customer">Khách hàng</option>
    </select>
  </div>

  <button class="btn-primary">Thêm Khách Hàng</button>

  <div id="status"></div>

  <script>
    function submitForm() {
      const data = {
        hoTen: document.getElementById('hoTen').value.trim(),
        email: document.getElementById('email').value.trim(),
        phone: document.getElementById('phone').value.trim(),
        loai: document.getElementById('loai').value
      };

      if (!data.hoTen || !data.phone) {
        showStatus('Vui lòng điền đầy đủ thông tin bắt buộc (*)', 'error');
        return;
      }

      // Gọi server-side function
      google.script.run
        .withSuccessHandler(result => showStatus(result.message, 'success'))
        .withFailureHandler(err => showStatus(err.message, 'error'))
        .addCustomer(data);
    }

    function showStatus(message, type) {
      const el = document.getElementById('status');
      el.className = 'status ' + type;
      el.textContent = message;
    }
  </script>
</body>
</html>

Bước 2: Server-side Code.gs

function showSidebar() {
  const html = HtmlService.createHtmlOutputFromFile('Sidebar')
    .setTitle('Quản Lý Khách Hàng')
    .setWidth(320);
  SpreadsheetApp.getUi().showSidebar(html);
}

function addCustomer(data) {
  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('KhachHang');

  // Validation
  if (!data.hoTen || !data.phone) {
    throw new Error('Thiếu thông tin bắt buộc');
  }

  // Kiểm tra trùng số điện thoại
  const phones = sheet.getRange('D:D').getValues().flat();
  if (phones.includes(data.phone)) {
    throw new Error('Số điện thoại đã tồn tại trong hệ thống');
  }

  // Tạo mã KH tự động
  const lastRow = sheet.getLastRow();
  const customerId = 'KH-' + String(lastRow).padStart(4, '0');

  sheet.appendRow([
    customerId,
    data.hoTen,
    data.email,
    data.phone,
    data.loai,
    new Date(),
    Session.getActiveUser().getEmail()
  ]);

  return { success: true, message: `✅ Đã thêm ${data.hoTen} (ID: ${customerId})` };
}

// Thêm menu vào Google Sheets
function onOpen() {
  SpreadsheetApp.getUi()
    .createMenu('Quản Lý')
    .addItem('Thêm khách hàng', 'showSidebar')
    .addToUi();
}

Sidebar Nâng Cao: Fetch Dữ Liệu Realtime

// Trong Sidebar.html - load dropdown từ sheet
function loadCategories() {
  google.script.run
    .withSuccessHandler(categories => {
      const select = document.getElementById('category');
      categories.forEach(cat => {
        const option = document.createElement('option');
        option.value = cat;
        option.textContent = cat;
        select.appendChild(option);
      });
    })
    .getCategories();
}

// Trong Code.gs
function getCategories() {
  const sheet = SpreadsheetApp.getActiveSpreadsheet()
    .getSheetByName('DanhMuc');
  return sheet.getRange('A2:A').getValues().flat().filter(v => v !== '');
}

Câu Hỏi Thường Gặp (FAQ)

Sidebar có thể hiển thị biểu đồ không?

Có. Dùng Google Charts API (charts.googleapis.com) hoặc Chart.js trong HTML để vẽ biểu đồ từ dữ liệu lấy qua google.script.run.

Sidebar có hoạt động trên mobile không?

Sidebar không hoạt động trên Google Sheets mobile app. Chỉ hoạt động trên desktop browser. Nếu cần mobile, tạo Google Form riêng thay thế.

Có thể tạo nhiều sidebar không?

Chỉ một sidebar hiển thị tại một thời điểm. Tuy nhiên bạn có thể tạo nhiều file HTML và switch giữa chúng bằng cách gọi showSidebar() với file HTML khác nhau.

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