Backend Modular: Schema.gs & Code.gs
Di Google Apps Script, semua file bertipe .gs secara otomatis berbagi global scope yang sama (tanpa memerlukan perintah import atau export). Kita bisa memisahkan tanggung jawab backend menjadi 2 file modular agar kode lebih bersih dan teratur:
Editor Google Apps Script:├── Schema.gs # Definisi skema tabel, mapping kolom, & inisialisasi sheet├── Code.gs # Logika backend CRUD & router Web App (doGet & doPost)└── Index.html # Frontend: Struktur HTML + Styling CSS dalam 1 file1. Prompt untuk Membuat Schema.gs & Code.gs (Framework T-C-R-E-I)
Section titled “1. Prompt untuk Membuat Schema.gs & Code.gs (Framework T-C-R-E-I)”[PERSONA]Bertindaklah sebagai spesialis backend Google Apps Script.
[TASK]- Buatkan 2 file backend modular: Schema.gs dan Code.gs untuk aplikasi absensi presensi Google Sheets.- Pastikan Schema.gs menangani inisialisasi sheet dan validasi struktur tabel, sementara Code.gs fokus pada logika CRUD dan routing Web App.
[CONTEXT]- Kolom database: ID, Timestamp, Nama, Status (Hadir/Izin/Sakit), Catatan.- Operasi CRUD: Catat presensi baru (ID unik & timestamp WIB), ambil semua data untuk tabel, ubah status, dan hapus baris.- Web App: Fungsi doGet() untuk merender Index.html dan doPost() untuk memproses form.
[OUTPUT FORMAT]1. File Schema.gs (konfigurasi tabel dan inisialisasi sheet otomatis)2. File Code.gs (fungsi CRUD dan router doGet/doPost yang memanggil fungsi dari Schema.gs)Bertindaklah sebagai backend developer Google Apps Script. Buatkan 2 file backend modular: Schema.gs dan Code.gs untuk aplikasi absensi.
Context:- Schema.gs: Mengatur nama sheet, inisialisasi kolom tabel (ID, Timestamp, Nama, Status, Catatan).- Code.gs: Mengelola fungsi CRUD (Create, Read, Update, Delete) serta router doGet dan doPost.
Output format:Berikan file Schema.gs dan Code.gs lengkap yang siap disalin ke editor Google Apps Script.2. Kode Hasil Schema.gs (Konfigurasi & Inisialisasi Database)
Section titled “2. Kode Hasil Schema.gs (Konfigurasi & Inisialisasi Database)”File Schema.gs mendefinisikan konstanta nama sheet, struktur kolom, dan fungsi pembantu untuk memastikan sheet siap digunakan:
// ===========================================================================// SCHEMA.GS — Konfigurasi & Inisialisasi Database Google Sheets// ===========================================================================
const DB_CONFIG = { SHEET_NAME: "Database_Absensi", COLUMNS: ["ID", "Timestamp", "Nama", "Status", "Catatan"], STATUS_OPTIONS: ["Hadir", "Izin", "Sakit"]};
/** * Membuka atau membuat sheet database absensi secara otomatis. * Jika sheet belum memiliki header kolom, fungsi ini akan membuatnya. */function getDatabaseSheet() { const ss = SpreadsheetApp.getActiveSpreadsheet(); let sheet = ss.getSheetByName(DB_CONFIG.SHEET_NAME);
if (!sheet) { sheet = ss.insertSheet(DB_CONFIG.SHEET_NAME); // Tambahkan header kolom pertama kali sheet.appendRow(DB_CONFIG.COLUMNS); sheet.getRange(1, 1, 1, DB_CONFIG.COLUMNS.length) .setFontWeight("bold") .setBackground("#242424") .setFontColor("#fafafa"); }
return sheet;}3. Kode Hasil Code.gs (CRUD Engine & Web Router)
Section titled “3. Kode Hasil Code.gs (CRUD Engine & Web Router)”File Code.gs memanfaatkan fungsi getDatabaseSheet() dari Schema.gs untuk menjalankan seluruh logika Create, Read, Update, Delete:
// ===========================================================================// CODE.GS — Logika CRUD & Router Web App// ===========================================================================
// ---------------------------------------------------------------------------// 1. CREATE: Menambah Catatan Presensi Baru// ---------------------------------------------------------------------------function createAttendance(nama, status, catatan) { const sheet = getDatabaseSheet(); const id = "ABS-" + new Date().getTime(); const timestamp = Utilities.formatDate(new Date(), "GMT+7", "yyyy-MM-dd HH:mm:ss");
sheet.appendRow([id, timestamp, nama, status, catatan || "-"]); return { status: "success", message: "Presensi berhasil dicatat!", id: id };}
// ---------------------------------------------------------------------------// 2. READ: Mengambil Seluruh Riwayat Presensi// ---------------------------------------------------------------------------function readAttendance() { const sheet = getDatabaseSheet(); const data = sheet.getDataRange().getValues(); if (data.length <= 1) return []; // Hanya header kolom
const rows = data.slice(1); return rows.map((row, index) => ({ rowNumber: index + 2, id: row[0], timestamp: row[1], nama: row[2], status: row[3], catatan: row[4] }));}
// ---------------------------------------------------------------------------// 3. UPDATE: Mengubah Status Kehadiran Berdasarkan ID// ---------------------------------------------------------------------------function updateAttendance(id, newStatus, newCatatan) { const sheet = getDatabaseSheet(); const data = sheet.getDataRange().getValues();
for (let i = 1; i < data.length; i++) { if (data[i][0] === id) { const row = i + 1; if (newStatus) sheet.getRange(row, 4).setValue(newStatus); if (newCatatan) sheet.getRange(row, 5).setValue(newCatatan); return { status: "success", message: "Data presensi berhasil diperbarui!" }; } } return { status: "error", message: "Data tidak ditemukan." };}
// ---------------------------------------------------------------------------// 4. DELETE: Menghapus Baris Presensi Berdasarkan ID// ---------------------------------------------------------------------------function deleteAttendance(id) { const sheet = getDatabaseSheet(); const data = sheet.getDataRange().getValues();
for (let i = 1; i < data.length; i++) { if (data[i][0] === id) { sheet.deleteRow(i + 1); return { status: "success", message: "Catatan presensi berhasil dihapus!" }; } } return { status: "error", message: "Data tidak ditemukan." };}
// ---------------------------------------------------------------------------// 5. PENYAJIAN WEB APP (doGet)// ---------------------------------------------------------------------------function doGet(e) { const template = HtmlService.createTemplateFromFile("Index"); template.attendanceData = readAttendance(); // Dikirim langsung ke HTML return template.evaluate() .setTitle("Aplikasi Presensi Karyawan") .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);}
// ---------------------------------------------------------------------------// 6. ROUTER HTTP POST: Menangani Kiriman Form dari HTML// ---------------------------------------------------------------------------function doPost(e) { const lock = LockService.getScriptLock(); lock.tryLock(30000);
try { const action = e.parameter.action || "create";
if (action === "create") { createAttendance(e.parameter.nama, e.parameter.status, e.parameter.catatan); } else if (action === "update") { updateAttendance(e.parameter.id, e.parameter.status, e.parameter.catatan); } else if (action === "delete") { deleteAttendance(e.parameter.id); }
// Tampilkan kembali halaman Index.html dengan data terbaru const template = HtmlService.createTemplateFromFile("Index"); template.attendanceData = readAttendance(); return template.evaluate() .setTitle("Aplikasi Presensi Karyawan") .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
} catch (err) { return HtmlService.createHtmlOutput("<h2 style='font-family:system-ui,sans-serif;color:#ef4444;'>Error: " + err.toString() + "</h2>"); } finally { lock.releaseLock(); }}4. Keuntungan Pemisahan Schema.gs dan Code.gs
Section titled “4. Keuntungan Pemisahan Schema.gs dan Code.gs”- Clean Code: Konfigurasi tabel dan nama kolom tidak tercampur dengan kode logika aplikasi.
- Inisialisasi Otomatis: Jika sheet database belum ada di Google Spreadsheet,
getDatabaseSheet()diSchema.gsakan langsung membuatnya beserta format header yang rapi. - Tanpa Perlu Import: Google Apps Script secara otomatis menggabungkan seluruh file
.gsdalam satu project.
Checkpoint
Section titled “Checkpoint”- Membuat file
Schema.gsdanCode.gsdi editor Google Apps Script. - Memahami cara kerja inisialisasi sheet otomatis di
Schema.gs. - Menguji fungsi
createAttendancedandeleteAttendancediCode.gs. - Siap mempublikasikan Web App di modul Integrasi & Deploy.