Skip to main content

Search

Membuat Aplikasi Absensi Google Sheets dan App Script

Dalam aktivitas mengajar di kelas seorang guru tentu membutuhkan lembar daftar hadari untuk merekap kehadiran siswa pada mata pelajaran atau kuliah tersebut berikut ini mungkin bisa membantu para guru untuk lebih mudah dalam melakukan presensi dan rekapitulasi kehadiran siswa. 

Aplikasi Absensi akan membantu dalam melakukan presensi kehadiran kemudian dalam melakukan rekapitulasi kehadiran. berikut  Activity Diagram dari aplikasi absensi siswa oleh guru

%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CUserObject%20label%3D%22%22%20plantUmlData%3D%22%7B%26quot%3Bdata%26quot%3B%3A%26quot%3B%40startuml%5Cnstart%5Cn%3ALogin%3B%5Cn%3AInput%20Username%20dan%20Password%3B%5Cnif%20(Validasi%20Login)%20then%20(Sukses)%5Cn%20%20%20%20%3ATampilkan%20Halaman%20Home%3B%5Cn%20%20%20%20%3AInput%20Tanggal%3B%5Cn%20%20%20%20%3APilih%20Kelas%3B%5Cn%20%20%20%20%3APilih%20Mata%20Pelajaran%3B%5Cn%20%20%20%20%3ACek%20List%20Siswa%20yang%20Hadir%3B%5Cn%20%20%20%20%3ASimpan%20Data%20Kehadiran%3B%5Cn%20%20%20%20%3ATampilkan%20Pesan%20Sukses%3B%5Cnelse%20(Gagal)%5Cn%20%20%20%20%3ATampilkan%20Pesan%20Kesalahan%3B%5Cn%20%20%20%20%3AKembali%20ke%20Login%3B%5Cnendif%5Cnstop%5Cn%40enduml%5Cn%26quot%3B%2C%26quot%3Bformat%26quot%3B%3A%26quot%3Bsvg%26quot%3B%7D%22%20id%3D%222%22%3E%3CmxCell%20style%3D%22shape%3Dimage%3BnoLabel%3D1%3BverticalAlign%3Dtop%3Baspect%3Dfixed%3BimageAspect%3D0%3Bimage%3Ddata%3Aimage%2Fsvg%2Bxml%2CPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXMtYXNjaWkiIHN0YW5kYWxvbmU9Im5vIj8%2BPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiBjb250ZW50U3R5bGVUeXBlPSJ0ZXh0L2NzcyIgaGVpZ2h0PSI2MjJweCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSIgc3R5bGU9IndpZHRoOjQxMnB4O2hlaWdodDo2MjJweDtiYWNrZ3JvdW5kOiNGRkZGRkY7IiB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCA0MTIgNjIyIiB3aWR0aD0iNDEycHgiIHpvb21BbmRQYW49Im1hZ25pZnkiPjxkZWZzLz48Zz48ZWxsaXBzZSBjeD0iMjA1LjUiIGN5PSIyMCIgZmlsbD0iIzIyMjIyMiIgcng9IjEwIiByeT0iMTAiIHN0eWxlPSJzdHJva2U6IzIyMjIyMjtzdHJva2Utd2lkdGg6MS4wOyIvPjxyZWN0IGZpbGw9IiNGMUYxRjEiIGhlaWdodD0iMzIuODQzOCIgcng9IjEyLjUiIHJ5PSIxMi41IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIHdpZHRoPSI1MyIgeD0iMTc5IiB5PSI1MCIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjEyIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjMzIiB4PSIxODkiIHk9IjcxLjM0MzgiPkxvZ2luPC90ZXh0PjxyZWN0IGZpbGw9IiNGMUYxRjEiIGhlaWdodD0iMzIuODQzOCIgcng9IjEyLjUiIHJ5PSIxMi41IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIHdpZHRoPSIyMDIiIHg9IjEwNC41IiB5PSIxMDIuODQzOCIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjEyIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjE4MiIgeD0iMTE0LjUiIHk9IjEyNC4xODc1Ij5JbnB1dCBVc2VybmFtZSBkYW4gUGFzc3dvcmQ8L3RleHQ%2BPHBvbHlnb24gZmlsbD0iI0YxRjFGMSIgcG9pbnRzPSIxNjMuNSwxNTUuNjg3NSwyNDcuNSwxNTUuNjg3NSwyNTkuNSwxNjcuNjg3NSwyNDcuNSwxNzkuNjg3NSwxNjMuNSwxNzkuNjg3NSwxNTEuNSwxNjcuNjg3NSwxNjMuNSwxNTUuNjg3NSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7Ii8%2BPHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTEiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iODQiIHg9IjE2My41IiB5PSIxNzIuMTk5MiI%2BVmFsaWRhc2kgTG9naW48L3RleHQ%2BPHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTEiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMzYiIHg9IjExNS41IiB5PSIxNjYuMzEyNSI%2BU3Vrc2VzPC90ZXh0Pjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjExIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjMwIiB4PSIyNTkuNSIgeT0iMTY2LjMxMjUiPkdhZ2FsPC90ZXh0PjxyZWN0IGZpbGw9IiNGMUYxRjEiIGhlaWdodD0iMzIuODQzOCIgcng9IjEyLjUiIHJ5PSIxMi41IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIHdpZHRoPSIxNjQiIHg9IjIxIiB5PSIxODkuNjg3NSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjEyIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjE0NCIgeD0iMzEiIHk9IjIxMS4wMzEzIj5UYW1waWxrYW4gSGFsYW1hbiBIb21lPC90ZXh0PjxyZWN0IGZpbGw9IiNGMUYxRjEiIGhlaWdodD0iMzIuODQzOCIgcng9IjEyLjUiIHJ5PSIxMi41IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIHdpZHRoPSIxMDYiIHg9IjUwIiB5PSIyNDIuNTMxMyIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjEyIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9Ijg2IiB4PSI2MCIgeT0iMjYzLjg3NSI%2BSW5wdXQgVGFuZ2dhbDwvdGV4dD48cmVjdCBmaWxsPSIjRjFGMUYxIiBoZWlnaHQ9IjMyLjg0MzgiIHJ4PSIxMi41IiByeT0iMTIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iOTEiIHg9IjU3LjUiIHk9IjI5NS4zNzUiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMiIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSI3MSIgeD0iNjcuNSIgeT0iMzE2LjcxODgiPlBpbGloIEtlbGFzPC90ZXh0PjxyZWN0IGZpbGw9IiNGMUYxRjEiIGhlaWdodD0iMzIuODQzOCIgcng9IjEyLjUiIHJ5PSIxMi41IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjAuNTsiIHdpZHRoPSIxNTIiIHg9IjI3IiB5PSIzNDguMjE4OCIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjEyIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjEzMiIgeD0iMzciIHk9IjM2OS41NjI1Ij5QaWxpaCBNYXRhIFBlbGFqYXJhbjwvdGV4dD48cmVjdCBmaWxsPSIjRjFGMUYxIiBoZWlnaHQ9IjMyLjg0MzgiIHJ4PSIxMi41IiByeT0iMTIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMTg0IiB4PSIxMSIgeT0iNDAxLjA2MjUiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMiIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIxNjQiIHg9IjIxIiB5PSI0MjIuNDA2MyI%2BQ2VrIExpc3QgU2lzd2EgeWFuZyBIYWRpcjwvdGV4dD48cmVjdCBmaWxsPSIjRjFGMUYxIiBoZWlnaHQ9IjMyLjg0MzgiIHJ4PSIxMi41IiByeT0iMTIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMTYwIiB4PSIyMyIgeT0iNDUzLjkwNjMiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMiIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIxNDAiIHg9IjMzIiB5PSI0NzUuMjUiPlNpbXBhbiBEYXRhIEtlaGFkaXJhbjwvdGV4dD48cmVjdCBmaWxsPSIjRjFGMUYxIiBoZWlnaHQ9IjMyLjg0MzgiIHJ4PSIxMi41IiByeT0iMTIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMTY2IiB4PSIyMCIgeT0iNTA2Ljc1Ii8%2BPHRleHQgZmlsbD0iIzAwMDAwMCIgZm9udC1mYW1pbHk9InNhbnMtc2VyaWYiIGZvbnQtc2l6ZT0iMTIiIGxlbmd0aEFkanVzdD0ic3BhY2luZyIgdGV4dExlbmd0aD0iMTQ2IiB4PSIzMCIgeT0iNTI4LjA5MzgiPlRhbXBpbGthbiBQZXNhbiBTdWtzZXM8L3RleHQ%2BPHJlY3QgZmlsbD0iI0YxRjFGMSIgaGVpZ2h0PSIzMi44NDM4IiByeD0iMTIuNSIgcnk9IjEyLjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIgd2lkdGg9IjE4NiIgeD0iMjE1IiB5PSIxODkuNjg3NSIvPjx0ZXh0IGZpbGw9IiMwMDAwMDAiIGZvbnQtZmFtaWx5PSJzYW5zLXNlcmlmIiBmb250LXNpemU9IjEyIiBsZW5ndGhBZGp1c3Q9InNwYWNpbmciIHRleHRMZW5ndGg9IjE2NiIgeD0iMjI1IiB5PSIyMTEuMDMxMyI%2BVGFtcGlsa2FuIFBlc2FuIEtlc2FsYWhhbjwvdGV4dD48cmVjdCBmaWxsPSIjRjFGMUYxIiBoZWlnaHQ9IjMyLjg0MzgiIHJ4PSIxMi41IiByeT0iMTIuNSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDowLjU7IiB3aWR0aD0iMTIzIiB4PSIyNDYuNSIgeT0iMjQyLjUzMTMiLz48dGV4dCBmaWxsPSIjMDAwMDAwIiBmb250LWZhbWlseT0ic2Fucy1zZXJpZiIgZm9udC1zaXplPSIxMiIgbGVuZ3RoQWRqdXN0PSJzcGFjaW5nIiB0ZXh0TGVuZ3RoPSIxMDMiIHg9IjI1Ni41IiB5PSIyNjMuODc1Ij5LZW1iYWxpIGtlIExvZ2luPC90ZXh0Pjxwb2x5Z29uIGZpbGw9IiNGMUYxRjEiIHBvaW50cz0iMjA1LjUsNTQ1LjU5MzgsMjE3LjUsNTU3LjU5MzgsMjA1LjUsNTY5LjU5MzgsMTkzLjUsNTU3LjU5MzgsMjA1LjUsNTQ1LjU5MzgiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MC41OyIvPjxlbGxpcHNlIGN4PSIyMDUuNSIgY3k9IjYwMC41OTM4IiBmaWxsPSJub25lIiByeD0iMTEiIHJ5PSIxMSIgc3R5bGU9InN0cm9rZTojMjIyMjIyO3N0cm9rZS13aWR0aDoxLjA7Ii8%2BPGVsbGlwc2UgY3g9IjIwNS41IiBjeT0iNjAwLjU5MzgiIGZpbGw9IiMyMjIyMjIiIHJ4PSI2IiByeT0iNiIgc3R5bGU9InN0cm9rZTojMjIyMjIyO3N0cm9rZS13aWR0aDoxLjA7Ii8%2BPGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7IiB4MT0iMjA1LjUiIHgyPSIyMDUuNSIgeTE9IjMwIiB5Mj0iNTAiLz48cG9seWdvbiBmaWxsPSIjMTgxODE4IiBwb2ludHM9IjIwMS41LDQwLDIwNS41LDUwLDIwOS41LDQwLDIwNS41LDQ0IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiIHgxPSIyMDUuNSIgeDI9IjIwNS41IiB5MT0iODIuODQzOCIgeTI9IjEwMi44NDM4Ii8%2BPHBvbHlnb24gZmlsbD0iIzE4MTgxOCIgcG9pbnRzPSIyMDEuNSw5Mi44NDM4LDIwNS41LDEwMi44NDM4LDIwOS41LDkyLjg0MzgsMjA1LjUsOTYuODQzOCIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8%2BPGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7IiB4MT0iMTAzIiB4Mj0iMTAzIiB5MT0iMjIyLjUzMTMiIHkyPSIyNDIuNTMxMyIvPjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iOTksMjMyLjUzMTMsMTAzLDI0Mi41MzEzLDEwNywyMzIuNTMxMywxMDMsMjM2LjUzMTMiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MS4wOyIvPjxsaW5lIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MS4wOyIgeDE9IjEwMyIgeDI9IjEwMyIgeTE9IjI3NS4zNzUiIHkyPSIyOTUuMzc1Ii8%2BPHBvbHlnb24gZmlsbD0iIzE4MTgxOCIgcG9pbnRzPSI5OSwyODUuMzc1LDEwMywyOTUuMzc1LDEwNywyODUuMzc1LDEwMywyODkuMzc1IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiIHgxPSIxMDMiIHgyPSIxMDMiIHkxPSIzMjguMjE4OCIgeTI9IjM0OC4yMTg4Ii8%2BPHBvbHlnb24gZmlsbD0iIzE4MTgxOCIgcG9pbnRzPSI5OSwzMzguMjE4OCwxMDMsMzQ4LjIxODgsMTA3LDMzOC4yMTg4LDEwMywzNDIuMjE4OCIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8%2BPGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7IiB4MT0iMTAzIiB4Mj0iMTAzIiB5MT0iMzgxLjA2MjUiIHkyPSI0MDEuMDYyNSIvPjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iOTksMzkxLjA2MjUsMTAzLDQwMS4wNjI1LDEwNywzOTEuMDYyNSwxMDMsMzk1LjA2MjUiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MS4wOyIvPjxsaW5lIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MS4wOyIgeDE9IjEwMyIgeDI9IjEwMyIgeTE9IjQzMy45MDYzIiB5Mj0iNDUzLjkwNjMiLz48cG9seWdvbiBmaWxsPSIjMTgxODE4IiBwb2ludHM9Ijk5LDQ0My45MDYzLDEwMyw0NTMuOTA2MywxMDcsNDQzLjkwNjMsMTAzLDQ0Ny45MDYzIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiIHgxPSIxMDMiIHgyPSIxMDMiIHkxPSI0ODYuNzUiIHkyPSI1MDYuNzUiLz48cG9seWdvbiBmaWxsPSIjMTgxODE4IiBwb2ludHM9Ijk5LDQ5Ni43NSwxMDMsNTA2Ljc1LDEwNyw0OTYuNzUsMTAzLDUwMC43NSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8%2BPGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7IiB4MT0iMzA4IiB4Mj0iMzA4IiB5MT0iMjIyLjUzMTMiIHkyPSIyNDIuNTMxMyIvPjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iMzA0LDIzMi41MzEzLDMwOCwyNDIuNTMxMywzMTIsMjMyLjUzMTMsMzA4LDIzNi41MzEzIiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiIHgxPSIxNTEuNSIgeDI9IjEwMyIgeTE9IjE2Ny42ODc1IiB5Mj0iMTY3LjY4NzUiLz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiIHgxPSIxMDMiIHgyPSIxMDMiIHkxPSIxNjcuNjg3NSIgeTI9IjE4OS42ODc1Ii8%2BPHBvbHlnb24gZmlsbD0iIzE4MTgxOCIgcG9pbnRzPSI5OSwxNzkuNjg3NSwxMDMsMTg5LjY4NzUsMTA3LDE3OS42ODc1LDEwMywxODMuNjg3NSIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8%2BPGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7IiB4MT0iMjU5LjUiIHgyPSIzMDgiIHkxPSIxNjcuNjg3NSIgeTI9IjE2Ny42ODc1Ii8%2BPGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7IiB4MT0iMzA4IiB4Mj0iMzA4IiB5MT0iMTY3LjY4NzUiIHkyPSIxODkuNjg3NSIvPjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iMzA0LDE3OS42ODc1LDMwOCwxODkuNjg3NSwzMTIsMTc5LjY4NzUsMzA4LDE4My42ODc1IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiIHgxPSIxMDMiIHgyPSIxMDMiIHkxPSI1MzkuNTkzOCIgeTI9IjU1Ny41OTM4Ii8%2BPGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7IiB4MT0iMTAzIiB4Mj0iMTkzLjUiIHkxPSI1NTcuNTkzOCIgeTI9IjU1Ny41OTM4Ii8%2BPHBvbHlnb24gZmlsbD0iIzE4MTgxOCIgcG9pbnRzPSIxODMuNSw1NTMuNTkzOCwxOTMuNSw1NTcuNTkzOCwxODMuNSw1NjEuNTkzOCwxODcuNSw1NTcuNTkzOCIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8%2BPGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7IiB4MT0iMzA4IiB4Mj0iMzA4IiB5MT0iMjc1LjM3NSIgeTI9IjU1Ny41OTM4Ii8%2BPGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7IiB4MT0iMzA4IiB4Mj0iMjE3LjUiIHkxPSI1NTcuNTkzOCIgeTI9IjU1Ny41OTM4Ii8%2BPHBvbHlnb24gZmlsbD0iIzE4MTgxOCIgcG9pbnRzPSIyMjcuNSw1NTMuNTkzOCwyMTcuNSw1NTcuNTkzOCwyMjcuNSw1NjEuNTkzOCwyMjMuNSw1NTcuNTkzOCIgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7Ii8%2BPGxpbmUgc3R5bGU9InN0cm9rZTojMTgxODE4O3N0cm9rZS13aWR0aDoxLjA7IiB4MT0iMjA1LjUiIHgyPSIyMDUuNSIgeTE9IjEzNS42ODc1IiB5Mj0iMTU1LjY4NzUiLz48cG9seWdvbiBmaWxsPSIjMTgxODE4IiBwb2ludHM9IjIwMS41LDE0NS42ODc1LDIwNS41LDE1NS42ODc1LDIwOS41LDE0NS42ODc1LDIwNS41LDE0OS42ODc1IiBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiLz48bGluZSBzdHlsZT0ic3Ryb2tlOiMxODE4MTg7c3Ryb2tlLXdpZHRoOjEuMDsiIHgxPSIyMDUuNSIgeDI9IjIwNS41IiB5MT0iNTY5LjU5MzgiIHkyPSI1ODkuNTkzOCIvPjxwb2x5Z29uIGZpbGw9IiMxODE4MTgiIHBvaW50cz0iMjAxLjUsNTc5LjU5MzgsMjA1LjUsNTg5LjU5MzgsMjA5LjUsNTc5LjU5MzgsMjA1LjUsNTgzLjU5MzgiIHN0eWxlPSJzdHJva2U6IzE4MTgxODtzdHJva2Utd2lkdGg6MS4wOyIvPjwhLS1TUkM9W1JMM0hJaUgwMzdwVmh5WFotbWxqZXU5QUpvWnF6N3JhU3N0aXhoUGl6Wlp5VXJEUkpXSnBhQzFDOVpENDJ0OW5wTWFQOVJNa1VLZGhqVDJSU2F3OEoxdzlVZ1pVYmtuUjluVWd0WDc0R3VMLTUzTUxZSERMbXRMTXJqZ0hMTkQ2TjJOQzlkcjZHRHBjNGhkVG9UdFdaM0lFMjBWTUl2MjlFV3hHRnlXaDJnV3QtMUNQd1EwVVVBUUpRQTUxejBSd2lhbGN1b0tWXzIxbkRTbDdKVGxuajM1dHhNLW9kak53N2hqcjc5SWZVZTk1Z2xfVnhBbTdKRlRCN1NTRi1tSkRKQ1ZoRTdjdkUydEItV3EwXS0tPjwvZz48L3N2Zz4%3D%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22-160%22%20y%3D%22140%22%20width%3D%22412%22%20height%3D%22622%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2FUserObject%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E 

