https://docs.google.com/spreadsheets/d/1lHt2WYLBWoBpq_XhjXQEwQYxzjEwIWObRymCBigsySc/edit?gid=0#gid=0
Code.gs
| const DATA_ENTRY_SHEET_NAME = "Sheet1"; |
| const TIME_STAMP_COLUMN_NAME = "Timestamp"; |
| const FOLDER_ID = ""; |
| const FILE_LINK_COLUMN_NAME = "FileLink"; |
| const UPLOADED_FILE_NAME_COLUMN = "UploadedFileName"; |
| const FORM_FILE_INPUT_NAME = "theFile"; |
| function doPost(e) { |
| try { |
| const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName( |
| DATA_ENTRY_SHEET_NAME |
| ); |
| if (!sheet) { |
| throw new Error(`Sheet '${DATA_ENTRY_SHEET_NAME}' not found`); |
| } |
| const formData = e.postData.contents ? JSON.parse(e.postData.contents) : {}; |
| // Handle file upload if present |
| let fileInfo = null; |
| if (formData.fileData) { |
| fileInfo = saveFile(formData.fileData); |
| delete formData.fileData; // Remove file data from form data |
| } |
| // Prepare data for sheet |
| const rowData = { |
| ...formData, |
| [TIME_STAMP_COLUMN_NAME]: new Date().toISOString(), |
| }; |
| if (fileInfo) { |
| rowData[FILE_LINK_COLUMN_NAME] = fileInfo.url; |
| rowData[UPLOADED_FILE_NAME_COLUMN] = fileInfo.name; |
| } |
| appendToGoogleSheet(rowData, sheet); |
| return ContentService.createTextOutput( |
| JSON.stringify({ |
| status: "success", |
| message: "Data submitted successfully", |
| }) |
| ).setMimeType(ContentService.MimeType.JSON); |
| } catch (error) { |
| console.error(error); |
| return ContentService.createTextOutput( |
| JSON.stringify({ |
| status: "error", |
| message: error.toString(), |
| }) |
| ).setMimeType(ContentService.MimeType.JSON); |
| } |
| } |
| /** |
| * Saves a file to Google Drive |
| */ |
| function saveFile(fileData) { |
| try { |
| const blob = Utilities.newBlob( |
| Utilities.base64Decode(fileData.data), |
| fileData.mimeType, |
| fileData.fileName |
| ); |
| const folder = DriveApp.getFolderById(FOLDER_ID); |
| const file = folder.createFile(blob); |
| file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW); |
| return { |
| url: `https://drive.google.com/uc?export=view&id=${file.getId()}`, |
| name: fileData.fileName, |
| }; |
| } catch (error) { |
| console.error("File upload error:", error); |
| throw new Error("Failed to upload file: " + error.toString()); |
| } |
| } |
| /** |
| * Appends data to the Google Sheet |
| */ |
| function appendToGoogleSheet(data, sheet) { |
| const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0]; |
| // If sheet is empty, create headers |
| if (headers.length === 0 || headers[0] === "") { |
| const newHeaders = Object.keys(data); |
| sheet.getRange(1, 1, 1, newHeaders.length).setValues([newHeaders]); |
| headers = newHeaders; |
| } |
| // Map data to header columns |
| const rowData = headers.map((header) => data[header] || ""); |
| sheet.appendRow(rowData); |
| } |
Index.html
| <!DOCTYPE html> |
| <html> |
| <head> |
| <link |
| rel="stylesheet" |
| href="https://cdn.jsdelivr.net/npm/bulma@0.9.4/css/bulma.min.css" |
| /> |
| <title>Data Entry Form with File Upload</title> |
| </head> |
| <body> |
| <section class="hero is-primary is-bold"> |
| <div class="hero-body"> |
| <div class="container"> |
| <h1 class="title">Data Entry Form</h1> |
| </div> |
| </div> |
| </section> |
| <form id="form" class="container m-4 pl-4"> |
| <div class="field"> |
| <label class="label">Client Name</label> |
| <div class="control"> |
| <input |
| class="input" |
| type="text" |
| placeholder="Your Client Name" |
| name="Client Name" |
| /> |
| </div> |
| </div> |
| <div class="field"> |
| <label class="label">Email</label> |
| <div class="control"> |
| <input |
| class="input" |
| type="email" |
| placeholder="Your Email" |
| name="Email" |
| /> |
| </div> |
| </div> |
| <div class="field"> |
| <label class="label">Password</label> |
| <div class="control"> |
| <input |
| class="input" |
| type="password" |
| placeholder="Your Password" |
| name="Password" |
| /> |
| </div> |
| </div> |
| <div class="field"> |
| <label class="label">Date of Birth</label> |
| <div class="control"> |
| <input |
| class="input" |
| type="date" |
| placeholder="Your Date of Birth" |
| name="DOB" |
| /> |
| </div> |
| </div> |
| <div class="field"> |
| <label class="label">Gender</label> |
| <div class="control"> |
| <label class="radio"> |
| <input type="radio" name="Gender" value="male" /> Male |
| </label> |
| <label class="radio"> |
| <input type="radio" name="Gender" value="female" /> Female |
| </label> |
| </div> |
| </div> |
| <div class="field"> |
| <label class="label">Upload Document (Optional)</label> |
| <div class="control"> |
| <div class="file has-name is-fullwidth"> |
| <label class="file-label"> |
| <input |
| class="file-input" |
| type="file" |
| name="theFile" |
| id="fileInput" |
| accept="*/*" |
| /> |
| <span class="file-cta"> |
| <span class="file-icon"> |
| <i class="fas fa-upload"></i> |
| </span> |
| <span class="file-label"> Choose a file… </span> |
| </span> |
| <span class="file-name" id="fileNameDisplay"> |
| No file selected |
| </span> |
| </label> |
| </div> |
| </div> |
| </div> |
| <input type="hidden" name="filename" id="actualFilename" /> |
| <div class="field"> |
| <label class="label">Agree to Terms</label> |
| <div class="control"> |
| <label class="checkbox"> |
| <input type="checkbox" name="Agree To Terms" value="yes" /> I agree |
| to the terms and conditions |
| </label> |
| </div> |
| </div> |
| <div class="field"> |
| <label class="label">Additional Information</label> |
| <div class="control"> |
| <textarea |
| class="textarea" |
| placeholder="Any additional information" |
| name="Notes" |
| ></textarea> |
| </div> |
| </div> |
| <div class="field is-grouped"> |
| <div class="control"> |
| <button class="button is-primary" type="submit" id="submit-button"> |
| Sign Up |
| </button> |
| </div> |
| <div class="control"> |
| <button |
| class="button is-danger" |
| type="button" |
| onclick="document.getElementById('form').reset(); document.getElementById('fileNameDisplay').textContent = 'No file selected';" |
| > |
| Cancel |
| </button> |
| </div> |
| </div> |
| </form> |
| <div |
| id="message" |
| style=" |
| display: none; |
| margin: 20px; |
| padding: 10px; |
| border-radius: 4px; |
| font-weight: bold; |
| " |
| ></div> |
| <script> |
| const form = document.getElementById("form"); |
| const submitButton = document.getElementById("submit-button"); |
| const messageDiv = document.getElementById("message"); |
| const fileInput = document.getElementById("fileInput"); |
| const fileNameDisplay = document.getElementById("fileNameDisplay"); |
| // Update displayed filename on file selection |
| fileInput.addEventListener("change", function () { |
| if (this.files && this.files.length > 0) { |
| fileNameDisplay.textContent = this.files[0].name; |
| } else { |
| fileNameDisplay.textContent = "No file selected"; |
| } |
| }); |
| // Function to handle file upload |
| async function uploadFile(file) { |
| return new Promise((resolve, reject) => { |
| const fr = new FileReader(); |
| fr.onload = (e) => { |
| const data = e.target.result.split(","); |
| const obj = { |
| fileName: file.name, |
| mimeType: data[0].match(/:(\w.+);/)[1], |
| data: data[1], |
| }; |
| resolve(obj); |
| }; |
| fr.onerror = reject; |
| fr.readAsDataURL(file); |
| }); |
| } |
| form.addEventListener("submit", async function (e) { |
| e.preventDefault(); |
| messageDiv.textContent = "Submitting..."; |
| messageDiv.style.display = "block"; |
| messageDiv.style.backgroundColor = "beige"; |
| messageDiv.style.color = "black"; |
| submitButton.disabled = true; |
| submitButton.classList.add("is-loading"); |
| try { |
| const formData = new FormData(this); |
| const formDataObj = {}; |
| // Convert FormData to object |
| for (let [key, value] of formData.entries()) { |
| formDataObj[key] = value; |
| } |
| // Handle file upload if a file is selected |
| if (fileInput.files.length > 0) { |
| const fileObj = await uploadFile(fileInput.files[0]); |
| formDataObj.fileData = fileObj; // Add file data to form data |
| } |
| // Submit form data |
| const scriptURL = |
| "https://script.google.com/macros/s/AKfycbxXnyn7h1yxqy3RZtlaGvmDjrqnzF-TdqlF8conEb_GT8iiWS_8n9UmrOCJqJaAl3K_/exec"; |
| const response = await fetch(scriptURL, { |
| redirect: "follow", |
| method: "POST", |
| body: JSON.stringify(formDataObj), |
| headers: { |
| "Content-Type": "text/plain;charset=utf-8", |
| }, |
| }); |
| const data = await response.json(); |
| if (data.status === "success") { |
| messageDiv.textContent = |
| data.message || "Data submitted successfully!"; |
| messageDiv.style.backgroundColor = "#48c78e"; |
| messageDiv.style.color = "white"; |
| form.reset(); |
| fileNameDisplay.textContent = "No file selected"; |
| } else { |
| throw new Error(data.message || "Submission failed"); |
| } |
| } catch (error) { |
| console.error("Error:", error); |
| messageDiv.textContent = "Error: " + error.message; |
| messageDiv.style.backgroundColor = "#f14668"; |
| messageDiv.style.color = "white"; |
| } finally { |
| submitButton.disabled = false; |
| submitButton.classList.remove("is-loading"); |
| setTimeout(() => { |
| messageDiv.textContent = ""; |
| messageDiv.style.display = "none"; |
| }, 4000); |
| } |
| }); |
| // Enhance cancel button to reset file input display |
| const cancelButton = form.querySelector("button.is-danger"); |
| cancelButton.addEventListener("click", function () { |
| form.reset(); |
| fileNameDisplay.textContent = "No file selected"; |
| messageDiv.style.display = "none"; |
| }); |
| </script> |
| </body> |
| </html> https://sites.google.com/view/latihanfajar1/script1 https://docs.google.com/spreadsheets/d/1raiOwkd3I2lXtUrNKISa5G6lRQjsDHaASyQv3bxcHZI/edit?gid=0#gid=0 https://script.google.com/u/0/home/projects/1m8sMC-RgNH0TV8AHuS5Yn2UEbJ5QWSn7sfqMZW0vwRQP7S8p_0iv1GjP/edit file:///Users/fajarbaskoro030474/Downloads/indexform.html |



Tidak ada komentar:
Posting Komentar