Formatting Parameter for Google Scripts - javascript

I am building out a script on my Google Sheet that will catch a Webhook POST from my CRM and update a row on the worksheet. Everything is working perfectly, except I can't figure out how to format this one parameter.
It comes over in the webhook payload like this:
...
"Dinner Seminar Session Choice":"Thursday, Feb 27th at 5:30pm",
...
The Google Sheet Script is this:
//this is a function that fires when the webapp receives a GET request
function doGet(e) {
return HtmlService.createHtmlOutput("request received 11:40");
}
//this is a function that fires when the webapp receives a POST request
function doPost(e) {
var params = JSON.stringify(e.postData.contents);
params = JSON.parse(params);
var myData = JSON.parse(e.postData.contents);
var FirstName = myData.first_name;
var LastName = myData.last_name;
var Phone = myData.phone;
var Session = myData.DinnerSeminarSessionChoice;
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = Math.max(sheet.getLastRow(),1);
sheet.insertRowAfter(lastRow);
var timestamp = new Date();
sheet.getRange(lastRow + 1, 1).setValue(timestamp);
sheet.getRange(lastRow + 1, 2).setValue(FirstName);
sheet.getRange(lastRow + 1, 3).setValue(LastName);
sheet.getRange(lastRow + 1, 4).setValue(Phone);
sheet.getRange(lastRow + 1, 5).setValue(Session);
sheet.getRange(lastRow + 1, 6).setValue(params);
SpreadsheetApp.flush();
return HtmlService.createHtmlOutput("post request received");
}
function myFunction() {
}
You can see on line 14, I'm trying to set the content of that param as var Session. But it doesn't seem to work with or without the spaces.
I'm sure this is a simple formatting error, but I just don't know how to do it. I appreciate any help.
Jason

As pointed to by #TheMaster's comments.
Property accessors can be used with "[ ]" to read or write property names with spaces.
Example:
const json_response = {
"oldValue": "false",
"trigger Uid": "30023847",
"user": {
"nick name": "fat.mike",
}
}
console.log(json_response.oldValue)
json_response.oldValue = null;
console.log(json_response['oldValue'])
console.log(json_response['trigger Uid'])
console.log(json_response.user);
console.log(json_response.user['nick name'])

Related

Telegram bot inline keyboard via AppScript