Lalu bagai mana cara Membuat Aplikasi Absensi ? anda bisa melakukan dengan mudah dengan google sheet untuk menampung data dan App script sebagai function dari aplikasi tersebut. 

Untuk membuatnya pertama yang harus dilakukan adalam membuat spreadsheet baru kemudian membuat bebera sheet untuk menampung data seperti di bawah ini

Data Guru




Data Siswa



Daftar Kelas



Mata Pelajaran



Absensi



Setelah membuat sheet seperti diata sekarang waktunya untuk menambahkran skrip code pada App Script langkah pertama tentu Buka App Script melalui menu Extensions > Apps Script lalu buat code script dibawah ini

Code.gs

function doGet(e) {
var userProperties = PropertiesService.getUserProperties();
var loggedIn = userProperties.getProperty('loggedIn');

if (loggedIn === 'true') {
if (e.parameter.page === 'riwayat') {
return HtmlService.createHtmlOutputFromFile('kehadiran_siswa');
}
return HtmlService.createHtmlOutputFromFile('home');
} else {
return HtmlService.createHtmlOutputFromFile('login');
}
}

function login(username, password) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data Guru'); // Ganti 'Data Guru' dengan nama lembar yang sesuai
var data = sheet.getRange('A2:C' + sheet.getLastRow()).getValues(); // Sesuaikan dengan range data guru

