Last active
November 22, 2025 03:36
-
-
Save pritamsharma45/fa6551cac0bf6a6be2b2a4c02d6d5337 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment