Membuat Sistem Presensi Mandiri menggunakan Google Sheets dan Apps Script
Tranformasi digital di ruang kelas tidak melulu mengenai sumber belajar yang memudahkan guru dalam menyampaikan materi selain materi guru juga mendigitalisasi penunjang lainnya seperti presensi. Tujuannya sama seperti sumber belajar memudahkan terkadang hal yang membingungkan bukan saat melakukan presensi tapi saat mengolah presensi dan penilaian yang diamati oleh guru saat dikelas.
Mengolah presensi bagian dari penilaian berkelanjutan dengan tujuan melihat tumbuh kembang dan kemampuan peserta didik. banyak dari kita tentunya mengenal software excel yang sering digunakan untuk memudahkan kita dalam merangkum seluruh proses tersebut namun beberapa dari para guru menjadikan sofware ini rumah kedua setelah kegiatan presensi manual maka kita menginputnya satu persatu sehingga kita memerlukan 2 proses yang sebenarnya bisa dilakukan dalam 1 kali.
Google sendiri telah memiliki pengolah data seperti excel yang kita kenal dengan spreadsheet cara kerja dan rumusnya sama persis, nah kemudahan yang diberikan salah satunya kita dapat mengakses dimanapun selama tempat tersebut memiliki jaringan seluler. Jika pada excel kita mengenal VBA untuk melakukan pengolahan data otomatis dan pada spreadsheet dengan fungsi yang sama yaitu AppsScript. Mari kita mulai merancang.
Langkah-langkah
- Buka google Drive-Kemudian siapkan google spreadsheet
- Buat sheet dengan nama Database_Siswa dan Admin
- Database_Siswa di isi dengan Nama siswa dan kelas dan pada sheet Admin isi dengan Nama dan pasword, Database_Siswa difungsikan untuk mengelompokan siswa sesuai kelasnya cukup Nama Siswa dan kelas saja nanti setelah sistem berjalan maka presensi otomatis akan terpisah sesuai kelasnya, sedangkan sheet Admin difungsikan untuk mengambil data login karena nanti akan menggunakan sistem login untuk keamanan
- selanjutnya pergi ke bagian extensions Pilih AppsScript
- Sekarang sudah ada di menu Apps Script, buat File baru-Pilih Html-kemudian berinama Index
- Selanjutnya Buka file Code.gs hapus seluruh data didalamnya gantikan dengan ini
- Lakukan Hal namun kali ini pada bagian Index.Html, hapus dan gantikan dengan kode dibawah ini
- Setelah itu jangan lupa save, langkah berikutnya Develoy (untuk pertama kali save kamu akan diminta untuk membuka beberapa ijin google terima keseluruhan ijin tersebut)
- Klik Develoy-New Develoyment-Klik Roda Gerigi dan pilih Web App-Pastikan di bagian Acsses diganti oleh Anyone
- setelah itu akan tampil Link App klik link tersebut Boom kamu sudah punya Presensi digital
- Tampilan Awalnya
- Tampilan dalamnya
/**
* SISTEM ADMINISTRASI GURU DIGITAL (VERSI LENGKAP + REKAP ABSEN)
*/
function doGet() {
return HtmlService.createTemplateFromFile('Index')
.evaluate()
.setTitle('Portal Guru Digital')
.addMetaTag('viewport', 'width=device-width, initial-scale=1')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
// 1. LOGIN SYSTEM
function checkLogin(username, password) {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Admin") || ss.insertSheet("Admin");
if (sheet.getLastRow() < 1) {
sheet.appendRow(["Nama", "Pasword"]);
sheet.appendRow(["admin", "12345"]);
}
var data = sheet.getDataRange().getValues();
for (var i = 1; i < data.length; i++) {
if (data[i][0].toString().trim() === username.trim() &&
data[i][1].toString().trim() === password.toString().trim()) {
return { success: true };
}
}
return { success: false, message: "Username atau Password salah!" };
} catch (e) { return { success: false, message: e.message }; }
}
// 2. DATABASE SISWA
function getDatabaseSiswa() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Database_Siswa");
if (!sheet) return { siswa: [], kelas: [] };
var data = sheet.getDataRange().getValues();
data.shift();
var daftarSiswa = data.filter(r => r[1] && r[2]).map(r => ({ nama: r[1].toString(), kelas: r[2].toString() }));
var daftarKelas = [...new Set(daftarSiswa.map(s => s.kelas))].sort();
return { siswa: daftarSiswa, kelas: daftarKelas };
}
// 3. PRESENSI
function simpanPresensiBulk(dataArray, kelas, mapel) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var namaSheet = "P_" + kelas.replace(/\s+/g, '_');
var sheet = ss.getSheetByName(namaSheet) || ss.insertSheet(namaSheet);
if (sheet.getLastColumn() === 0) { sheet.appendRow(["Nama Siswa"]); sheet.setFrozenColumns(1); }
var names = sheet.getLastRow() > 1 ? sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues().flat() : [];
dataArray.forEach(d => { if (!names.includes(d.nama) && d.nama !== "") sheet.appendRow([d.nama]); });
names = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues().flat();
var header = Utilities.formatDate(new Date(), "GMT+7", "dd/MM") + "\n" + mapel;
var col = sheet.getLastColumn() + 1;
sheet.getRange(1, col).setValue(header).setFontWeight("bold").setHorizontalAlignment("center");
var vals = names.map(n => {
var find = dataArray.find(d => d.nama === n);
return [find ? find.status : ""];
});
sheet.getRange(2, col, vals.length, 1).setValues(vals);
return true;
}
// 4. AGENDA DENGAN FOTO
function simpanAgenda(data) {
try {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Agenda") || ss.insertSheet("Agenda");
if (sheet.getLastRow() === 0) sheet.appendRow(["Tanggal", "Kelas", "Mapel", "Materi", "Foto"]);
var photoLink = "";
if (data.fileData) {
var folder = DriveApp.getFoldersByName("Agenda_Photos").hasNext() ? DriveApp.getFoldersByName("Agenda_Photos").next() : DriveApp.createFolder("Agenda_Photos");
var blob = Utilities.newBlob(Utilities.base64Decode(data.fileData.split(",")[1]), "image/jpeg", "IMG_" + new Date().getTime() + ".jpg");
photoLink = folder.createFile(blob).getUrl();
}
sheet.appendRow([new Date(), data.kelas, data.mapel, data.materi, photoLink]);
return true;
} catch (e) { return false; }
}
// 5. NILAI
function simpanNilaiBulk(dataArray, kelas, mapel, materi) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var namaSheet = "N_" + kelas.replace(/\s+/g, '_') + "_Nilai";
var sheet = ss.getSheetByName(namaSheet) || ss.insertSheet(namaSheet);
if (sheet.getLastColumn() === 0) { sheet.appendRow(["Nama Siswa"]); sheet.setFrozenColumns(1); }
var names = sheet.getLastRow() > 1 ? sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues().flat() : [];
dataArray.forEach(d => { if (!names.includes(d.nama) && d.nama !== "") sheet.appendRow([d.nama]); });
names = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues().flat();
var header = Utilities.formatDate(new Date(), "GMT+7", "dd/MM") + "\n" + mapel + "\n" + materi;
var col = sheet.getLastColumn() + 1;
sheet.getRange(1, col).setValue(header).setFontWeight("bold").setHorizontalAlignment("center");
var vals = names.map(n => {
var find = dataArray.find(d => d.nama === n);
return [find ? find.nilai : ""];
});
sheet.getRange(2, col, vals.length, 1).setValues(vals);
return true;
}
// 6. REKAP NILAI
function getDataNilai(kelas) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("N_" + kelas.replace(/\s+/g, '_') + "_Nilai");
if (!sheet) return { header: ["Data Kosong"], data: [] };
var val = sheet.getDataRange().getValues();
return { header: val[0], data: val.slice(1) };
}
// 7. REKAP ABSEN (FITUR BARU)
function getDataPresensi(kelas) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("P_" + kelas.replace(/\s+/g, '_'));
if (!sheet) return { header: ["Belum ada data"], data: [] };
var val = sheet.getDataRange().getValues();
var header = val[0];
var body = val.slice(1);
var newHeader = [...header, "H", "S", "I", "A"];
var newData = body.map(row => {
var h=0, s=0, i=0, a=0;
for (var c = 1; c < row.length; c++) {
var st = row[c].toString().toUpperCase();
if (st === 'H') h++; else if (st === 'S') s++; else if (st === 'I') i++; else if (st === 'A') a++;
}
return [...row, h, s, i, a];
});
return { header: newHeader, data: newData };
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Guru Digital</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
<style>
body { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); font-family: 'Poppins', sans-serif; min-height: 100vh; }
#loginScreen { position: fixed; inset: 0; display: flex; align-items: center; justify-content: center; z-index: 9999; background: inherit; }
#mainApp { display: none; padding: 20px; }
.card-menu { background: white; border-radius: 20px; transition: 0.3s; cursor: pointer; border: none; height: 100%; box-shadow: 0 4px 15px rgba(0,0,0,0.1); }
.card-menu:hover { transform: translateY(-5px); }
.view-section { display: none; background: white; border-radius: 25px; padding: 25px; box-shadow: 0 10px 30px rgba(0,0,0,0.2); }
#loadingOverlay { display:none; position:fixed; inset: 0; background:rgba(0,0,0,0.6); z-index:10000; align-items:center; justify-content:center; color: white; }
footer { background: rgba(255,255,255,0.1); border-top: 1px solid rgba(255,255,255,0.2); margin-top: 40px; }
@media print {
footer { display: none; }
nav { display: none; }
body { background: white; }
#mainMenu { display: none !important; }
.view-section { display: none !important; box-shadow: none; }
#printSection { display: block !important; background: white; padding: 20px; }
#printSection table { width: 100%; border-collapse: collapse; margin-top: 20px; }
#printSection table th, #printSection table td { border: 1px solid #000; padding: 8px; text-align: left; }
#printSection table th { background-color: #f0f0f0; font-weight: bold; }
#printSection h5 { margin: 20px 0 10px 0; font-weight: bold; }
}
</style>
<style>body { box-sizing: border-box; }</style>
<script src="https://cdn.tailwindcss.com/3.4.17" type="text/javascript"></script>
<script src="/_sdk/data_sdk.js" type="text/javascript"></script>
<script src="/_sdk/element_sdk.js" type="text/javascript"></script>
</head>
<body>
<div id="loadingOverlay">
<div class="text-center">
<div class="spinner-border mb-2"></div><br><b>Memproses...</b>
</div>
</div>
<div id="loginScreen">
<div class="card p-4 shadow-lg border-0" style="width: 380px; border-radius: 25px;">
<div class="text-center mb-4"><i class="bi bi-person-badge-fill text-primary display-1"></i>
<h4 class="fw-bold">Login Admin</h4>
</div><input type="text" id="userLogin" class="form-control mb-2" placeholder="Username">
<div class="input-group mb-4">
<input type="password" id="passLogin" class="form-control" placeholder="Password"> <button class="btn btn-outline-secondary" type="button" onclick="togglePassword()" style="border-color: #dee2e6;"> <i class="bi bi-eye" id="eyeIcon"></i> </button>
</div><button onclick="prosesLogin()" class="btn btn-primary w-100 fw-bold py-2">MASUK</button>
<div id="loginMsg" class="text-danger mt-2 small text-center"></div>
</div>
</div>
<div id="mainApp">
<nav class="d-flex justify-content-between align-items-center text-white mb-4">
<h4 class="fw-bold mb-0"><i class="bi bi-cpu"></i> Presensi Digital</h4><button class="btn btn-danger btn-sm px-3 shadow" onclick="prosesLogout()">LOGOUT</button>
</nav>
<div id="mainMenu" class="row g-3">
<div class="col-6 col-md-4" onclick="showView('vP')">
<div class="card card-menu p-3 text-center"><i class="bi bi-person-check fs-1 text-primary"></i>
<h6 class="mt-2 fw-bold">Presensi</h6>
</div>
</div>
<div class="col-6 col-md-4" onclick="showView('vA')">
<div class="card card-menu p-3 text-center"><i class="bi bi-journal-text fs-1 text-warning"></i>
<h6 class="mt-2 fw-bold">Agenda</h6>
</div>
</div>
<div class="col-6 col-md-4" onclick="showView('vN')">
<div class="card card-menu p-3 text-center"><i class="bi bi-pencil-square fs-1 text-success"></i>
<h6 class="mt-2 fw-bold">Input Nilai</h6>
</div>
</div>
<div class="col-6 col-md-6" onclick="showView('vCN')">
<div class="card card-menu p-3 text-center"><i class="bi bi-search fs-1 text-info"></i>
<h6 class="mt-2 fw-bold">Cek Nilai</h6>
</div>
</div>
<div class="col-6 col-md-6" onclick="showView('vCP')">
<div class="card card-menu p-3 text-center"><i class="bi bi-calendar-check fs-1 text-danger"></i>
<h6 class="mt-2 fw-bold">Cek Absen</h6>
</div>
</div>
</div>
<div id="vP" class="view-section shadow">
<div class="d-flex justify-content-between mb-3">
<h5 class="fw-bold text-primary">Input Presensi</h5><button class="btn-close" onclick="showView('mainMenu')"></button>
</div><select id="selKlsP" class="form-select mb-2" onchange="loadPresensi()"></select> <input type="text" id="mapelP" class="form-control mb-3" placeholder="Mata Pelajaran">
<div class="table-responsive">
<table class="table table-sm">
<tbody id="listP"></tbody>
</table>
</div><button onclick="simpanP()" class="btn btn-primary w-100 mt-3 fw-bold">SIMPAN PRESENSI</button>
</div>
<div id="vA" class="view-section shadow">
<div class="d-flex justify-content-between mb-3">
<h5 class="fw-bold text-warning">Input Agenda</h5><button class="btn-close" onclick="showView('mainMenu')"></button>
</div><select id="selKlsA" class="form-select mb-2"></select> <input type="text" id="mapelA" class="form-control mb-2" placeholder="Mapel"> <textarea id="materiA" class="form-control mb-3" rows="3" placeholder="Uraian Materi"></textarea> <input type="file" id="fileA" class="form-control mb-3" accept="image/*"> <button onclick="simpanA()" class="btn btn-warning w-100 text-white fw-bold">SIMPAN AGENDA</button>
</div>
<div id="vN" class="view-section shadow">
<div class="d-flex justify-content-between mb-3">
<h5 class="fw-bold text-success">Input Nilai</h5><button class="btn-close" onclick="showView('mainMenu')"></button>
</div><select id="selKlsN" class="form-select mb-2" onchange="loadSiswaN()"></select> <input type="text" id="mapelN" class="form-control mb-2" placeholder="Mapel"> <input type="text" id="tugasN" class="form-control mb-3" placeholder="Nama Tugas/UH/Tugas">
<div id="listSiswaN" style="max-height: 300px; overflow-y: auto;"></div><button onclick="simpanN()" class="btn btn-success w-100 mt-3 fw-bold">SIMPAN NILAI</button>
</div>
<div id="vCN" class="view-section shadow">
<div class="d-flex justify-content-between mb-3">
<h5 class="fw-bold text-info">Rekap Nilai</h5><button class="btn-close" onclick="showView('mainMenu')"></button>
</div>
<div class="input-group mb-3"><select id="selKlsCN" class="form-select"></select><button onclick="showCN()" class="btn btn-info text-white">Buka</button>
</div>
<div class="table-responsive">
<table class="table table-bordered table-sm small">
<thead id="hCN" class="table-light"></thead>
<tbody id="bCN"></tbody>
</table>
</div>
<div class="d-flex gap-2 mt-3">
<button onclick="cetakNilai()" class="btn btn-outline-info flex-grow-1 fw-bold"><i class="bi bi-file-pdf"></i> CETAK PDF</button>
</div>
</div>
<div id="vCP" class="view-section shadow">
<div class="d-flex justify-content-between mb-3">
<h5 class="fw-bold text-danger">Rekap Absensi</h5><button class="btn-close" onclick="showView('mainMenu')"></button>
</div>
<div class="input-group mb-3"><select id="selKlsCP" class="form-select"></select><button onclick="showCP()" class="btn btn-danger">Buka</button>
</div>
<div class="table-responsive">
<table class="table table-bordered table-sm small">
<thead id="hCP" class="table-light text-center"></thead>
<tbody id="bCP"></tbody>
</table>
</div>
<div class="d-flex gap-2 mt-3">
<button onclick="cetakAbsensi()" class="btn btn-outline-danger flex-grow-1 fw-bold"><i class="bi bi-file-pdf"></i> CETAK PDF</button>
</div>
</div>
<div id="printSection" style="display: none;"></div>
<footer class="text-center text-white py-3">
<p class="mb-0">© 2026 <strong> sejarah31.com</p>
</footer>
</div>
<script>
let dbSiswa = [];
function showLoading() { document.getElementById('loadingOverlay').style.display='flex'; }
function hideLoading() { document.getElementById('loadingOverlay').style.display='none'; }
function togglePassword() {
const passInput = document.getElementById('passLogin');
const eyeIcon = document.getElementById('eyeIcon');
if(passInput.type === 'password') {
passInput.type = 'text';
eyeIcon.classList.remove('bi-eye');
eyeIcon.classList.add('bi-eye-slash');
} else {
passInput.type = 'password';
eyeIcon.classList.remove('bi-eye-slash');
eyeIcon.classList.add('bi-eye');
}
}
function prosesLogin() {
const u = document.getElementById('userLogin').value;
const p = document.getElementById('passLogin').value;
if(!u || !p) return;
showLoading();
google.script.run.withSuccessHandler(res => {
hideLoading();
if(res.success) { document.getElementById('loginScreen').style.display='none'; document.getElementById('mainApp').style.display='block'; initApp(); }
else { document.getElementById('loginMsg').innerText = res.message; }
}).checkLogin(u, p);
}
function initApp() {
google.script.run.withSuccessHandler(res => {
dbSiswa = res.siswa;
const sels = document.querySelectorAll('#selKlsP, #selKlsA, #selKlsN, #selKlsCN, #selKlsCP');
sels.forEach(s => {
s.innerHTML = '<option value="">Pilih Kelas</option>';
res.kelas.forEach(k => s.innerHTML += `<option value="${k}">${k}</option>`);
});
}).getDatabaseSiswa();
}
function showView(id) {
document.getElementById('mainMenu').style.display = id === 'mainMenu' ? 'flex' : 'none';
document.querySelectorAll('.view-section').forEach(v => v.style.display = 'none');
if(id !== 'mainMenu') document.getElementById(id).style.display = 'block';
}
// --- PRESENSI ---
function loadPresensi() {
const k = document.getElementById('selKlsP').value;
const l = document.getElementById('listP'); l.innerHTML = "";
dbSiswa.filter(s => s.kelas === k).forEach(s => {
l.innerHTML += `<tr><td>${s.nama}</td><td><select class="form-select form-select-sm stsP" data-nama="${s.nama}"><option value="H">H</option><option value="S">S</option><option value="I">I</option><option value="A">A</option></select></td></tr>`;
});
}
function simpanP() {
const kls = document.getElementById('selKlsP').value;
const mapel = document.getElementById('mapelP').value;
if(!kls || !mapel) { alert('Pilih Kelas & Mapel!'); return; }
const d = []; document.querySelectorAll('.stsP').forEach(s => d.push({nama:s.dataset.nama, status:s.value}));
showLoading();
google.script.run.withSuccessHandler(() => { hideLoading(); alert('Berhasil!'); showView('mainMenu'); }).simpanPresensiBulk(d, kls, mapel);
}
// --- AGENDA ---
function simpanA() {
const f = document.getElementById('fileA').files[0];
const data = { kelas: document.getElementById('selKlsA').value, mapel: document.getElementById('mapelA').value, materi: document.getElementById('materiA').value };
if(!data.kelas || !data.mapel) { alert('Lengkapi data!'); return; }
showLoading();
if(f) {
const r = new FileReader();
r.onload = (e) => { data.fileData = e.target.result; google.script.run.withSuccessHandler(() => { hideLoading(); alert('Berhasil!'); showView('mainMenu'); }).simpanAgenda(data); };
r.readAsDataURL(f);
} else { google.script.run.withSuccessHandler(() => { hideLoading(); alert('Berhasil!'); showView('mainMenu'); }).simpanAgenda(data); }
}
// --- NILAI ---
function loadSiswaN() {
const k = document.getElementById('selKlsN').value;
const d = document.getElementById('listSiswaN'); d.innerHTML = "";
dbSiswa.filter(s => s.kelas === k).forEach(s => {
d.innerHTML += `<div class="d-flex justify-content-between mb-2 border-bottom pb-1"><span>${s.nama}</span><input type="number" class="form-control valN" style="width:75px" data-nama="${s.nama}" value="80"></div>`;
});
}
function simpanN() {
const kls = document.getElementById('selKlsN').value;
const mapel = document.getElementById('mapelN').value;
const tugas = document.getElementById('tugasN').value;
if(!kls || !mapel || !tugas) { alert('Lengkapi data!'); return; }
const d = []; document.querySelectorAll('.valN').forEach(i => d.push({nama:i.dataset.nama, nilai:i.value}));
showLoading();
google.script.run.withSuccessHandler(() => { hideLoading(); alert('Nilai Tersimpan!'); showView('mainMenu'); }).simpanNilaiBulk(d, kls, mapel, tugas);
}
// --- CEK NILAI ---
function showCN() {
const kls = document.getElementById('selKlsCN').value;
if(!kls) return;
showLoading();
google.script.run.withSuccessHandler(res => {
hideLoading();
let h = "<tr>", b = "";
res.header.forEach(v => h += `<th>${v.replace(/\n/g,'<br>')}</th>`);
res.data.forEach(r => { b += "<tr>"; r.forEach(v => b += `<td>${v}</td>`); b += "</tr>"; });
document.getElementById('hCN').innerHTML = h + "</tr>"; document.getElementById('bCN').innerHTML = b;
}).getDataNilai(kls);
}
// --- CEK ABSEN (TOTAL H/S/I/A) ---
function showCP() {
const kls = document.getElementById('selKlsCP').value;
if(!kls) return;
showLoading();
google.script.run.withSuccessHandler(res => {
hideLoading();
let h = "<tr>", b = "";
res.header.forEach((v, i) => {
let style = (i >= res.header.length - 4) ? 'class="bg-dark text-white text-center"' : '';
h += `<th ${style}>${v.replace(/\n/g,'<br>')}</th>`;
});
res.data.forEach(r => {
b += "<tr>";
r.forEach((v, i) => {
let style = (i === r.length - 1 && v > 0) ? "color:red; font-weight:bold" : "";
b += `<td class="text-center" style="${style}">${v}</td>`;
});
b += "</tr>";
});
document.getElementById('hCP').innerHTML = h + "</tr>"; document.getElementById('bCP').innerHTML = b;
}).getDataPresensi(kls);
}
function cetakNilai() {
const h = document.getElementById('hCN').innerHTML;
const b = document.getElementById('bCN').innerHTML;
const printSection = document.getElementById('printSection');
printSection.innerHTML = `<h5>Rekap Nilai</h5><table><thead>${h}</thead><tbody>${b}</tbody></table>`;
setTimeout(() => window.print(), 100);
}
function cetakAbsensi() {
const h = document.getElementById('hCP').innerHTML;
const b = document.getElementById('bCP').innerHTML;
const printSection = document.getElementById('printSection');
printSection.innerHTML = `<h5>Rekap Absensi</h5><table><thead>${h}</thead><tbody>${b}</tbody></table>`;
setTimeout(() => window.print(), 100);
}
function prosesLogout() {
showLoading();
document.getElementById('userLogin').value = "";
document.getElementById('passLogin').value = "";
document.getElementById('loginMsg').innerText = "";
document.getElementById('mainApp').style.display = 'none';
document.getElementById('loginScreen').style.display = 'flex';
showView('mainMenu');
setTimeout(() => {
hideLoading();
alert('Anda telah keluar.');
}, 500);
}
</script>
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'9d702049330440f7',t:'MTc3MjYxOTM5My4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
</html>
Selamat mencoba.










Posting Komentar untuk "Membuat Sistem Presensi Mandiri menggunakan Google Sheets dan Apps Script"