for (var i = 0; i < data.length; i++) {
if (data[i][0] === username && data[i][1] === password) {
var userProperties = PropertiesService.getUserProperties();
userProperties.setProperty('loggedIn', 'true');
userProperties.setProperty('loggedInUser', data[i][2]); // Simpan nama guru
return true;
}
}
return false;
}

function logout() {
var userProperties = PropertiesService.getUserProperties();
userProperties.deleteProperty('loggedIn');
return HtmlService.createHtmlOutputFromFile('login').getContent();
}

function kehadiran_siswa() {
return HtmlService.createHtmlOutputFromFile('kehadiran_siswa').getContent();
}

function riwayatMengajar() {
return HtmlService.createHtmlOutputFromFile('riwayat').getContent();
}

function getSiswaPage() {
return HtmlService.createHtmlOutputFromFile('siswa').getContent();
}

function getHomePage() {
return HtmlService.createHtmlOutputFromFile('home').getContent();
}

// Fungsi-fungsi untuk mendapatkan data siswa dan mata pelajaran, sesuaikan dengan struktur data yang ada
function getStudentData(page) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Absensi');
var values = sheet.getRange('A2:G' + sheet.getLastRow()).getValues();

var rowsPerPage = 10; // Sesuaikan dengan jumlah baris per halaman yang diinginkan
var startRow = (page - 1) * rowsPerPage;
var endRow = startRow + rowsPerPage;

