I'm trying to write a simple Content Service API with Google App Script. My doGet() just takes a single param 'row' and returns the value in that row from col 2. Here it is:
function doGet(req){
try{
reqRow = req.queryString.split('=')[1];
rowNum = parseInt(reqRow);
}
catch(err){
throw "Error: "+ err + " -- Here's what we got: " + req + "Did you include a row parameter?";
}
resultValue = getFromSheet(rowNum);
if(resultValue != ""){
result = {
"Result":"Success",
"Row": reqRow,
"Value" : resultValue
}
}
else{
result = {
"Result":"Failure",
"Row": reqRow,
"Value" : "No value found at row"
}
}
return ContentService.createTextOutput(JSON.stringify(result)).setMimeType(ContentService.MimeType.JSON);
}
And here's our simple getFromSheet function:
function getFromSheet(row){
if(typeof row != "number"){
row = Number(row);
Logger.log("converting");
}
sheetid = 111111111;
ss = SpreadsheetApp.openById(sheetid);
sheet = ss.getSheets()[0];
return ss.getRange(row, 2).getValue();
}
When I post something to it, via a url similar to
"https://script.google.com/macros/s/111111111/exec?row=3"
I get the following error:
Cannot find method getRange(number,number).
Note: Why didn't I use req.parameters.row in our doGet() method? Because I was receiving the following error:
Cannot find method getRange((class),number).
Isn't getRange(number, number) the main way to call this method?
Here is the reference guide to the sheet class:
https://developers.google.com/apps-script/reference/spreadsheet/sheet
Thank you all!
Changed the variable name to rowRequest instead of row.
function getFromSheet(rowRequest){
if(typeof rowRequest != "number"){
rowRequest = Number(rowRequest);
Logger.log("converting");
}
ss = SpreadsheetApp.openById('12r0gHSgvBg8s_RJIuWJl-3aZCAGOpW0PfGb0SVGNu4Q');
sheet = ss.getSheets()[0];
result = sheet.getRange(rowRequest, 2).getValue();
return result;
}
Related
I'm trying to submit a contact form using google-app-script. When I'm submit that, it displays the following page:
https://script.google.com/macros/s/AKfycbx-sxqjOmCD5pGhLzzcI9Tc906bZN5VnNQQCe34/exec
I want this url to to redirect to my another page, how can I achieve that using scripts.
Below is the script. Just for the info, I'm a beginner.
/******************************************************************************
* 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 = "abc#gmail.com";
// 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: "About Me: 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;
}
I tried to see your script, but it return this error: Script function not found: doGet
However, you could try do this...
window.location.href = "YOUR_URL";
Im having trouble with an script that posts the outcome twice, I have reviewed the script but I cant find the issue.
The script gets the "Timestamp", "Cell address", "Column label" and "Value entered" and post it on the sheet named "Tracker" but it gets posted twice
function onEdit() {
var sheetsToWatch = ['Responses'];
// name of the sheet where the changelog is stored
var changelogSheetName = "Tracker";
var timestamp = new Date();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = sheet.getActiveCell();
var sheetName = sheet.getName();
// if it is the changelog sheet that is being edited, do not record the change
if (sheetName == changelogSheetName) return;
// if the sheet name does not appear in sheetsToWatch, do not record the change
var matchFound = false;
for (var i = 0; i < sheetsToWatch.length; i++) {
if (sheetName.match(sheetsToWatch[i])) matchFound = true;
}
if (!matchFound) return;
var columnLabel = sheet.getRange(/* row 1 */ 1, cell.getColumn()).getValue();
var rowLabel = sheet.getRange(cell.getRow(), /* column A */ 1).getValue();
var changelogSheet = ss.getSheetByName(changelogSheetName);
if (!changelogSheet) {
// no changelog sheet found, create it as the last sheet in the spreadsheet
changelogSheet = ss.insertSheet(changelogSheetName, ss.getNumSheets());
// Utilities.sleep(2000); // give time for the new sheet to render before going back
// ss.setActiveSheet(sheet);
changelogSheet.appendRow(["Timestamp", "Cell address", "Column label", "Value entered"]);
changelogSheet.setFrozenRows(1);
}
changelogSheet.appendRow([timestamp, cell.getA1Notation(), columnLabel, cell.getValue()]);
}
Google's method documentation makes it seem like you can programmatically check for the existence of some other user's trigger with a function like this:
function triggerLogger() {
// Read installed triggers for the project.
var triggers = ScriptApp.getProjectTriggers();
var installedReport = {};
triggers.forEach(function (t) { installedReport[t.getUniqueId()] = {
event: t.getEventType(),
calledFunction: t.getHandlerFunction(),
source: t.getTriggerSource(),
source_id: t.getTriggerSourceId() || "Time-based triggers have no source id."
}});
// Read "simple" triggers for the project by checking for globals that start with "on".
var simpleReport = {};
for (var thing in this)
if (thing.indexOf("on") === 0 && thing.length > 2)
simpleReport[String(thing)] = {def: this[thing]};
var possibleSimple = Object.keys(simpleReport).length,
message = "Trigger report: " + triggers.length + " installed";
if (possibleSimple) message += ", " + possibleSimple + " possible simple triggers";
message += ".";
// Log to Stackdriver (so the report can be viewed sensibly).
console.log({
message: message,
installed: Object.keys(installedReport).length ?
installedReport : "No detected installed triggers.",
simple: possibleSimple ?
simpleReport : "No simple triggers used",
reportRunAs: Session.getActiveUser().getEmail()
});
}
But the getProjectTriggers() method, despite claiming to get all of the current project's installed triggers, will only obtain your installed triggers for the document, even if you are the owner of the document.
Note that this behavior is accepted as a bug (meaning someone, someday will fix it). If you would like to feel that you have done your part to accelerate that timeline, please star that issue:
I am working on a firebase project. During testing the
return user.val().name;
will return an
undefined
value however the
console.log(user.val().name)
will return the actual string stored in the .name field. Why is that. Also even if assign the
user.val().name
to a variable, the variable remains undefined.Please help figure out why this happens. I am printing it to a csv.
Here is my code:
var database = firebase.database();
var ref2 = database.ref('information/');
var id;
var name;
ref2.on("value", function (one) {
one.forEach(function (two) {
if (typeof two.val().Id !== 'undefined') {
id = two.val().Id;
name = program(id); //name undefined
}
else {
id = "";
}
csv = name + "," + id +"\n";
});
download(csv);
});
};
function program (id) {
var database = firebase.database();
var ref = database.ref("users/" + id + "/");
ref.on('value',function(user){
if (typeof user.val().name === 'undefined') {
return null;
}
else {
console.log(user.val().name); //this doesnt show undefined
return user.val().name; //this shows undefined when returned to the name variable
}
})
}
Note: In the firebase database, the name value is not null. It has a string added to it.
I have a Lambda function which runs in Node.js 4.3. The input parameter of the function is a String, which is being sent from an AWS Lex bot.
I want to get an item from a DynamoDB table. In this item I have a Map-type attribute, which contains a String key and String value. I want to get a value from that map using the key String I got as a parameter at the start of the function.
The problem is that when I log the map to the console, all I see there is {}.
This is my code:
var AWS = require('aws-sdk');
AWS.config.region = 'us-east-1';
var dynamodb = new AWS.DynamoDB();
const sessionAttributes = intentRequest.sessionAttributes;
const slots = intentRequest.currentIntent.slots;
const name = slots.names;
var id = null;
if (name == "a") {
id = "00";
} else if (name == "b") {
id = "01";
}
var params = {
TableName: 'names',
Key: {
'id' : {S: 'test-id'}
}
};
var names = {};
dynamodb.getItem(params, function(err, data) {
if (err) {
console.log(err); // an error occurred
} else {
names = data.Item.names.M;
}
});
console.log(names);
var content = names[id];
callback(close(sessionAttributes, 'Fulfilled',
{'contentType': 'PlainText', 'content': content}));
As you can see, there is a console.log line at the end of the code. This line logs just {}. The final message's content is undefined.
What can I do to fix this?
dynamodb.getItem() is executing asynchronously, it has a callback function for this very reason.
console.log(names) is executing before any value is returned in the call to dynamodb.
Add a console.log() inside the getItem function and you will see that this is true.
Google "asynchronous javascript" and you'll find some good pointers.
I'm trying to access a global variable from a main function to a handler function using scriptDb.
Following the [documentation instructions][1], I create a piece of code similar to this:
function showList(arrayList) {
Logger.log("arrayList argument value = " + arrayList);
var arrayToUse = {
arrayName: 'theses',
arrayValue: arrayList,
};
var record = db.save(arrayToUse);
var scriptDbObject = db.query({arrayName: 'theses'});
var arrayList = scriptDbObject.arrayValue;
Logger.log("ShowList arrayList query value = " + arrayList);
}
But when I try to query the inserted item, It doesn't work:
![enter image description here][2]
The argument arrayList is OK (as the log shows).
I also tried this other code, following as similar as I could [this stackoverflow question][3]:
function showList(arrayList) {
Logger.log("arrayList argument value = " + arrayList);
var record = db.save({arrayName: "savedArray", arrayValue: arrayList});
var result = db.query({arrayName: 'thesesRequests'});
if (result.hasNext()) {
arrayList = result.next().data;
}
else {
arrayList ["empty array", "empty", "array"];
}
Logger.log("ShowList arrayList query value = " + arrayList);
And I got the same undefined message.
What is going wrong here?
[1]: https://developers.google.com/apps-script/guides/script-db/
[2]: http://i.stack.imgur.com/5CpyY.png
[3]: Error when trying to store an array in ScriptDb
That first go of yours was on the mark, except that when u do a query you need to use the next() operator on the result to get the actual dbResult entry:
function showList(arrayList) {
Logger.log("arrayList argument value = " + arrayList);
var arrayToUse = {
arrayName: 'theses',
arrayValue: arrayList,
};
var record = db.save(arrayToUse);
var scriptDbObject = db.query({arrayName: 'theses'});
if (scriptDbObject.hasNext()) {
var dbItem = scriptDbObject.next();
var dbArrayList = dbItem.arrayValue
Logger.log("ShowList arrayList query value = " + dbArrayList);
}
}