Gscript code to send dummy parameters to google spreadsheet - javascript

I am trying to send the dummy values using Gscript code to my google spreadsheet.
Code:
function doGet(e) {
Logger.log( JSON.stringify(e) ); // view parameters
var result = 'Ok'; // assume success
if (e.parameter == 'undefined')
{
result = 'No Parameters';
}
else {
var sheet_id = 'google sheet ID /d<ID>/edit'; //
Spreadsheet ID
var sheet = SpreadsheetApp.openById(sheet_id).getActiveSheet();
var newRow = sheet.getLastRow() + 1;
var rowData = [];
rowData[0] = new Date(); //
Timestamp in column A
for (var param in e.parameter) {
Logger.log('In for loop, param=' + param);
var value = stripQuotes(e.parameter[param]);
Logger.log(param + ':' + e.parameter[param]);
switch (param) {
case 'tempC': //Parameter
rowData[1] = value; //Value in column B
result = 'Written on column B';
break;
case 'tempF': //Parameter
rowData[2] = value; //Value in column B
result = 'Written on column C';
break;
case 'humiD': //Parameter
rowData[3] = value; //Value in column C
result += ' ,Written on column D';
break;
default:
result = "unsupported parameter";
}
}
Logger.log(JSON.stringify(rowData));
// Write new row below
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
// Return result of operation
return ContentService.createTextOutput(result);
}
/**
* Remove leading and trailing single or double quotes
*/
function stripQuotes( value ) {
return value.replace(/^["']|['"]$/g, "");
}
//-----------------------------------------------
// End of file
//-----------------------------------------------
I am new with this work and whenever I am using script id URL to post the dummy data to google spreadsheet
like below:
https://script.google.com/macros/s/<*GScript ID>/exec?tempC=1&tempF=2&humiD=3
then the error of unsupported parameters shown at my execution screen and even Logger. logs show "undefined" message.
If someone has worked with this kind of issue before please share your advice will be a great much help.

Related

Replace dots with commas in google app script

i need help raplacing dots with commas with this script;
function doPost(e) {
//Return if null
if( e == undefined ) {
console.log("no data");
return HtmlService.createHtmlOutput("need data");
}
//Parse the JSON data
var event = JSON.parse(e.postData.contents);
var data = event.data;
var price = event.data;
var at = event.data;
//Get the last row without data
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = Math.max(sheet.getLastRow(),1);
var column = sheet.getRange("C1:C");
var columnn = sheet.getRange("E1:E");
sheet.insertRowAfter(lastRow);
//Insert the data into the sheet
sheet.getRange(lastRow + 1, 1).setValue(event.price);
sheet.getRange(lastRow + 1, 2).setValue(event.at);
column.setNumberFormat("#");
columnn.setNumberFormat("#");
SpreadsheetApp.flush();
return HtmlService.createHtmlOutput("post request received");
}
price and at is coming as eg:347.7100 but i need it as 347,7100
Thanks!
Ciao you could try replace function like:
function doPost(e) {
//Return if null
if( e == undefined ) {
console.log("no data");
return HtmlService.createHtmlOutput("need data");
}
//Parse the JSON data
var event = JSON.parse(e.postData.contents);
var data = event.data;
var price = event.data.replace('.', ',');
var at = event.data.replace('.', ',');
//Get the last row without data
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = Math.max(sheet.getLastRow(),1);
var column = sheet.getRange("C1:C");
var columnn = sheet.getRange("E1:E");
sheet.insertRowAfter(lastRow);
//Insert the data into the sheet
sheet.getRange(lastRow + 1, 1).setValue(event.price);
sheet.getRange(lastRow + 1, 2).setValue(event.at);
column.setNumberFormat("#");
columnn.setNumberFormat("#");
SpreadsheetApp.flush();
return HtmlService.createHtmlOutput("post request received");
}
Note: replace works only with string. If at and/or price are not strings, you have to parse before apply replace like:
...
var price = String(event.data).replace('.', ',');
var at = String(event.data).replace('.', ',');
...

How to send multiple html form to different google sheet in the same file/database? I have a google sheet which have 3 sheets in total

I have a google sheet which have 3 sheets, and I have 3 html form in total. Html don't run from google app script.
Here's the code I have to send from html from to google sheet. But it only can send to one sheet, I would to send to another sheet. It's a javascript for google app script, it's a .cs file. The code is from here https://medium.com/#dmccoy/how-to-submit-an-html-form-to-google-sheets-without-google-forms-b833952cc175
// original gist: https://gist.github.com/willpatera/ee41ae374d3c9839c2d6
function doGet(e){
return handleResponse(e);
}
// Enter sheet name where data is to be written below
var SHEET_NAME = "Sheet1";
var SCRIPT_PROP = PropertiesService.getScriptProperties(); // new property service
function handleResponse(e) {
// shortly after my original solution Google announced the LockService[1]
// this prevents concurrent access overwritting data
// [1] http://googleappsdeveloper.blogspot.co.uk/2011/10/concurrency-and-google-apps-script.html
// we want a public lock, one that locks for all invocations
var lock = LockService.getPublicLock();
lock.waitLock(30000); // wait 30 seconds before conceding defeat.
try {
// next set where we write the data - you could write to multiple/alternate destinations
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
// we'll assume header is in row 1 but you can override with header_row in GET/POST data
var headRow = e.parameter.header_row || 1;
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var nextRow = sheet.getLastRow()+1; // get next row
var row = [];
// loop through the header columns
for (i in headers){
if (headers[i] == "Timestamp"){ // special case if you include a 'Timestamp' column
row.push(new Date());
} else { // else use header name to get data
row.push(e.parameter[headers[i]]);
}
}
// more efficient to set values as [][] array than individually
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "row": nextRow}))
.setMimeType(ContentService.MimeType.JSON);
} catch(e){
// if error return this
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": e}))
.setMimeType(ContentService.MimeType.JSON);
} finally { //release lock
lock.releaseLock();
}
}
function setup() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
SCRIPT_PROP.setProperty("key", doc.getId());
}
I don't understand this part. I try to add in more variable and PropertiesService. And I can't get the result.
// Enter sheet name where data is to be written below
var SHEET_NAME = "Sheet1";
var SCRIPT_PROP = PropertiesService.getScriptProperties(); // new property service
try {
// next set where we write the data - you could write to multiple/alternate destinations
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
function setup() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
SCRIPT_PROP.setProperty("key", doc.getId());
}
Here is the solution for your question. https://www.youtube.com/watch?v=V4JMjmwHPEg
I have made a tutorial on youtube you can check the link in the description of youtube for source code.
You have to create duplicate functions for every sheets you have in spreadsheet. Check below code which you need to add in spreadsheet .gs file. for further information you can check the youtube link provided.
// See front-end example at: http://codepen.io/notarazi/pen/yMqyXX
// Usage
// 1. Enter sheet name where data is to be written below
//var SHEET_NAME;
// 2. Run > setup
//
// 3. Publish > Deploy as web app
// - enter Project Version name and click 'Save New Version'
// - set security level and enable service (most likely execute as 'me' and access 'anyone, even anonymously)
//
// 4. Copy the 'Current web app URL' and post this in your form/script action
//
// 5. Insert column names on your destination sheet matching the parameter names of the data you are passing in (exactly matching case)
var SCRIPT_PROP = PropertiesService.getScriptProperties(); // new property service
// If you don't want to expose either GET or POST methods you can comment out the appropriate function
function doGet(e){
return handleResponse(e);
}
function doPost(e){
return handleResponse(e);
}
function handleResponse(e) {
// shortly after my original solution Google announced the LockService[1]
// this prevents concurrent access overwritting data
// [1] http://googleappsdeveloper.blogspot.co.uk/2011/10/concurrency-and-google-apps-script.html
// we want a public lock, one that locks for all invocations
var lock = LockService.getPublicLock();
lock.waitLock(30000); // wait 30 seconds before conceding defeat.
//Sheet1
try {
var action = e.parameter.action;
if (action == 'create') {
return create(e);
}
else if (action == 'retrieve') {
return retrieve(e);
}
else if (action == 'update') {
return update(e);
}
else if (action == 'delete') {
return del(e);
}
else if (action == 'findRowId'){
return findRowId(e.parameter.findstr);
}
} catch(e){
// if error return this
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": e}))
.setMimeType(ContentService.MimeType.JSON);
} finally { //release lock
lock.releaseLock();
}
//Sheet2
try {
var action = e.parameter.action;
if (action == 'create_1') {
return create_1(e);
}
else if (action == 'retrieve_1') {
return retrieve_1(e);
}
else if (action == 'update_1') {
return update_1(e);
}
else if (action == 'delete_1') {
return del_1(e);
}
else if (action == 'findRowId'){
return findRowId(e.parameter.findstr);
}
} catch(e){
// if error return this
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": e}))
.setMimeType(ContentService.MimeType.JSON);
} finally { //release lock
lock.releaseLock();
}
}
function getDataArr(headers, e){
var row = [];
// loop through the header columns
for (i in headers){
var d= new Date();
if (headers[i] == "tid"){ // special case if you include a unix Timestamp column
row.push(d.getTime());
}else if (headers[i] == "Timestamp"){ // special case if you include a 'Timestamp' column
row.push(new Date());
} else { // else use header name to get data
row.push(e.parameter[headers[i]]);
}
}
return row;
}
function create0(e){
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "row": 99}))
.setMimeType(ContentService.MimeType.JSON);
}
function findRowId(data) {
var SHEET_NAME = "Published Online";
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
//var column = sheet.getRange(column + ":" + column); // like A:A
var column = sheet.getRange(1,1,sheet.getLastRow(),1);
var values = column.getValues();
var data1=Number(data);
var row = 0;
var result = 0;
while ( values[row] && values[row][0] !== data ) {
row++;
}
if (values[row][0] === data)
result= row+1;
else
result = -1;
//result += data1;
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "values": result}))
.setMimeType(ContentService.MimeType.JSON);
}
function findInColumn(data) {
var SHEET_NAME = "Sheet1";
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
//var column = sheet.getRange(column + ":" + column); // like A:A
var column = sheet.getRange(1,1,sheet.getLastRow(),1);
var values = column.getValues();
//data=1490461629269;
var testdata = Number(data);
var row = 0;
while ( values[row] && values[row][0] !== testdata ) {
row++;
}
if (values[row][0] === testdata)
return row+1;
else
return -1;
// return ContentService
// .createTextOutput(JSON.stringify({"result":"success", "values": row}))
// .setMimeType(ContentService.MimeType.JSON);
}
function findInColumn_s2(data) {
var SHEET_NAME = "Sheet2";
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
//var column = sheet.getRange(column + ":" + column); // like A:A
var column = sheet.getRange(1,1,sheet.getLastRow(),1);
var values = column.getValues();
//data=1490461629269;
var testdata = Number(data);
var row = 0;
while ( values[row] && values[row][0] !== testdata ) {
row++;
}
if (values[row][0] === testdata)
return row+1;
else
return -1;
// return ContentService
// .createTextOutput(JSON.stringify({"result":"success", "values": row}))
// .setMimeType(ContentService.MimeType.JSON);
}
function findInRow(data) {
var SHEET_NAME = "Published Online";
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var rows = sheet.getDataRange.getValues();
for (var r=0; r<rows.length; r++) {
if ( rows[r].join("#").indexOf(data) !== -1 ) {
return r+1;
}
}
return -1;
}
/***********************************************************************************************************************************************************************************/
//SHEET 1 CREATE
function create(e) {
var SHEET_NAME = e.parameter.sheet_name || 'Sheet1';
// next set where we write the data - you could write to multiple/alternate destinations
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
// we'll assume header is in row 1 but you can override with header_row in GET/POST data
var headRow = e.parameter.header_row || 1;
var numColumns = sheet.getLastColumn();
var headers = sheet.getRange(1, 1, 1, numColumns).getValues()[0];
var nextRow = sheet.getLastRow()+1; // get next row
var row = getDataArr(headers, e);
// more efficient to set values as [][] array than individually
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "row": nextRow}))
.setMimeType(ContentService.MimeType.JSON);
}
//SHEET 1 RETRIEVE
function retrieve(e) {
var SHEET_NAME = e.parameter.sheet_name || 'Sheet1';
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
var numRows = sheet.getLastRow();
var numColumns = sheet.getLastColumn();
var range = sheet.getRange(1, 1, numRows, numColumns);
var values = range.getValues();
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "values": values}))
.setMimeType(ContentService.MimeType.JSON);
}
//SHEET 1 UPDATE
function update(e) {
var SHEET_NAME = e.parameter.sheet_name || 'Sheet1';
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
var numColumns = sheet.getLastColumn();
var rowId = findInColumn(e.parameter.tid);
var headers = sheet.getRange(1, 1, 1, numColumns).getValues()[0];
var row = getDataArr(headers, e);
//var rowId = e.parameter.rowId;
var tid= row[0];
// more efficient to set values as [][] array than individually
sheet.getRange(rowId, 1, 1, numColumns).setValues([row]);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "tid": tid}))
.setMimeType(ContentService.MimeType.JSON);
}
//SHEET 1 DELETE
function del(e) {
var SHEET_NAME = e.parameter.sheet_name || 'Sheet1';
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
var rowId = findInColumn(e.parameter.tid);
sheet.deleteRow(rowId);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "rowId": rowId}))
.setMimeType(ContentService.MimeType.JSON);
}
/***********************************************************************************************************************************************************************************/
/***********************************************************************************************************************************************************************************/
//SHEET 2 CREATE
function create_1(e) {
var SHEET_NAME = e.parameter.sheet_name || 'Sheet2';
// next set where we write the data - you could write to multiple/alternate destinations
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
// we'll assume header is in row 1 but you can override with header_row in GET/POST data
var headRow = e.parameter.header_row || 1;
var numColumns = sheet.getLastColumn();
var headers = sheet.getRange(1, 1, 1, numColumns).getValues()[0];
var nextRow = sheet.getLastRow()+1; // get next row
var row = getDataArr(headers, e);
// more efficient to set values as [][] array than individually
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "row": nextRow}))
.setMimeType(ContentService.MimeType.JSON);
}
//SHEET 2 RETRIEVE
function retrieve_1(e) {
var SHEET_NAME = e.parameter.sheet_name || 'Sheet2';
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
var numRows = sheet.getLastRow();
var numColumns = sheet.getLastColumn();
var range = sheet.getRange(1, 1, numRows, numColumns);
var values = range.getValues();
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "values": values}))
.setMimeType(ContentService.MimeType.JSON);
}
//SHEET 2 UPDATE
function update_1(e) {
var SHEET_NAME = e.parameter.sheet_name || 'Sheet2';
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
var numColumns = sheet.getLastColumn();
var rowId = findInColumn_s2(e.parameter.tid);
var headers = sheet.getRange(1, 1, 1, numColumns).getValues()[0];
var row = getDataArr(headers, e);
//var rowId = e.parameter.rowId;
var tid= row[0];
// more efficient to set values as [][] array than individually
sheet.getRange(rowId, 1, 1, numColumns).setValues([row]);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "tid": tid}))
.setMimeType(ContentService.MimeType.JSON);
}
//SHEET 2 DELETE
function del_1(e) {
var SHEET_NAME = e.parameter.sheet_name || 'Sheet2';
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
var rowId = findInColumn_s2(e.parameter.tid);
sheet.deleteRow(rowId);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "rowId": rowId}))
.setMimeType(ContentService.MimeType.JSON);
}
/***********************************************************************************************************************************************************************************/
//SETUP
function setup() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
SCRIPT_PROP.setProperty("key", doc.getId());
}
For getting the sheet that you exactly want, you can set another parameter in the Request parameters e.parameters. In each of your forms add a key/value pair defining the name of where you want the form to be submitted. For example:
For the first sheet
sheetName=Sheet1
For the second sheet
sheetName=Sheet2
If you are using a Get Request the URL would look like this:
https://script.google.com/a/your-domain/macros/s/your-id/exec?sheetName=Sheet1.
Then, you would only need to pass that value to the .getSheetByName() like this:
var sheet = doc.getSheetByName(e.parameters.sheetName);

