1. Cơ chế Tự động Tách từ Mẫu 10 cột của Trưởng thôn ➔ 79 cột Excel Bộ GD&ĐT

Ô nhập trên Mẫu Phiếu Đơn Giản Ví dụ Người dân nhập / chọn Hệ thống tự động tách sang File Excel 79 cột (Bộ GD&ĐT)
Họ và tên (4) Phan Trâm Anh Cột 3 (Họ đệm): Phan Trâm | Cột 4 (Tên): Anh (Tương tự cho Họ đệm & Tên Chủ hộ ở Cột 13, 14)
Ngày sinh 19/11/2017 Cột 5 (Ngày): 19 | Cột 6 (Tháng): 11 | Cột 7 (Năm): 2017
Tổ số & Tổ dân phố Tổ 1 - Hòa Khê Gộp tự động vào Cột 16 (Địa chỉ: Số nhà, tên đường, tổ): Tổ 1 - Hòa Khê
Tên lớp - Tên Trường - Phường ĐANG HỌC (6) 11/2 - Trường THPT Phạm Phú Thứ - Hoà Khánh • Cột 32 (Cấp học): Trung học phổ thông | Cột 33 (Khối): Khối 11 | Cột 35 (Tên lớp): 11/2
• Cột 40 & 41 (Trường & Phân hiệu): Trường THPT Phạm Phú Thứ
• Cột 38 & 39 (Tỉnh & Phường học tập): Thành phố Đà Nẵng - Phường Hòa Khánh
Hoàn thành chương trình (7) Chọn: Mầm non / Tiểu học / Trung học cơ sở / Trung học phổ thông • Ghi trực tiếp vào Cột 55 theo đúng danh mục của Bộ GD&ĐT.
Cách 1 — Khuyên dùng (Miễn phí 100% với Gmail)

Kết nối với Google Trang tính (Google Sheets) & Xuất File Web Gửi Dân

Làm theo 3 bước dưới đây để mọi phiếu người dân bấm "Lưu phiếu" trên điện thoại đều tự động đổ về Google Trang tính của bạn:

Bước 1: Dán mã vào Google Trang tính

Mở 1 file Google Trang tính mới ➔ trên thanh menu bấm Tiện ích mở rộng (Extensions) ➔ Apps Script. Xóa chữ có sẵn, bấm nút "Sao chép mã Google Apps Script" ở trên rồi dán vào và bấm biểu tượng đĩa mềm 💾 (Lưu).

Bước 2: Lấy đường link Web App

Bấm nút màu xanh Triển khai (Deploy) ở góc phải trên ➔ Tùy chọn triển khai mới (New deployment) ➔ Chọn loại Ứng dụng web (Web app). Mục Ai có quyền truy cập (Who has access) chọn Bất kỳ ai (Anyone) ➔ Bấm Triển khai và copy đường link https://script.google.com/macros/s/.../exec.

Bước 3: Dán link vào ô dưới & Tải file Web

Dán đường link vừa copy vào ô bên dưới rồi bấm "Tải File index.html Đã Gắn Link". Sau đó đưa file index.html đó lên Cloudflare Pages là có link gửi Zalo cho toàn dân!

● Đã kết nối Google Trang tính: Mọi phiếu bấm "Lưu phiếu" sẽ tự động gửi thẳng về Google Sheets của bạn.

