Skip to content

Instantly share code, notes, and snippets.

@pritamsharma45
Last active November 22, 2025 03:36
Show Gist options
  • Select an option

  • Save pritamsharma45/fa6551cac0bf6a6be2b2a4c02d6d5337 to your computer and use it in GitHub Desktop.

Select an option

Save pritamsharma45/fa6551cac0bf6a6be2b2a4c02d6d5337 to your computer and use it in GitHub Desktop.
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);
}
<!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