var rowData = values.slice(startRow, endRow);

// Hitung total halaman berdasarkan total baris data
var totalRows = values.length;
var totalPages = Math.ceil(totalRows / rowsPerPage);

return { data: rowData, totalPages: totalPages };
}

function searchStudentData(query) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Absensi');
var values = sheet.getRange('A2:G' + sheet.getLastRow()).getValues();

var results = values.filter(function(row) {
return row.some(function(cell) {
return cell.toString().toLowerCase().indexOf(query.toLowerCase()) !== -1;
});
});

return { data: results };
}

function getStudentProfile(page) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data Siswa'); // Ganti 'Data Siswa' dengan nama lembar yang sesuai
var values = sheet.getRange('A2:D' + sheet.getLastRow()).getValues();

var rowsPerPage = 10; // Sesuaikan dengan jumlah baris per halaman yang diinginkan
var startRow = (page - 1) * rowsPerPage;
var endRow = startRow + rowsPerPage;

var rowData = values.slice(startRow, endRow);

// Hitung total halaman berdasarkan total baris data
var totalRows = values.length;
var totalPages = Math.ceil(totalRows / rowsPerPage);

return { data: rowData, totalPages: totalPages };
}

function getStudentSubjects(page) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Mata Pelajaran'); // Ganti 'Mata Pelajaran' dengan nama lembar yang sesuai
var values = sheet.getRange('A2:B' + sheet.getLastRow()).getValues();

var rowsPerPage = 10; // Sesuaikan dengan jumlah baris per halaman yang diinginkan
var startRow = (page - 1) * rowsPerPage;
var endRow = startRow + rowsPerPage;

var rowData = values.slice(startRow, endRow);

// Hitung total halaman berdasarkan total baris data
var totalRows = values.length;
var totalPages = Math.ceil(totalRows / rowsPerPage);

return { data: rowData, totalPages: totalPages };
}

function getClasses() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Daftar Kelas');
var data = sheet.getRange('A2:A' + sheet.getLastRow()).getValues();
return data.map(function(row) {
return row[0];
});
}


function getStudents(className) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data Siswa');
var data = sheet.getRange('A2:C' + sheet.getLastRow()).getValues();
return data.filter(function(row) {
return row[2] === className;
}).map(function(row) {
return { id: row[0], name: row[1] };
});
}

function saveAttendance(attendanceData) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Absensi");
var userProperties = PropertiesService.getUserProperties();
var teacher = userProperties.getProperty('loggedInUser');

attendanceData.forEach(function(record) {
var date = record.date;
var studentId = record.studentId;
var studentName = record.studentName;
var studentClass = record.class;
var subject = record.subject;
var status = record.status;
var reason = record.reason;

var existingRow = findRow(sheet, date, studentId, subject);
if (existingRow > 0) {
sheet.getRange(existingRow, 6).setValue(status); // Kolom Status Kehadiran
sheet.getRange(existingRow, 7).setValue(reason); // Kolom Alasan Tidak Hadir
sheet.getRange(existingRow, 8).setValue(teacher); // Kolom Nama Guru
} else {
sheet.appendRow([date, studentId, studentName, studentClass, subject, status, reason, teacher]);
}
});

return "Data absensi berhasil disimpan.";
}

function findRow(sheet, date, studentId, subject) {
var data = sheet.getRange('A2:H' + sheet.getLastRow()).getValues(); // Mengambil data dari baris 2

for (var i = 0; i < data.length; i++) {
if (data[i][0] === date && data[i][1] === studentId && data[i][4] === subject) {
return i + 2; // Kembalikan nomor baris (dibuat +2 karena dimulai dari baris 2)
}
}

return 0; // Kembalikan 0 jika tidak ditemukan
}


function getLoggedInUser() {
var userProperties = PropertiesService.getUserProperties();
return userProperties.getProperty('loggedInUser');
}

function getSubjects() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Mata Pelajaran'); // Pastikan nama sheet benar
var data = sheet.getRange('A2:A' + sheet.getLastRow()).getValues();
var subjects = data.map(function(row) {
return row[0];
});
return subjects;
}


function getTeachingHistory(subject, tanggal) {
try {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Absensi');
var dataRange = sheet.getDataRange();
var data = dataRange.getValues();
Logger.log("Data yang diambil: " + JSON.stringify(data)); // Log untuk melihat data yang diambil dari spreadsheet

var results = [];
var userProperties = PropertiesService.getUserProperties();
var loggedInUser = userProperties.getProperty('loggedInUser'); // Mendapatkan nama guru yang login
Logger.log("Nama guru yang login: " + loggedInUser);

for (var i = 1; i < data.length; i++) {
var dataTanggal = new Date(data[i][0]); // Ubah ke objek Date
var formattedDate = formatDate(dataTanggal); // Format tanggal untuk membandingkan
Logger.log("Membandingkan: " + formattedDate + " dengan " + tanggal + " dan " + data[i][4] + " dengan " + subject + " dan " + data[i][7] + " dengan " + loggedInUser);

if (data[i][4] === subject && formattedDate === tanggal && data[i][7] === loggedInUser) {
results.push({
tanggal: formattedDate,
nomorInduk: data[i][1],
namaSiswa: data[i][2],
kelas: data[i][3],
mataPelajaran: data[i][4],
statusKehadiran: data[i][5],
alasanTidakHadir: data[i][6],
namaGuru: data[i][7]
});
}
}

Logger.log("Hasil getTeachingHistory: " + JSON.stringify(results)); // Log untuk melihat hasil pencarian
return results;

} catch (error) {
Logger.log('Terjadi kesalahan: ' + error);
throw new Error('Terjadi kesalahan saat memuat data: ' + error);
}
}

function formatDate(date) {
return Utilities.formatDate(date, Session.getScriptTimeZone(), 'yyyy-MM-dd');
}

function getAttendanceReport(startDate, endDate, selectedClass) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Absensi');
var dataRange = sheet.getDataRange();
var data = dataRange.getValues();
var results = {};