I am making a Telegram bot using Appscript and I want to copy/send message with an inline_keyboard but when I send the URL I get an invalid parameter error and I don't know what is wrong, because everything worked until I add the reply_markup parameter.
function enviarMnesjePruebaCanal() {//ENVIAR MENSAJE
var urlusuarioconid = "tg://userid?=" + miID
var keyboard = {
"inline_keyboard": [
[
{
"text": "Usuario",
"url": urlusuarioconid
}
]
]
};
var url = telegramUrl + '/sendMessage?chat_id=' + miID + '&text=' + "texto" + "&reply_markup=" + JSON.stringify(keyboard);
Logger.log(url);
UrlFetchApp.fetch(url);
}
`
This is my code and this is what I send to telegram and what I get back:
(I have deleted the data of my bot and my id for obvious reasons, but that part is ok because when I run it without the last part it sends me the message)
I have already tried several things and they all give the same problem, I don't know if anyone can help me or see what could be happening. Thanks!
The issue is caused by the reply_markup containing non-url tokens.
You should encode that part of the url using encodeURIComponent()
Change the code to:
function enviarMnesjePruebaCanal() {
var myID = 123456;
var urlusuarioconid = "tg://userid?=" + myID
var keyboard = {
"inline_keyboard": [
[
{
"text": "Usuario",
"url": urlusuarioconid
}
]
]
};
var url = telegramUrl + '/sendMessage?chat_id=' + myID + '&text=' + "texto" + "&reply_markup=" + encodeURIComponent(JSON.stringify(keyboard));
Logger.log(url);
var response = UrlFetchApp.fetch(url);
Logger.log(response.getContentText());
}
The important change here is adding the encodeURIComponent:
encodeURIComponent(JSON.stringify(keyboard))

Get SpreadSheetApp Id through webapp

I have Add-On and WebApp, I want to read active spreadsheetapp Id in webapp but not able to do it, getting error
SyntaxError: Unexpected token < in JSON at position 0
Kindly help me to correct the code as I am new to Javascript/JSON.
Add-On:
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu('DataQ')
.addItem('Submit to Manager', 'copyData')
.addToUi();
}
//Backup data to master spreadsheet.
function copyData() {
var ss_id = SpreadsheetApp.getActive().getId();
//This is the Web App URL.
var url = "https://script.google.com/macros/s/xyz/exec";
var payload = {
"ss_id" : JSON.stringify(ss_id),
}
var options = {
"method" : "POST",
"payload" : payload,
"followRedirects" : true,
"muteHttpExceptions" : true,
};
var result = UrlFetchApp.fetch(url, options);
}
WebApp
function doPost(e) {
var ss_id = JSON.parse(e.parameters.ss_id);
var response = {
"status" : "FAILED",
"ss_id" : ss_id,
};
var ss_id = ss_id[0];
var dss=SpreadsheetApp.openById('1vMeoANf6JJ8w0MP2DHJ6oTC4');
var dsh=dss.getSheetByName('Consolidated_Data');
dsh.getRange(dsh.getLastRow()+1,1,sData.length,sData[0].length).setValues(sData);
var FrontDesk_ss = SpreadsheetApp.openById(ss_id);
var FrontDesk_sheet = FrontDesk_ss.getSheetByName('Data');
FrontDesk_sheet.getRange('D1:D20').setValue('Done');
var response = {
"status" : "SUCCESS",
"sData" : sData,
};
return ContentService.createTextOutput(JSON.stringify(response));
}
Modification points:
In your function of copyData(), ss_id is sent as "payload" : {"ss_id" : JSON.stringify(ss_id)},. In this case, at the doPost(e) side, e.postData.contents, e.parameters.ss_id, and e.parameter.ss_id are ss_id=%22{Spreadsheet ID}%22, ["\"{Spreadsheet ID}\""] and \"{Spreadsheet ID}\", respectively.
By this, when the value of Spreadsheet ID is retrieved from this event object, the double quotes of " are required to be removed.
But, when I saw your script of doPost, you use var ss_id = JSON.parse(e.parameters.ss_id). In this case, ss_id is dthe Spreadsheet ID. But, you use var ss_id = ss_id[0] after var ss_id = JSON.parse(e.parameters.ss_id). By this, ss_id is the 1st character of Spreadsheet ID. I think that this might be an issue of your script.
In this answer, in order to send and use Spreadsheet ID in your script, I would like to propose to modify both copyData() and doPost(e) as follows.
Modified script:
copyData()
Please modify copyData() as follows.
From:
var payload = {
"ss_id" : JSON.stringify(ss_id),
}
To:
var payload = {
"ss_id" : ss_id, // Modified
}
doPost(e)
Please modify doPost(e) as follows.
From:
var ss_id = JSON.parse(e.parameters.ss_id);
var response = {
"status" : "FAILED",
"ss_id" : ss_id,
};
var ss_id = ss_id[0];
To:
var ss_id = e.parameter.ss_id; // Modified
var response = {
"status" : "FAILED",
"ss_id" : ss_id,
};
// var ss_id = ss_id[0]; // Removed
Note:
When you modified the script of Web Apps, please redeploy the Web Apps as new version. By this, the latest script is reflected to the Web Apps. Please be careful this.
References:
Web Apps
Taking advantage of Web Apps with Google Apps Script

Sending data to Google Spreadsheet via Ajax

I'm having problems sending data to a Google Spreadsheet via Ajax.
I followed this guide to achieve this: https://medium.com/#dmccoy/how-to-submit-an-html-form-to-google-sheets-without-google-forms-b833952cc175
My own code looks as simple as this:
var data = {"user": "bar"};
var url = 'https://script.google.com/macros/s/AKfycby6BzLifopR36ZBJ2WqDMNsndCYUpHihSOfhomfSRZXcdetvOA/exec';
$('.my-button').on('click', function (e) {
$.ajax({
url: url,
method: "GET",
dataType: "json",
data: data
}).done(
function (__e) {
console.log('Remote sheet updated!', __e);
}
).fail(function (__e) {
console.log('Remote sheet update failed', __e);
});
});
This is what my spreadsheet looks like:
This is the code from the tutorial that goes into the Google scripteditor.
function doGet(e){
return handleResponse(e);
}
// Enter sheet name where data is to be written below
var SHEET_NAME = "DATA";
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());
}
In the code provided by the author of the tutorial all I did is change the sheet name in line 9 to "DATA"
// Enter sheet name where data is to be written below
var SHEET_NAME = "DATA";
...which is the name of the sheet.
The problem is now, when I click "my-button", it gets send successfully, but returns an error object. The error doesn't contain any additional information though. It seems to go into the "catch" section of the Google script, but doesn't inform me of what exactly went wrong. Now I don't even know how to debug this, let alone understand, what went wrong.
I already tried all kinds of weird things like using JSON.stringify, none of that helped. It should work like this anyway, so I have no idea what's the problem here.

Ho do I Parse XML using Google Apps Script and loop through all elements

This is my first time working with XML and I am not that techy but trying to get to understand programming to make my work easier. I am using Google App script and finding it a challenge in passing XML data that I get via API.
I need to get this data so that I can set the specific values to Google sheets using google app script.
I am not sure how to iterate/loop through elements to get everyone's data and then set it to google sheet.
And here is the code I have worked on so far. When I log to say the first name, I only get one name instead of about 50 names in the system. Any help here will highly be appreciated.
ak ='key'
start = '2019-01-01'
end = '2019-12-31'
function getData() {
var options = {
method: 'get',
headers: {
Authorization: 'Bearer ' + ak
}
};
var url = 'https://data.purelyhr.com/daily?ak='+ ak + '&sDate=' + start + '&eDate=' + end + '&TimeOffTypeName';
var response = UrlFetchApp.fetch(url).getContentText();
var document = XmlService.parse(response);
var root = document.getRootElement();
//set variables to data from PurelyHR
var TimeOffDate = root.getChild('Request').getChild('TimeOffDate').getText();
var TimeOffDayOfWeek = root.getChild('Request').getChild('TimeOffDayOfWeek').getText();
var TimeStart = root.getChild('Request').getChild('TimeStart').getText();
var TimeEnd = root.getChild('Request').getChild('TimeEnd').getText();
var TimeOffHours = root.getChild('Request').getChild('TimeOffHours').getText();
var TimeOffTypeName = root.getChild('Request').getChild('TimeOffTypeName').getText();
var LoginID= root.getChild('Request').getChild('LoginID').getText();
var Firstname = root.getChild('Request').getChild('Firstname').getText();
var Lastname = root.getChild('Request').getChild('Lastname').getText();
var UserCategory = root.getChild('Request').getChild('UserCategory').getText();
var SubmittedDate = root.getChild('Request').getChild('SubmittedDate').getText();
var Deducted = root.getChild('Request').getChild('Deducted').getText();
var Comment = root.getChild('Request').getChild('Comment').getText();
//populate the sheet with variable data
Logger.log(response)
}
Sample response
<?xml version='1.0' encoding='ISO-8859-1'?>
<DataService>
<Request ID="1253" Status="Approved">
<TimeOffDate>2020-02-07</TimeOffDate>
<TimeOffDayOfWeek>Friday</TimeOffDayOfWeek>
<TimeStart></TimeStart>
<TimeEnd></TimeEnd>
<TimeOffHours>8.000</TimeOffHours>
<TimeOffTypeName>Annual Vacation</TimeOffTypeName>
<LoginID>testuser</LoginID>
<Firstname>test</Firstname>
<Lastname>user</Lastname>
<UserCategory></UserCategory>
<SubmittedDate>2019-10-03</SubmittedDate>
<Deducted>Yes</Deducted>
<Comment>
<![CDATA[* time-off request created by administrator]]>
</Comment>
</Request>
<Request ID="126292" Status="Approved">
<TimeOffDate>2020-02-07</TimeOffDate>
<TimeOffDayOfWeek>Friday</TimeOffDayOfWeek>
<TimeStart></TimeStart>
<TimeEnd></TimeEnd>
<TimeOffHours>8.000</TimeOffHours>
<TimeOffTypeName>Annual Vacation</TimeOffTypeName>
<LoginID>usertwo</LoginID>
<Firstname>user</Firstname>
<Lastname>two</Lastname>
<UserCategory></UserCategory>
<SubmittedDate>2019-10-15</SubmittedDate>
<Deducted>Yes</Deducted>
<Comment>
<![CDATA[Neil (as my mentor)]]>
</Comment>
</Request>
If I understand correctly, the problem is that you have multiple <Request> elements, but your code is only looking at one of them. This is because you're using getChild(), which will only provide the first element with the given name.
I can't fully test that this works because you haven't provided the XML text, but you should instead use the getChildren() method to get all of the Request elements. Then you can loop through that.
function getData() {
var options = {
method: 'get',
headers: {
Authorization: 'Bearer ' + ak
}
};
var url = 'https://data.purelyhr.com/daily?ak=' + ak + '&sDate=' + start + '&eDate=' + end + '&TimeOffTypeName';
var response = UrlFetchApp.fetch(url).getContentText();
var document = XmlService.parse(response);
var root = document.getRootElement();
//set variables to data from PurelyHR
var requestElements = root.getChildren('Request'); // Get all <Request> elements
var requestObjects = []; // Request objects for logging / eventual printing
for (var i = 0; i < requestElements.length; i++) {
var request = requestElements[i]; // A single <Request> element
// Add to requestObjects array
requestObjects.push({
TimeOffDate: request.getChild('TimeOffDate').getText(),
TimeOffDayOfWeek: request.getChild('TimeOffDayOfWeek').getText(),
TimeStart: request.getChild('TimeStart').getText(),
TimeEnd: request.getChild('TimeEnd').getText(),
TimeOffHours: request.getChild('TimeOffHours').getText(),
TimeOffTypeName: request.getChild('TimeOffTypeName').getText(),
LoginID: request.getChild('LoginID').getText(),
Firstname: request.getChild('Firstname').getText(),
Lastname: request.getChild('Lastname').getText(),
UserCategory: request.getChild('UserCategory').getText(),
SubmittedDate: request.getChild('SubmittedDate').getText(),
Deducted: request.getChild('Deducted').getText(),
Comment: request.getChild('Comment').getText()
});
}
Logger.log(JSON.stringify(requestObjects));
}
Since I don't know how you're printing, I created an array of request objects and logged that in the sample above. I hope this made sense, but please let me know if you have any questions or if I'm completely off with my response.

Parsing XML in Google Scripts to a google sheet

I'm trying to import data from a server, XML format via the server API, which require's a login.
Using information on this question: Cheers MogsDad
I can successful get the external xml file and data shows in the logger.
I cannot for the life of me write any of the info or elements to my spreadsheet. In the link shared, #mogsdad has linked to a parsing XML site. Unfortunately the link is dead. The current code returns an XML file. Normally I would try to use the importxml formula but not had much luck.
Have taken out my coding attempts to parse the XML so code doesn't look awful
has anyone got any pointers on how to parse some of all of the file or know a working URL for the XML parsing doc?
Here is my code so far. Thanks in advance
function importFromXml(){
var url = 'URL HERE'; // Advance search for macs not encrypted.
var username = 'USER HERE';
var password = 'PASSWORD HERE';
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
// Getting "bad request" here - check the username & password
var result = UrlFetchApp.fetch(url, options);
var state=result.getContentText();
// You should check state.getResponseCode()
Logger.log('1: '+state);
Logger.log(parse(state));
}
function parse(txt) {
var doc = Xml.parse(txt, true);
return doc; // Return results
}
**** EDIT ****
After a bit more playing, I have some progress.
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("NoFirevault");
var range = ss.getRange(1, 1);
range.setValue(state);
I managed to write the XML contents to my sheet. Albeit in one cell. When I try to split the data into cells, using the data length and use setValues. It bums out on me, will keep on playing.
**** EDIT *****
After a bit more playing around. I can get XML data written to sheet.
There's 31 entries, with various attributes. But these all get written to a single cell per entry.
Which is an improvement on ALL 31 entries going to a single cell.
In case it helps, here is the XML layout I'm looking at.
I want the computer data, in the computers section.
function importFromJamf(){
var url = 'URL HERE'; // Advance search for macs not encrypted.
var username = 'USER HERE';
var password = 'Password';
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
var result = UrlFetchApp.fetch(url, options);
var state = result.getContentText();
var document = XmlService.parse(state);
var entries = document.getRootElement().getChild('computers').getChildren(); // Working but values joined into one row
for (i=0;i<entries.length;i++){
var value = entries[i].getValue();
SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2").getRange(i+1,1).setValue(value);
}
}
function importFromJamf(){
var url = 'url';
var username = 'user';
var password = 'pw';
var headers =
{
Authorization : "Basic " + Utilities.base64Encode(username+':'+password)
}
var options =
{
"method" : "get",
"headers": headers
};
var result = UrlFetchApp.fetch(url, options);
var state = result.getContentText();
var document = XmlService.parse(state);
var array= [];
var entries = document.getRootElement().getChild('computers').getChildren('computer');
for(i = 0 ; i < entries.length ; i++){
var a = entries[i].getContent(5).getValue();
var b = entries[i].getContent(8).getValue();
var c = entries[i].getContent(9).getValue();
var d = entries[i].getContent(6).getValue();
var e = entries[i].getContent(11).getValue();
var f = entries[i].getContent(12).getValue();
var g = entries[i].getContent(10).getValue();
var data = [a,b, c,d,e, f,g];
array.push(data);
}
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Sheet1");
sheet.getRange("A2:Z").clearContent();
var range = sheet.getRange(2,1,array.length, array[0].length);
range.setValues(array);
}
Code above works for what I need, it allows me to grab the values I want into an array I can use to write to a sheet.
.getContent() helped me get the values of y columns of array each loop
But I'm sure there are better ways of going about it.

Categories