How do I update specific rows in Google Spreadsheets using Reactjs?

What needs to happen is that from my React web app there's this form and data inputted should be sent to Google Spreadsheet.
Is there away to avoid using Timestamp when inserting new data in the spreadsheet?
How do I update a SPECIFIC row?
For example, i have Joe and I need to update his number to 456
| NAME | NUMBER |
|-------|---------|
|Joe |123 |
|Brian |420 |
|Raine |143 |
How do I do this coming from the web app?
I've tried this but still no luck
https://mashe.hawksey.info/2018/02/google-apps-script-patterns-conditionally-updating-rows-of-google-sheet-data-by-reading-and-writing-data-once/
This is from the web app with some code in the componentDidMount()
This code is used to the form data and to prevent the page from redirecting to the App script link. Basically it stays on the page and even reloads the form.
componentDidMount() {
console.log("Contact form submission handler loaded successfully.");
// bind to the submit event of our form
var forms = document.querySelectorAll("form.gform");
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener("submit", handleFormSubmit, false);
}
//document.addEventListener("DOMContentLoaded", loaded, false);
function validateHuman(honeypot) {
if (honeypot) { //if hidden form filled up
console.log("Robot Detected!");
return true;
} else {
console.log("Welcome Human!");
}
}
// get all data in form and return object
function getFormData(form) {
var elements = form.elements;
var honeypot;
var fields = Object.keys(elements).filter(function (k) {
if (elements[k].name === "honeypot") {
honeypot = elements[k].value;
return false;
}
return true;
}).map(function (k) {
if (elements[k].name !== undefined) {
return elements[k].name;
// special case for Edge's html collection
} else if (elements[k].length > 0) {
return elements[k].item(0).name;
}
}).filter(function (item, pos, self) {
return self.indexOf(item) === pos && item;
});
var formData = {};
fields.forEach(function (name) {
var element = elements[name];
// singular form elements just have one value
formData[name] = element.value;
// when our element has multiple items, get their values
if (element.length) {
var data = [];
for (var i = 0; i < element.length; i++) {
var item = element.item(i);
if (item.checked || item.selected) {
data.push(item.value);
}
}
formData[name] = data.join(', ');
}
});
// add form-specific values into the data
formData.formDataNameOrder = JSON.stringify(fields);
formData.formGoogleSheetName = form.dataset.sheet || "responses"; // default sheet name
//formData.formGoogleSend = form.dataset.email || ""; // no email by default
console.log(formData);
return { data: formData, honeypot };
}
function handleFormSubmit(event) { // handles form submit without any jquery
event.preventDefault(); // we are submitting via xhr below
var form = event.target;
var formData = getFormData(form);
var data = formData.data;
// If a honeypot field is filled, assume it was done so by a spam bot.
if (formData.honeypot) {
return false;
}
disableAllButtons(form);
var url = form.action;
var xhr = new XMLHttpRequest();
xhr.open('POST', url);
// xhr.withCredentials = true;
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function () {
console.log(xhr.status, xhr.statusText);
console.log(xhr.responseText);
form.reset();
return;
};
// url encode form data for sending as post data
var encoded = Object.keys(data).map(function (k) {
return encodeURIComponent(k) + "=" + encodeURIComponent(data[k]);
}).join('&');
xhr.send(encoded);
}
function disableAllButtons(form) {
var buttons = form.querySelectorAll("button");
for (var i = 0; i > buttons.length; i++) {
buttons[i].disabled = true;
}
}
}
This is the snippet form in the web app
<form className="gform" method="POST"
action="GOOGLE APP SCRIPT">
<div className="row Late-body-container">
<div className="col-6">
<select name="Message" className="form-control reason-text" id="selectLateReason" onClick={this.checkOption} onChange={this.loaded}>
<option value="--">--</option>
<option value="Sick Leave">Sick Leave</option>
<option value="Emergency Leave">Emergency Leave</option>
<option value="Family Affairs">Family Affairs</option>
<option value="To travel">To travel</option>
<option value="Other reasons">Other reasons</option>
</select>
</div>
<button type="submit" className="btn btn-send" id="btnSubmit" value="Submit" >Send</button>
</div>
</form>
and then finally this is the Google app script code
/******************************************************************************
* This tutorial is based on the work of Martin Hawksey twitter.com/mhawksey *
* But has been simplified and cleaned up to make it more beginner friendly *
* All credit still goes to Martin and any issues/complaints/questions to me. *
******************************************************************************/
// if you want to store your email server-side (hidden), uncomment the next line
// var TO_ADDRESS = "example#email.net";
// spit out all the keys/values from the form in HTML for email
// uses an array of keys if provided or the object to determine field order
function formatMailBody(obj, order) {
var result = "";
if (!order) {
order = Object.keys(obj);
}
// loop over all keys in the ordered form data
for (var idx in order) {
var key = order[idx];
result += "<h4 style='text-transform: capitalize; margin-bottom: 0'>" + key + "</h4><div>" + sanitizeInput(obj[key]) + "</div>";
// for every key, concatenate an `<h4 />`/`<div />` pairing of the key name and its value,
// and append it to the `result` string created at the start.
}
return result; // once the looping is done, `result` will be one long string to put in the email body
}
// sanitize content from the user - trust no one
// ref: https://developers.google.com/apps-script/reference/html/html-output#appendUntrusted(String)
function sanitizeInput(rawInput) {
var placeholder = HtmlService.createHtmlOutput(" ");
placeholder.appendUntrusted(rawInput);
return placeholder.getContent();
}
function doPost(e) {
try {
Logger.log(e); // the Google Script version of console.log see: Class Logger
record_data(e);
// shorter name for form data
var mailData = e.parameters;
// names and order of form elements (if set)
var orderParameter = e.parameters.formDataNameOrder;
var dataOrder;
if (orderParameter) {
dataOrder = JSON.parse(orderParameter);
}
// determine recepient of the email
// if you have your email uncommented above, it uses that `TO_ADDRESS`
// otherwise, it defaults to the email provided by the form's data attribute
var sendEmailTo = (typeof TO_ADDRESS !== "undefined") ? TO_ADDRESS : mailData.formGoogleSendEmail;
// send email if to address is set
if (sendEmailTo) {
MailApp.sendEmail({
to: String(sendEmailTo),
subject: "Contact form submitted",
// replyTo: String(mailData.email), // This is optional and reliant on your form actually collecting a field named `email`
htmlBody: formatMailBody(mailData, dataOrder)
});
}
return ContentService // return json success results
.createTextOutput(
JSON.stringify({"result":"success",
"data": JSON.stringify(e.parameters) }))
.setMimeType(ContentService.MimeType.JSON);
} catch(error) { // if error return this
Logger.log(error);
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": error}))
.setMimeType(ContentService.MimeType.JSON);
}
}
/**
* record_data inserts the data received from the html form submission
* e is the data received from the POST
*/
function record_data(e) {
var lock = LockService.getDocumentLock();
lock.waitLock(30000); // hold off up to 30 sec to avoid concurrent writing
try {
Logger.log(JSON.stringify(e)); // log the POST data in case we need to debug it
// select the 'responses' sheet by default
var doc = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = e.parameters.formGoogleSheetName || "responses";
var sheet = doc.getSheetByName(sheetName);
var oldHeader = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var newHeader = oldHeader.slice();
var fieldsFromForm = getDataColumns(e.parameters);
var row = [new Date()]; // first element in the row should always be a timestamp
// loop through the header columns
for (var i = 1; i < oldHeader.length; i++) { // start at 1 to avoid Timestamp column
var field = oldHeader[i];
var output = getFieldFromData(field, e.parameters);
row.push(output);
// mark as stored by removing from form fields
var formIndex = fieldsFromForm.indexOf(field);
if (formIndex > -1) {
fieldsFromForm.splice(formIndex, 1);
}
}
// set any new fields in our form
for (var i = 0; i < fieldsFromForm.length; i++) {
var field = fieldsFromForm[i];
var output = getFieldFromData(field, e.parameters);
row.push(output);
newHeader.push(field);
}
// more efficient to set values as [][] array than individually
var nextRow = sheet.getLastRow() + 1; // get next row
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// update header row with any new data
if (newHeader.length > oldHeader.length) {
sheet.getRange(1, 1, 1, newHeader.length).setValues([newHeader]);
}
}
catch(error) {
Logger.log(error);
}
finally {
lock.releaseLock();
return;
}
}
function getDataColumns(data) {
return Object.keys(data).filter(function(column) {
return !(column === 'formDataNameOrder' || column === 'formGoogleSheetName' || column === 'formGoogleSendEmail' || column === 'honeypot');
});
}
function getFieldFromData(field, data) {
var values = data[field] || '';
var output = values.join ? values.join(', ') : values;
return output;
}
As mentioned earlier
I have Joe and I need to update his number to 456
| NAME | NUMBER |
|-------|---------|
|Joe |123 |
|Brian |420 |
|Raine |143 |
so the Expected result should be that
| NAME | NUMBER |
|-------|---------|
|Joe |456 |
|Brian |420 |
|Raine |143 |
Additional note:
The code works but when I insert new data
I can't get rid of the Timestamp. How do I get rid of it?
I'm dividing this answer in two parts:
1. Get rid of the Timestamp
As you see in your Google Appscript code:
var row = [new Date()]; // first element in the row should always be a timestamp
You just have to remove the new Date() function at leave it as an empty array declaration:
var row = []; //There is no first element yet.
Right after this there is a for loop whose index is starting from 1 to avoid the Timestamp, but since we have removed it there is no need to start at 1, so we have to change it.
for (var i = 0; i < oldHeader.length; i++) { // Now we start at 0 instead of 1
var field = oldHeader[i];
var output = getFieldFromData(field, e.parameters);
row.push(output);
....
2. Updating a cell depending on the condition
Since you already know the Name's condition (Joe) to update the Number, we just have to compare the values of each cell in A with the String 'Joe':
function updateCell() {
var doc = SpreadsheetApp.getActiveSpreadsheet(); //this line is not necessary if you just paste this code in yours
var names = doc.getRange("A2:A").getValues(); //We store all the names from A2 to the last one
var newValue = '456';
for (var n = 2; n < names.length + 2; n++){ //We start at 2 since A1 and B1 are the headers of the table
if (names[n - 2] == 'Joe'){ //But the array's first position is 0, so we deduct 2 form n.
doc.getRange("B" + (n)).setValue(newValue);
}
}
}
Result:

Google Sheets Email Daily Report based on cell values

Is there a way to only display rows that are blank in column F and email them.
Trying to get all rows that don't have equipment ordered and send them in a email daily.
I'm using this script that uses SheetConverter.
Here is what my sheet looks like. Here is what my email looks like.
function convSheetAndEmail(rng, email, subj)
{
var HTML = SheetConverter.convertRange2html(rng);
MailApp.sendEmail(email, subj, '', {htmlBody : HTML});
}
function doGet()
{
var dataRange = SpreadsheetApp.getActiveSpreadsheet().getDataRange();
var emailUser = '****#gmail.com';
var subject = 'Test Email';
convSheetAndEmail(dataRange, emailUser, subject);
}
Edit
Do you mean like this #Yash, I keep getting error cannot find getsheet in object
function convSheetAndEmail(rng, email, subj)
{
var HTML = SheetConverter.convertRange2html(rng);
MailApp.sendEmail(email, subj, '', {htmlBody : HTML});
}
function doGet()
{
var data = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
for (i in data) {
if (data[i][5] === ""){
var labels=new Array;
labels.push([data[i][0], data[i][1], data[i][2], data[i][3], data[i][4], data[i][5], data[i][6], data[i][7]]);
var emailUser = '****#gmail.com';
var subject = 'Test Email';
convSheetAndEmail(labels, emailUser, subject);
}
}
}
Don't know where you are facing the issue. Check this code, it will help you.
First sort the values of F column and select the unfilled cells from A to H Sort the F column in descending and then first column in ascending (just to get range in sequence).
function convSheetAndEmail(rng, email, subj)
{
var HTML = SheetConverter.convertRange2html(rng);
MailApp.sendEmail(email, subj, '', {htmlBody : HTML});
}
function lastValueOfColumn(column) {
var iLastRow = SpreadsheetApp.getActiveSheet().getMaxRows();
var aValues = SpreadsheetApp.getActiveSheet().getRange(column + "1:" + column + iLastRow).getValues();
for (; aValues[iLastRow - 1] == "" && iLastRow > 0; iLastRow--) {}
return iLastRow;
}
function doGet()
{
var iLastRowOfH = lastValueOfColumn('H');
var ss = SpreadsheetApp.getActiveSpreadsheet().getRange('A1:H' + iLastRowOfH).sort([{column: 6, ascending: false}, {column: 1, ascending: true}]);
var iLastRowOfF = lastValueOfColumn('F') + 1;
var data = SpreadsheetApp.getActiveSpreadsheet().getRange('A' + iLastRowOfF + ':H' + iLastRowOfH);
var emailUser = '****#gmail.com';
var subject = 'Test Email';
convSheetAndEmail(data, emailUser, subject);
}
The easiest way, and the one I know, is to :
get the values in an Array using
var data = SpreadsheetApp.getActiveSpreadsheet().getDataRange().getValues();
then to make a loop
for (i in data) {
in this loop to check if the items ordered (data[i][5]) is equal to null that you're looking for. If yes, then push that row to an array
var labels=new Array;
label.push([data[i][0], data[i][1], data[i][2], data[i][3], data[i][4], data[i][5], data[i][6], data[i][7]]);
then having all your data in this array, you can populate a panen Ui with label using a for loop.
An alternate way is to use the "Query" formula on getRange() which directly gives you filtered data
Finally your script looks like this :-
function convSheetAndEmail(rng, email, subj)
{
var HTML = SheetConverter.convertRange2html(rng);
MailApp.sendEmail(email, subj, '', {htmlBody : HTML});
}
function doGet()
{
var data = SpreadsheetApp.getActiveSpreadsheet().getDataRange().getValues();
var labels=new Array;
for (i in data) {
if (data[i][5] === ""){
labels.push([data[i][0], data[i][1], data[i][2], data[i][3], data[i][4], data[i][5], data[i][6], data[i][7]]);
}
}
var emailUser = '****#gmail.com';
var subject = 'Test Email';
convSheetAndEmail(labels, emailUser, subject);
}

sheetjs excel to json - adding extra <tr> for each row

I couldn't find anything on SO that matched my question. I'm using Sheetjs plugin to convert an excel sheet into json, and displaying it using jquery in the browser. I'm able to do the conversion and display, but I have a use-case where I need to validate each of the json rows with data returned from a jquery ajax 'GET' call.
I'm able to perform that validation as well. Once each excel json row is validated against the values from the ajax response, based on a set of rules, the excel json row is marked either a success row or an error row. For success rows, I perform no action. For error row, I need to add an additional key/value pair in the json element, denoting the error type, and the error description. Further, this error row, when displayed in the browser needs to have a css style with a color:red for red text, to indicate an error.
I haven't seen anything in Sheetjs documentation that might allow me to do this, but I'm pretty sure it can be done. In the code below, I have to modify the helper function called BindTable() in order to add the css style to set the text color to red IF it is an error row. I also have to somehow add a for each of the error rows in order to display the error type and error description.
In the below code, I need to be able to display the invalidRequests JSON object with the css style applied to display the text in red color. Or, if there is a way to directly manipulate the exceljson JSON object to somehow append the key/value pairs of MSG1/message to each of the error rows, that would be even better. I realize that due to the nature of this question, I can't create a jsfiddle, but any ideas/suggestion/comments would be extremely helpful, even if it doesn't provide the complete solution.
Expected format:
author1 JOHN DOE USA N.AMERICA
ERROR: THIS AUTHOR NAME ALREADY EXISTS IN THE SYSTEM!
This is the code that I currently have:
//Excel Reader
function ExcelToTable(event) {
event.preventDefault();
var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.xlsx|.xls)$/;
/*Checks whether the file is a valid excel file*/
if (regex.test($("#excelfile").val().toLowerCase())) {
var xlsxflag = false; /*Flag for checking whether excel is .xls
format or .xlsx format*/
if ($("#excelfile").val().toLowerCase().indexOf(".xlsx") > 0) {
xlsxflag = true;
}
/*Checks whether the browser supports HTML5*/
if (typeof (FileReader) != "undefined") {
var reader = new FileReader();
reader.onload = function (e) {
var data = e.target.result;
//pre-process data
var binary = "";
var bytes = new Uint8Array(data);
var length = bytes.byteLength;
for(var i=0;i<length;i++){
binary += String.fromCharCode(bytes[i]);
}
// /pre-process data
/*Converts the excel data in to object*/
if (xlsxflag) {
// var workbook = XLSX.read(data, { type: 'binary' });
var workbook = XLSX.read(binary, {type: 'binary'});
}
else {
var workbook = XLS.read(binary, { type: 'binary' });
}
/*Gets all the sheetnames of excel in to a variable*/
var sheet_name_list = workbook.SheetNames;
// console.log('Sheet name list : ' + sheet_name_list);
var cnt = 0; /*This is used for restricting the script to
consider only first sheet of excel*/
// sheet_name_list.forEach(function (y) { /*Iterate through
all sheets*/
/*Convert the cell value to Json*/
if (xlsxflag) {
exceljson =
XLSX.utils.sheet_to_json(workbook.Sheets['CUSTOM_EXCEL_TAB'],{defval:
"NULL"});
var emptyAuthorCells =[];
var invalidCountryCells = [];
Object.keys(exceljson).forEach(function(value, key) {
if(exceljson[key].AUTHOR == 'ADD'){
}
else if(exceljson[key].AUTHOR == 'NULL'){
emptyAuthorCells.push({'MARKET':
exceljson[key].MARKET, 'REGION':exceljson[key].REGION,
'PARTNER':exceljson[key].PARTNER, 'AUTHOR': exceljson[key].AUTHOR });
}
//check effective end date
if((exceljson[key].DATE_ENDING != '') ||
(exceljson[key].DATE_ENDING <= getTodayDate())){
invalidCountryCells.push({
'MARKET': exceljson[key].MARKET,
'REGION':exceljson[key].REGION, 'PARTNER':exceljson[key].PARTNER, 'AUTHOR':
exceljson[key].AUTHOR
});
}
});
var emptyActionCellsMessage = "There were " +
emptyAuthorCells.length + " rows with Author=Null <br />";
var completedActionCellsMessage = " Success! There
were " + emptyAuthorCells.length + " rows with authro=Null <br />";
var invalidDateMsg = "There are missing or incorrect
date values.";
var validCompareDataMessage = "Success! All data has been successfully validated!";
var invalidCompareDataMessage = "Validation Failed!
Data does not match Rules.";
}
else {
var exceljson =
XLS.utils.sheet_to_row_object_array(workbook.Sheets[y]);
}
var conflictRows = [];
var returnedRows = [];
var errorReturnedRows = [];
if(emptyAuthorCells.length == 0){
var uniqueAuthor = $.unique(exceljson.map(function
(d){
return d.MARKET;
}));
var doAllValidations = function(){
var ajaxList = [];
var ajxIndex = 1;
$.each(uniqueAuthor, function (index, value){
var jqResponse =
$.ajax({
type: "get",
url: "authorlist.cfm?method=getlist&name=" +
value,
dataType: "json"
});
ajaxList.push(jqResponse);
jqResponse.then(
function( apiResponse ){
$.each (apiResponse, function (cc) {
if(apiResponse[cc].hasOwnProperty('SUCCESS')){
errorReturnedRows.push({
'success':
apiResponse[cc].SUCCESS,
'message':
apiResponse[cc].MESSAGE,
'country_code' : value
});
}
else{
returnedRows.push(apiResponse[cc]);
}
// }
// }
});
}
);
});
return ajaxList;
};
// /LOOP OVER country_code
}
var invalidRequests = [];
var validRequests = [];
$(function() {
var ajaxCalls = doAllValidations();
//begin apply
$.when.apply($, ajaxCalls).done(function(){
//console.log(ajaxList);
$('#hidReturnedRows').val();
$('#hidReturnedRows').val(JSON.stringify(returnedRows));
if (exceljson.length > 0 && cnt == 0) {
if((emptyAuthorCells.length != 0) ||
(errorReturnedRows.length!=0) ) {
//data is invalid
console.log("data is invalid");
$('#displayErrors tr
td.previewSuccessClass').html("");
$('#displayErrors tr
td.previewErrorsClass').html(emptyActionCellsMessage);
$('#export-file').addClass('hidebtn');
}
else{
//outer loop
var found = false;
var book_found = false;
var response_validation_errors = [];
var message = "The author's zone is
incorrect";
var message2 = "This book already
exists";
$.each(exceljson, function(x, ej){
// console.log("inside outer
loop");
found = false;
$.each(returnedRows, function(y,
rr){
//compare inner row with outer
row to make sure they're the same
if(rr.AUTHOR_ID == ej.ID &&
rr.AUTHOR_NAME == ej.NAME)
{
if((rr.AUTHOR ==
ej.NATIVE_AUTHOR) && (rr.BOOK_QUALITY == ej.AUTHOR_ZONE)){
// console.log("found!");
found = true;
}
}
});
if(found){
invalidRequests.push({
"AUTHOR": ej.NAME,
"AUTHOR_ZONE":
ej.AUTHOR_ZONE,
"COUNTRY": ej.COUNTRY
});
}
else{
validRequests.push(ej);
}
});
// /outer loop
}
BindTable(exceljson, '#exceltable');
cnt++;
}
})();
//end apply
});
};
if (xlsxflag) {/*If excel file is .xlsx extension than creates a
Array Buffer from excel*/
reader.readAsArrayBuffer($("#excelfile")[0].files[0]);
}
else {
reader.readAsBinaryString($("#excelfile")[0].files[0]);
}
}
else {
alert("Sorry! Your browser does not support HTML5!");
}
}
else {
alert("Please upload a valid Excel file!");
}
}
//Helper funcs
function BindTable(jsondata, tableid, invalidreqs) {/*Function used to convert the JSON
array to Html Table*/
var columns = BindTableHeader(jsondata, tableid); /*Gets all the column
headings of Excel*/
//ADDED .map() & .find() INSTEAD OF NESTED LOOPS
jsondata.map(a => {
// SEARCH FOR AN ELEMENT IN invalidreqs THAT MATCH THE
// CRITERIA TESTED FOR IN THE FUNCTION
if (invalidreqs.find(b => {
return a.AUTHOR == b.AUTHOR && a.BOOKNAME == b.BOOKNAME && a.COUNTRY ==
b.COUNTRY;
})) {
a.MSG = "THIS ROW ALREADY EXISTS";
}
});
console.log (jsondata);
//THE BELOW CODE NEEDS TO BE CHANGED
var row$ = $('<tr/>');
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
var cellValue = jsondata[i][columns[colIndex]];
row$.append($('<td/>').html(cellValue));
}
//console.log("before table append");
$(tableid).append(row$);
if( has_error ){
row$.addClass( 'response-errors' );//add class to make text red
var error_row = $('<tr/>');
var error_cell = $('<td/>');
error_cell.attr('colspan', column.length); //set cols to span lenght of row
error_cell.html("SET ERROR MESSAGE TO DISPLAY BASED ON invalidreq object");
error_row.append( error_cell );
$( tableid ).append( error_row );
}
}
// /Outer loop
}
function BindTableHeader(jsondata, tableid) {/*Function used to get all
column names from JSON and bind the html table header*/
var columnSet = [];
var headerTr$ = $('<tr/>');
for (var i = 0; i < jsondata.length; i++) {
var rowHash = jsondata[i];
for (var key in rowHash) {
if (rowHash.hasOwnProperty(key)) {
if ($.inArray(key, columnSet) == -1) {/*Adding each unique
column names to a variable array*/
columnSet.push(key);
// console.log(key);
headerTr$.append($('<th/>').html(key));
}
}
}
}
$(tableid).append(headerTr$);
return columnSet;
}
Ok so what you want to do is:
1) Assign the row index to the invalidRequests object, on line 191 like this:
invalidRequests.push({
"AUTHOR": ej.NAME,
"AUTHOR_ZONE": ej.AUTHOR_ZONE,
"COUNTRY": ej.COUNTRY,
"index": x,
"MSG1": "Put the error message here"
});
Now it is very easy to determine which row has an error.
Since the invalidRequests is a private object of the ExcelTable function, you will need to
2) pass it on to the BindTable function like this:
BindTable(exceljson, '#exceltable', invalidRequests);
3) modify the BindTable function to check for invalidRequests and handle them:
function BindTable(jsondata, tableid, invalidreqs) {
var columns = BindTableHeader(jsondata, tableid);
for (var i = 0; i < jsondata.length; i++) {
//look for rows with error
var has_error = false
var invalidreq
for(var u=0;u<invalidreqs.length;u++){
if(i==invalidreqs[u].index){
//found invalid request belonging to current row, set flag
has_error = true
invalidreq = invalidreqs[u] // and store the current invalidrequest infos on temp obj
//break - not really needed
}
}
var row$ = $('<tr/>');
for (var colIndex = 0; colIndex < columns.length; colIndex++) {
var cellValue = jsondata[i][columns[colIndex]];
row$.append($('<td/>').html(cellValue));
}
$(tableid).append(row$);
if(has_error){
row$.addClass('error') // add css class which will make the text red or whatever
var error_row = $('<tr/>') // create error row
var error_cell = $('<td/>')
error_cell.attr('colspan',columns.length) // set column to span over all columns of table
error_cell.html(invalidreq.MSG1)
error_row.append(error_cell)
$(tableid).append(error_row);
}
}
}
Please note it is not clear, nor specified in your code, in which column the error should appear. Try to implement that yourself by pushing that info into the invalidRequests object and reading it out on BindTable.

Categories

Resources