for (var i = 1; i < data.length; i++) { // Mulai dari baris kedua, karena baris pertama adalah header
var tanggal = formatDate(data[i][0]);
var kelas = data[i][3];

if (tanggal >= startDate && tanggal <= endDate && kelas === selectedClass) {
var nomorInduk = data[i][1];
var namaSiswa = data[i][2];
var statusKehadiran = data[i][5];
var alasanTidakHadir = data[i][6];

if (!results[nomorInduk]) {
results[nomorInduk] = {
namaSiswa: namaSiswa,
hadir: 0,
ijin: 0,
alpha: 0,
sakit: 0
};
}

if (statusKehadiran === 'Hadir') {
results[nomorInduk].hadir++;
} else if (statusKehadiran === 'Ijin') {
results[nomorInduk].ijin++;
} else if (statusKehadiran === 'Tidak Hadir' && alasanTidakHadir === 'Alpha') {
results[nomorInduk].alpha++;
} else if (statusKehadiran === 'Tidak Hadir' && alasanTidakHadir === 'Sakit') {
results[nomorInduk].sakit++;
}
}
}

return results;
}

function toggleSelectAll(source) {
var checkboxes = document.querySelectorAll('.status-checkbox');
checkboxes.forEach(function(checkbox) {
checkbox.checked = source.checked;
var reasonSelect = document.getElementById("reason-" + checkbox.id.split("-")[1]);
if (source.checked) {
reasonSelect.value = "Hadir";
reasonSelect.disabled = true;
} else {
reasonSelect.disabled = false;
reasonSelect.value = "Alpha";
}
});
}


login.html 

<!DOCTYPE html>
<html>
<head>
<base target="_top">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(to right, #00C9FF, #92FE9D);
color: #333;
padding: 20px;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}

.login-container {
background: rgba(255, 255, 255, 0.1);
padding: 2rem;
border-radius: 10px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
width: 300px;
text-align: center;
}

.login-container h1 {
margin-bottom: 1.5rem;
color: black;
}

.login-container label {
display: block;
text-align: left;
margin-bottom: 0.5rem;
font-weight: bold;
color: black;
}

.login-container input[type="text"], .login-container input[type="password"] {
width: 100%;
padding: 0.5rem;
margin-bottom: 1rem;
border: none;
border-radius: 5px;
font-size: 1rem;
color: #000000;
}

.login-container input[type="text"]::placeholder, .login-container input[type="password"]::placeholder {
color: #999999;
}

.login-container input[type="submit"] {
background: #1c4c08;
border: none;
color: white;
padding: 0.75rem 1.5rem;
border-radius: 5px;
font-size: 1rem;
cursor: pointer;
transition: background 0.3s, transform 0.3s;
}

.login-container input[type="submit"]:hover {
background: #6aa84f;
transform: translateY(-2px);
}

.login-container input[type="submit"]:active {
transform: translateY(0);
}
</style>
<script>
function login(event) {
event.preventDefault();

var username = document.getElementById("username").value;
var password = document.getElementById("password").value;

google.script.run
.withSuccessHandler(function(success) {
if (success) {
loadHomePage();
} else {
alert("Username atau password salah!");
}
})
.login(username, password);
}

function loadHomePage() {
google.script.run.withSuccessHandler(function(htmlContent) {
document.open();
document.write(htmlContent);
document.close();
displayStudentData();
}).getHomePage();
}
</script>
</head>
<body>
<div class="login-container">
<h2>Aplikasi<br>Absensi Siswa</h2>
<h4>Login</h4>
<form id="loginForm" action="#">
<label for="username">Username:</label>
<input type="text" id="username" name="username" placeholder="Enter your username" required>
<label for="password">Password:</label>
<input type="password" id="password" name="password" placeholder="Enter your password" required>
<input type="submit" value="Login" onclick="login(event)">
</form>
</div>
</body>
</html>


home.html

<!DOCTYPE html>
<html>
<head>
<base target="_top">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(to right, #00C9FF, #92FE9D);
color: #333;
padding: 20px;
}

h1 {
text-align: center;
}

.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.form-group {
margin-bottom: 15px;
}

label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}

select, input[type="text"], input[type="date"], button {
width: 80%;
padding: 10px;
margin-top: 5px;
border: 1px solid #ddd;
border-radius: 4px;
}

button {
background: #0858cf;
color: white;
cursor: pointer;
transition: background 0.3s, transform 0.3s;
}

button:hover {
background: #4b58cc;
transform: translateY(-2px);
}

button:active {
transform: translateY(0);
}

table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}

table, th, td {
border: 1px solid #ddd;
}

th, td {
padding: 10px;
text-align: left;
}