Xem toàn bộ đoạn mã Google Apps Script (Code.gs) để dán vào Google Trang tính
function doPost(e) {
  var lock = LockService.getScriptLock();
  lock.waitLock(10000);
  try {
    var data = JSON.parse(e.postData.contents);
    var ss = SpreadsheetApp.getActiveSpreadsheet();
    
    // 1. Lưu vào sheet DuLieuPhieu_Goc (Để đồng bộ về App xuất Excel 79 cột)
    var sheetHo = ss.getSheetByName('DuLieuPhieu_Goc');
    if (!sheetHo) {
      sheetHo = ss.insertSheet('DuLieuPhieu_Goc');
      sheetHo.appendRow(['ID_Ho', 'ThoiGian', 'SoPhieu', 'HoTenChuHo', 'CCCD_ChuHo', 'DienThoai', 'ToSo', 'ToDanPho', 'DienCuTru', 'JSON_Full']);
    }
    var rows = sheetHo.getDataRange().getValues();
    var foundRow = -1;
    for (var i = 1; i < rows.length; i++) {
      if (String(rows[i][0]) === String(data.id) || (String(rows[i][4]) !== '000000000000' && String(rows[i][4]) === String(data.cccd_chu_ho))) {
        foundRow = i + 1;
        break;
      }
    }
    var rowData = [data.id, new Date().toLocaleString('vi-VN'), data.so_phieu, data.ho_ten_chu_ho, "'" + data.cccd_chu_ho, "'" + data.dien_thoai, data.to_so, data.dia_chi_hien_o, data.dien_cu_tru, JSON.stringify(data)];
    if (foundRow > 0) {
      sheetHo.getRange(foundRow, 1, 1, rowData.length).setValues([rowData]);
    } else {
      sheetHo.appendRow(rowData);
    }

    // 2. Lưu thêm vào sheet BangThanhVien_10Cot để Cán bộ xem trực tiếp trên Google Sheets
    var sheetTV = ss.getSheetByName('BangThanhVien_10Cot');
    if (!sheetTV) {
      sheetTV = ss.insertSheet('BangThanhVien_10Cot');
      sheetTV.appendRow(['Thời gian', 'Tổ dân phố', 'Tổ số', 'Chủ hộ', 'CCCD Chủ hộ', 'SĐT', 'Họ tên TV (4)', 'Giới tính', 'Ngày sinh', 'Số CCCD (12 số)', 'Quan hệ (5)', 'Đang học (6)', 'Hoàn thành CT (7)', 'TN Nghề (8)', 'Khuyết tật (9)', 'Ghi chú (10)']);
    }
    (data.rows || []).forEach(function(r) {
      sheetTV.appendRow([new Date().toLocaleString('vi-VN'), data.dia_chi_hien_o, data.to_so, data.ho_ten_chu_ho, "'" + data.cccd_chu_ho, "'" + data.dien_thoai, r.ho_ten, r.gioi_tinh, r.ngay_sinh, "'" + r.cccd, r.quan_he, r.dang_hoc, r.hoan_thanh, r.bac_nghe, r.khuyet_tat, r.ghi_chu]);
    });

    return ContentService.createTextOutput(JSON.stringify({ status: 'ok' })).setMimeType(ContentService.MimeType.JSON);
  } catch (err) {
    return ContentService.createTextOutput(JSON.stringify({ status: 'error', message: err.toString() })).setMimeType(ContentService.MimeType.JSON);
  } finally {
    lock.releaseLock();
  }
}

function doGet(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheetHo = ss.getSheetByName('DuLieuPhieu_Goc');
  var list = [];
  if (sheetHo) {
    var rows = sheetHo.getDataRange().getValues();
    for (var i = 1; i < rows.length; i++) {
      try { list.push(JSON.parse(rows[i][9])); } catch (err) {}
    }
  }
  return ContentService.createTextOutput(JSON.stringify({ status: 'ok', households: list })).setMimeType(ContentService.MimeType.JSON);
}

2. Mã lệnh SQL khởi tạo bảng trên Supabase (PostgreSQL)

CREATE TABLE public.phieu_dieu_tra_ho (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    so_phieu VARCHAR(30),
    dien_cu_tru VARCHAR(20) DEFAULT 'Thường trú',
    ho_ten_chu_ho VARCHAR(150) NOT NULL,
    cccd_chu_ho VARCHAR(12) NOT NULL,
    dien_thoai VARCHAR(15) NOT NULL,
    to_so VARCHAR(50),
    to_dan_pho VARCHAR(100) NOT NULL,
    tre_chua_den_truong TEXT,
    ly_do_chua_den_truong TEXT,
    thanh_vien_10_cot JSONB NOT NULL DEFAULT '[]'::jsonb,
    updated_at TIMESTAMPTZ DEFAULT now(),
    CONSTRAINT uq_cccd_phone UNIQUE (cccd_chu_ho, dien_thoai)
);