.hidden {
display: none;
}
.navbar {
display: flex;
justify-content: center; /* Mengatur agar tombol berada di tengah */
align-items: center;
margin-bottom: 20px;
}
.logout-btn {
background-color: #dc3545;
margin-left:10px;
color: white;
padding: 10px 10px; /* Mengatur padding lebih kecil */
font-size: 14px; /* Mengatur ukuran font */
width:200px;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
.logout-btn:hover {
background-color: #c82333;
}

.history-btn {
background-color: #0AA966;
color: white;
padding: 10px 10px; /* Mengatur padding lebih kecil */
font-size: 14px; /* Mengatur ukuran font */
width:200px;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
.history-btn:hover {
background-color: #0AA960;
}

.laporan-btn {
background-color: #1762e3;
margin-left:10px;
color: white;
padding: 10px 10px; /* Mengatur padding lebih kecil */
font-size: 14px; /* Mengatur ukuran font */
width:200px;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
.laporan-btn:hover {
background-color: #1762e0;
}
.loading-bar {
display: none;
width: 100%;
height: 10px;
background: #ddd;
position: relative;
margin-top: 20px;
}

.loading-bar .progress {
width: 30%;
height: 100%;
background: #0858cf;
position: absolute;
transition: width 0.4s ease;
}

.loading-bar.active {
display: block;
}
</style>
<script>
var loggedInTeacher = ""; // Variabel global untuk menyimpan nama guru yang login

function fetchClasses() {
google.script.run.withSuccessHandler(function(classes) {
var classSelect = document.getElementById("classSelect");
classSelect.innerHTML = '<option value="">--Pilih Kelas--</option>';
classes.forEach(function(cls) {
var option = document.createElement("option");
option.value = cls;
option.textContent = cls;
classSelect.appendChild(option);
});
document.getElementById("classSection").classList.remove("hidden");
}).getClasses();
}

function fetchSubjects() {
var selectedClass = document.getElementById("classSelect").value;
google.script.run.withSuccessHandler(function(subjects) {
var subjectSelect = document.getElementById("subjectSelect");
subjectSelect.innerHTML = '<option value="">--Pilih Mata Pelajaran--</option>';
subjects.forEach(function(subj) {
var option = document.createElement("option");
option.value = subj;
option.textContent = subj;
subjectSelect.appendChild(option);
});
document.getElementById("subjectSection").classList.remove("hidden");
}).getSubjects(selectedClass);
}

function fetchStudents() {
var selectedClass = document.getElementById("classSelect").value;
google.script.run.withSuccessHandler(function(students) {
var tableBody = document.getElementById("studentsTableBody");
tableBody.innerHTML = '';
students.forEach(function(student, index) {
var row = document.createElement("tr");

var cellNo = document.createElement("td");
cellNo.textContent = index + 1;
row.appendChild(cellNo);

var cellId = document.createElement("td");
cellId.textContent = student.id;
row.appendChild(cellId);

var cellName = document.createElement("td");
cellName.textContent = student.name;
row.appendChild(cellName);

var cellStatus = document.createElement("td");
var checkBox = document.createElement("input");
checkBox.type = "checkbox";
checkBox.classList.add("status-checkbox");
checkBox.id = "status-" + student.id;
checkBox.onclick = function() {
var reasonSelect = document.getElementById("reason-" + student.id);
if (checkBox.checked) {
reasonSelect.value = "Hadir";
reasonSelect.disabled = true;
} else {
reasonSelect.disabled = false;
reasonSelect.value = "Alpha";
}
};
cellStatus.appendChild(checkBox);
row.appendChild(cellStatus);

var cellReason = document.createElement("td");
var reasonSelect = document.createElement("select");
reasonSelect.id = "reason-" + student.id;
reasonSelect.innerHTML = '<option value="Alpha">Alpha</option><option value="Ijin">Ijin</option><option value="Sakit">Sakit</option>';
cellReason.appendChild(reasonSelect);
row.appendChild(cellReason);

tableBody.appendChild(row);
});
document.getElementById("studentsSection").classList.remove("hidden");
}).getStudents(selectedClass);
}

function recordAttendance() {
var table = document.getElementById("studentsTableBody");
var rows = table.getElementsByTagName("tr");
var attendanceData = [];
var date = document.getElementById("attendanceDate").value;
var selectedClass = document.getElementById("classSelect").value;
var selectedSubject = document.getElementById("subjectSelect").value;

if (!date) {
alert("Mohon pilih tanggal kehadiran.");
return;
}

for (var i = 0; i < rows.length; i++) {
var cells = rows[i].getElementsByTagName("td");
var studentId = cells[1].textContent;
var studentName = cells[2].textContent;
var status = document.getElementById("status-" + studentId).checked ? "Hadir" : "Tidak Hadir";
var reason = status === "Hadir" ? "-" : document.getElementById("reason-" + studentId).value;
attendanceData.push({
date: date,
studentId: studentId,
studentName: studentName,
class: selectedClass,
subject: selectedSubject,
status: status,
reason: reason,
teacher: loggedInTeacher
});
}

showLoadingBar();

var totalRecords = attendanceData.length;
var savedRecords = 0;

function saveNextRecord() {
if (savedRecords < totalRecords) {
google.script.run.withSuccessHandler(function(response) {
savedRecords++;
var progress = Math.round((savedRecords / totalRecords) * 100);
updateLoadingBar(progress);

if (savedRecords === totalRecords) {
alert(response); // Tampilkan pesan balik dari server
resetForm(); // Reset form setelah berhasil simpan
hideLoadingBar();
} else {
saveNextRecord(); // Simpan record berikutnya
}
}).saveAttendance([attendanceData[savedRecords]]);
}
}

saveNextRecord();
}


function resetForm() {
document.getElementById("classSelect").value = "";
document.getElementById("subjectSelect").innerHTML = "";
document.getElementById("studentsTableBody").innerHTML = "";
// Tambahkan baris berikut untuk mengaktifkan kembali section yang tersembunyi
document.getElementById("classSection").classList.remove("hidden");
document.getElementById("subjectSection").classList.add("hidden");
document.getElementById("studentsSection").classList.add("hidden");
document.getElementById("attendanceDate").value = "";
}

function toggleSelectAll(source) {
var checkboxes = document.querySelectorAll('.status-checkbox');
checkboxes.forEach(function(checkbox) {
checkbox.checked = source.checked;
var reasonSelect = document.getElementById("reason-" + checkbox.id.split("-")[1]);
if (source.checked) {
reasonSelect.value = "Hadir";
reasonSelect.disabled = true;
} else {
reasonSelect.disabled = false;
reasonSelect.value = "Alpha";
}
});
}

function setLoggedInTeacher(teacherName) {
loggedInTeacher = teacherName; // Set nama guru yang login
document.getElementById("loggedInTeacherName").textContent = teacherName; // Perbarui elemen HTML dengan nama guru yang login
}

function logout() {
google.script.run.withSuccessHandler(function(htmlContent) {
document.open();
document.write(htmlContent);
document.close();
}).logout();
}
document.addEventListener('DOMContentLoaded', function() {
fetchClasses();
google.script.run.withSuccessHandler(setLoggedInTeacher).getLoggedInUser();
});

function riwayatMengajar() {
google.script.run.withSuccessHandler(function(htmlContent) {
document.open();
document.write(htmlContent);
document.close();
}).riwayatMengajar();
}

function kehadiran_siswa() {
google.script.run.withSuccessHandler(function(htmlContent) {
document.open();
document.write(htmlContent);
document.close();
}).kehadiran_siswa();
}

function showLoadingBar() {
document.getElementById("loadingBar").classList.add("active");
document.getElementById("loadingProgress").style.width = "0";
document.getElementById("loadingProgressText").textContent = "0%";
}

function updateLoadingBar(progress) {
var progressBar = document.getElementById("loadingProgress");
var progressText = document.getElementById("loadingProgressText");
progressBar.style.width = progress + "%";
progressText.textContent = progress + "%";
}

function hideLoadingBar() {
document.getElementById("loadingBar").classList.remove("active");
document.getElementById("loadingProgress").style.width = "0";
document.getElementById("loadingProgressText").textContent = "0%";
}


</script>
</head>
<body>
<div class="container">
<h2 style="text-align:center" >Aplikasi Absensi Siswa</h2>
<h3 style="text-align:center" >Aplikasi untuk pencatatan Kehadiran Siswa oleh Guru</h3>
<h4 style="text-align:center" id="loggedInTeacherName"></h4> <!-- Elemen untuk menampilkan nama guru yang login -->
<div class="loading-bar" id="loadingBar">
<div class="progress" id="loadingProgress"></div>
<div class="progress-text" id="loadingProgressText">0%</div>
</div>

<hr>
<div class="navbar">
<button class="history-btn" onclick="riwayatMengajar()">Riwayat Mengajar</button>
<button class="laporan-btn" onclick="kehadiran_siswa()">Kehadiran Siswa</button>
<button class="logout-btn" onclick="logout()">Logout</button>
</div>
<div class="form-group">
<label for="attendanceDate">Pilih Tanggal:</label>
<input style="width:77%" type="date" id="attendanceDate">
</div>

<div id="classSection" class="hidden">
<label for="classSelect">Pilih Kelas:</label>
<select id="classSelect" onchange="fetchSubjects()">
<option value="">--Pilih Kelas--</option>
</select>
</div>

<div id="subjectSection" class="hidden">
<label for="subjectSelect">Pilih Mata Pelajaran:</label>
<select id="subjectSelect" onchange="fetchStudents()">
<option value="">--Pilih Mata Pelajaran--</option>
</select>
</div>

<div id="studentsSection" class="hidden">
<h2>Daftar Siswa</h2>
<table>
<thead>
<tr>
<th>No</th>
<th>Nomor Induk</th>
<th>Nama Siswa</th>
<th>Status Kehadiran <input type="checkbox" onclick="toggleSelectAll(this)"></th>
<th>Alasan Tidak Hadir</th>
</tr>
</thead>
<tbody id="studentsTableBody">
</tbody>
</table>
<button onclick="recordAttendance()">Simpan Kehadiran</button>
</div>
</div>
</div>
</body>
</html>

riwayat.html

<!DOCTYPE html>
<html>
<head>
<base target="_top">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(to right, #00C9FF, #92FE9D);
color: #333;
padding: 20px;
}

h1 {
text-align: center;
}

.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.form-group {
margin-bottom: 15px;
}

label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}

select, input[type="text"], input[type="date"], button {
width: 100%;
padding: 10px;
margin-top: 5px;
border: 1px solid #ddd;
border-radius: 4px;
}

.logout-btn, .history-btn, .print-btn, .home-btn {
background-color: #dc3545;
color: white;
padding: 10px 10px;
font-size: 14px;
width: 150px;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
margin-left: 10px;
}

.history-btn {
background-color: #0AA966;
}

.print-btn {
background-color: #007BFF;
}

.home-btn {
background-color: #6C757D;
}

.logout-btn:hover, .history-btn:hover, .print-btn:hover, .home-btn:hover {
background-color: #c82333;
}

.history-btn:hover {
background-color: #0AA960;
}

.print-btn:hover {
background-color: #0069D9;
}

.home-btn:hover {
background-color: #5A6268;
}

table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}

table, th, td {
border: 1px solid #ddd;
}

th, td {
padding: 10px;
text-align: left;
}

.hidden {
display: none;
}

@media print {
.print-hide {
display: none;
}

.print-show {
display: block;
}
.history-btn, .print-btn, .home-btn {
display: none !important;
}
}
</style>
<script>
var loggedInTeacher = ""; // Variabel global untuk menyimpan nama guru yang login

function populateSubjects() {
google.script.run.withSuccessHandler(function(subjects) {
var select = document.getElementById('mataPelajaran');
subjects.forEach(function(subject) {
var option = document.createElement('option');
option.value = subject;
option.text = subject;
select.appendChild(option);
});
}).getSubjects();
}

function fetchTeachingHistory() {
var subject = document.getElementById('mataPelajaran').value;
var tanggal = document.getElementById('tanggal').value;

google.script.run.withSuccessHandler(function(data) {
var resultTable = document.getElementById('resultTable');
var infoSection = document.getElementById('infoSection');
resultTable.innerHTML = "";
infoSection.innerHTML = "";

var jumlahSiswaHadir = 0;
var jumlahSiswaAlpha = 0;
var jumlahSiswaIjin = 0;
var jumlahSiswaSakit = 0;

if (data && data.length > 0) {
data.forEach(function(row, index) {
var rowElement = document.createElement('tr');
rowElement.innerHTML = '<td>' + (index + 1) + '</td>' +
'<td>' + row.nomorInduk + '</td>' +
'<td>' + row.namaSiswa + '</td>' +
'<td>' + row.kelas + '</td>' +
'<td>' + row.mataPelajaran + '</td>' +
'<td>' + row.statusKehadiran + '</td>' +
'<td>' + row.alasanTidakHadir + '</td>';
// '<td>' + row.namaGuru + '</td>';
resultTable.appendChild(rowElement);

// Menghitung jumlah siswa berdasarkan status kehadiran
switch (row.alasanTidakHadir.toLowerCase()) {
case '-':
jumlahSiswaHadir++;
break;
case 'alpha':
jumlahSiswaAlpha++;
break;
case 'ijin':
jumlahSiswaIjin++;
break;
case 'sakit':
jumlahSiswaSakit++;
break;
default:
break;
}
});
} else {
resultTable.innerHTML = '<tr><td colspan="8">No data found</td></tr>';
}

// Menampilkan informasi jumlah siswa hadir, Alpha, ijin, dan sakit
var infoText = 'Jumlah siswa hadir: ' + jumlahSiswaHadir + '<br>' +
'Jumlah siswa Alpha: ' + jumlahSiswaAlpha + '<br>' +
'Jumlah siswa ijin: ' + jumlahSiswaIjin + '<br>' +
'Jumlah siswa sakit: ' + jumlahSiswaSakit;
infoSection.innerHTML = '<p>' + infoText + '</p>';
}).getTeachingHistory(subject, tanggal);
}

// Fungsi untuk mengatur format tanggal saat mencetak
function setupPrint() {
var tanggalInput = document.getElementById('tanggal');
var mataPelajaranInput = document.getElementById('mataPelajaran');
var formattedDate = formatDate(tanggalInput.value);
document.getElementById('tanggalCetak').textContent = formattedDate;
document.getElementById('mataPelajaranCetak').textContent = mataPelajaranInput.options[mataPelajaranInput.selectedIndex].text;
document.getElementById('tanggalCetak').classList.remove('hidden');
document.getElementById('mataPelajaranCetak').classList.remove('hidden');
}

// Fungsi untuk memformat tanggal ke format 'dd MMMM yyyy' (misal: 15 Juli 2024)
function formatDate(dateString) {
var date = new Date(dateString);
var options = { day: 'numeric', month: 'long', year: 'numeric' };
return date.toLocaleDateString('id-ID', options);
}

// Menghapus elemen setelah selesai mencetak
function clearPrintElements() {
document.getElementById('tanggalCetak').classList.add('hidden');
document.getElementById('mataPelajaranCetak').classList.add('hidden');
}

window.onload = function() {
populateSubjects();
window.addEventListener('afterprint', clearPrintElements);
};

function loadHomePage() {
google.script.run.withSuccessHandler(function(htmlContent) {
document.open();
document.write(htmlContent);
document.close();
}).getHomePage();
}

document.addEventListener('DOMContentLoaded', function() {
google.script.run.withSuccessHandler(setLoggedInTeacher).getLoggedInUser();
});
</script>
</head>
<body>
<div class="container">
<h1>Riwayat Mengajar</h1>
<h4 style="text-align:center" id="loggedInTeacherName"></h4> <!-- Elemen untuk menampilkan nama guru yang login -->
<div class="form-group">
<label for="tanggal">Tanggal:</label>
<input style="width:97.5%" type="date" id="tanggal" name="tanggal" class="print-hide">
<!-- Elemen untuk menampilkan tanggal dalam format cetak -->
<span id="tanggalCetak" class="hidden print-show"></span>
</div>
<div class="form-group">
<label for="mataPelajaran">Mata Pelajaran:</label>
<select id="mataPelajaran" class="print-hide">
<option value="" disabled selected>Pilih Mata Pelajaran</option>
</select>
<!-- Elemen untuk menampilkan mata pelajaran dalam format cetak -->
<span id="mataPelajaranCetak" class="hidden print-show"></span>
</div>
<button onclick="fetchTeachingHistory()" class="history-btn">Tampilkan Data</button>
<button onclick="setupPrint(); window.print()" class="print-btn">Cetak</button>
<button onclick="loadHomePage()" class="home-btn">Kembali ke Home</button>
<table>
<thead>
<tr>
<th>No</th>
<th>Nomor Induk</th>
<th>Nama Siswa</th>
<th>Kelas</th>
<th>Mata Pelajaran</th>
<th>Status Kehadiran</th>
<th>Alasan Tidak Hadir</th>
</tr>
</thead>
<tbody id="resultTable">
</tbody>
</table>
<div id="infoSection"></div>
</div>
</body>
</html>

kehadiran_siswa.html

<!DOCTYPE html>
<html>
<head>
<base target="_top">
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(to right, #00C9FF, #92FE9D);
color: #333;
padding: 20px;
}

h2 {
text-align: center;
}

.container {
max-width: 800px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

.form-group {
margin-bottom: 15px;
}

label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}

select, input[type="text"], input[type="date"], button {
width: 100%;
padding: 10px;
margin-top: 5px;
border: 1px solid #ddd;
border-radius: 4px;
}

.logout-btn, .history-btn, .print-btn, .home-btn {
background-color: #dc3545;
color: white;
padding: 10px 10px;
font-size: 14px;
width: 150px;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
margin-left: 10px;
}

.history-btn {
background-color: #0AA966;
}

.print-btn {
background-color: #007BFF;
}

.home-btn {
background-color: #6C757D;
}

.logout-btn:hover, .history-btn:hover, .print-btn:hover, .home-btn:hover {
background-color: #c82333;
}

.history-btn:hover {
background-color: #0AA960;
}

.print-btn:hover {
background-color: #0069D9;
}

.home-btn:hover {
background-color: #5A6268;
}

table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}

table, th, td {
border: 1px solid #ddd;
}

th, td {
padding: 10px;
text-align: left;
}

.hidden {
display: none;
}

@media print {
.print-hide {
display: none;
}

.print-show {
display: block;
}
.form-group{
display:none;
}
.history-btn, .print-btn, .home-btn {
display: none !important;
}
}
</style>
</head>
<body>
<div class="container">
<h2>Rekapitulasi Kehadiran Siswa</h2>
<div class="form-group">
<form id="attendanceForm">
<label for="startDate">Tanggal Mulai:</label>
<input type="date" id="startDate" name="startDate" required>
<label for="endDate">Tanggal Selesai:</label>
<input type="date" id="endDate" name="endDate" required>
<label for="classSelect">Pilih Kelas:</label>
<select id="classSelect" name="classSelect">
<option value="">--Pilih Kelas--</option>
</select>
<button onclick="loadAttendanceData()" class="history-btn">Tampilkan Data</button>
<button onclick="setupPrint();" class="print-btn">Cetak</button>
<button onclick="loadHomePage()" class="home-btn">Kembali ke Home</button>
</form>
</div>
<!-- Elemen untuk dicetak -->
<div id="printElements" class="hidden">
<p><strong>Tanggal:</strong> <span id="tanggalCetak"></span></p>
<p><strong>Kelas:</strong> <span id="kelasCetak"></span></p>
</div>
<table id="attendanceTable">
<thead>
<tr>
<th>No</th>
<th>Nomor Induk</th>
<th>Nama Siswa</th>
<th>Hadir</th>
<th>Ijin</th>
<th>Alpha</th>
<th>Sakit</th>
</tr>
</thead>
<tbody id="tableBody">
<!-- Data akan ditampilkan di sini -->
</tbody>
</table>
</div>
<script>
// Fungsi untuk menyimpan posisi gulir ke dalam localStorage
function saveScrollPosition() {
localStorage.setItem('scrollPosition', window.scrollY);
}

// Fungsi untuk mengambil dan mengatur posisi gulir
function setScrollPosition() {
const scrollPosition = localStorage.getItem('scrollPosition');
if (scrollPosition !== null) {
window.scrollTo(0, scrollPosition);
localStorage.removeItem('scrollPosition');
}
}

// Menyimpan posisi gulir saat halaman akan di-reload atau sebelum ditutup
window.addEventListener('beforeunload', saveScrollPosition);

// Mengatur posisi gulir setelah halaman dimuat
window.addEventListener('load', setScrollPosition);
// Memuat pilihan kelas saat halaman dimuat
window.onload = function() {
fetchClasses();
};

// Fungsi untuk mengambil daftar kelas dari Google Sheets
function fetchClasses() {
google.script.run.withSuccessHandler(function(classes) {
var classSelect = document.getElementById("classSelect");
classSelect.innerHTML = '<option value="">--Pilih Kelas--</option>';
classes.forEach(function(cls) {
var option = document.createElement("option");
option.value = cls;
option.textContent = cls;
classSelect.appendChild(option);
});
}).getClasses();
}

// Menangani pengiriman form untuk memuat data kehadiran
document.getElementById('attendanceForm').addEventListener('submit', function(event) {
event.preventDefault();
var startDate = document.getElementById('startDate').value;
var endDate = document.getElementById('endDate').value;
var selectedClass = document.getElementById('classSelect').value;
loadAttendanceData(startDate, endDate, selectedClass);
});

// Fungsi untuk memuat data kehadiran berdasarkan tanggal dan kelas yang dipilih
function loadAttendanceData(startDate, endDate, selectedClass) {
google.script.run.withSuccessHandler(function(data) {
var tableBody = document.getElementById('tableBody');
tableBody.innerHTML = "";

if (data) {
var index = 1;
Object.keys(data).forEach(function(nomorInduk) {
var row = data[nomorInduk];
var rowElement = document.createElement('tr');
rowElement.innerHTML = '<td>' + index + '</td>' +
'<td>' + nomorInduk + '</td>' +
'<td>' + row.namaSiswa + '</td>' +
'<td>' + (row.hadir || '') + '</td>' + // Memastikan field yang kosong tetap terisi
'<td>' + (row.ijin || '') + '</td>' +
'<td>' + (row.alpha || '') + '</td>' +
'<td>' + (row.sakit || '') + '</td>';
tableBody.appendChild(rowElement);
index++;
});
} else {
tableBody.innerHTML = '<tr><td colspan="7">No data found</td></tr>';
}
}).getAttendanceReport(startDate, endDate, selectedClass);
}

// Setup elemen untuk mencetak
function setupPrint() {
var startDate = document.getElementById('startDate').value;
var endDate = document.getElementById('endDate').value;
var selectedClass = document.getElementById('classSelect').value;

var formattedStartDate = formatDate(startDate);
var formattedEndDate = formatDate(endDate);

document.getElementById('tanggalCetak').textContent = formattedStartDate + ' - ' + formattedEndDate;
document.getElementById('kelasCetak').textContent = selectedClass;

// Menunjukkan elemen cetak
document.getElementById('printElements').classList.remove('hidden');

// Menambahkan delay untuk memastikan elemen terlihat saat dicetak
setTimeout(function() {
window.print();
}, 500);
}

// Fungsi untuk memformat tanggal ke format 'dd MMMM yyyy' (misal: 15 Juli 2024)
function formatDate(dateString) {
var date = new Date(dateString);
var options = { day: 'numeric', month: 'long', year: 'numeric' };
return date.toLocaleDateString('id-ID', options);
}

// Setelah mencetak, sembunyikan elemen cetak
function clearPrintElements() {
document.getElementById('printElements').classList.add('hidden');
}

// Menghapus elemen setelah selesai mencetak
window.addEventListener('afterprint', clearPrintElements);

// Fungsi untuk kembali ke halaman utama
function loadHomePage() {
google.script.run.withSuccessHandler(function(htmlContent) {
document.open();
document.write(htmlContent);
document.close();
}).getHomePage();
}
</script>
</body>
</html>

Selanjutnya setealh semua script dimasukkan klik menu deploy > New Deployment >kemudian pilih tipe deploy WebApp isi deskripsi pilih tipe hak akses kemudian setelah selesai pilih deploy 


dan sekarang anda bisa buka link webApp yang sudah anda buat.