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
Related
I'm trying to create a google app script attached to a spreadsheet that can set a google user's profile picture. According to the documentation, this should work:
var response = UrlFetchApp.fetch(url);
var photoBlob = response.getBlob();
var data = Utilities.base64EncodeWebSafe(photoBlob.getBytes());
AdminDirectory.Users.Photos.update({photoData: data}, this.email);
However this causes an exception:
GoogleJsonResponseException: API call to directory.users.photos.update failed with error: Invalid Input: photoData
The user running this script has permission to edit the profile picture
There must be a problem with your URL, the following works for me:
function myFunction() {
var url = "https://www.telegraph.co.uk/content/dam/Pets/spark/royal-canin/tabby-kitten-small.jpg"
var response = UrlFetchApp.fetch(url);
var photoBlob = response.getBlob();
var data = Utilities.base64EncodeWebSafe(photoBlob.getBytes());
var email = Session.getEffectiveUser().getEmail()
AdminDirectory.Users.Photos.update({photoData: data}, /*this.*/email);
}
Alternatively, you can also use an image from your Drive as following:
function myFunction() {
var url = "https://www.telegraph.co.uk/content/dam/Pets/spark/royal-canin/tabby-kitten-small.jpg"
var response = DriveApp.getFileById("1f8EFG6G5zNd6by_fNEecSh2D1My_p-_p")
var photoBlob = response.getBlob();
var data = Utilities.base64EncodeWebSafe(photoBlob.getBytes());
var email = Session.getEffectiveUser().getEmail()
AdminDirectory.Users.Photos.update({photoData: data}, /*this.*/email);
}
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.
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.
I am a newbie in coding.
I am trying to create a function in google app script that acts like a dictionary and pulls out the meaning of the word passed as the argument. Its using the API of oxford dictionaries but its not working. Its showing the error 403. "var response = UrlFetchApp.fetch(url,headers);" shows the error.
function Word_meaning(word){
var url="https://odapi.oxforddictionaries.com:443/api/v1/entries/en/" + word + "/regions=us";
var headers =
{
'Accept': 'application/json',
'app_id': 'abc',
'app_key': '123'
};
var response = UrlFetchApp.fetch(url,headers);
var data = JSON.parse(response.getContentText());
Logger.log(data);
}
A couple of things - why do you include the port number in the API call? My API endpoint for querying Oxford Dictionaries looks different. Also, there's a dash in "od-api".
https://od-api.oxforddictionaries.com/api/v1/entries/en/{word_id}/regions={region}
Testing the link in the address bar, I get the expected server response of "Authorization required" while the URL you provided doesn't seem to exist.
Anyway, the error pops up because the optional 'params' object for the UrlFetchApp.fetch(url, params) method is not constructed properly. The "headers" property must be contained within that object. Somewhat ambiguous here, but please read:
https://developers.google.com/apps-script/reference/url-fetch/url-fetch-app#fetch(String,Object)
I was able to get things up and running using the code below.
function getData(word, region){
var word = word || "leprechaun";
var region = region || "us";
var wordId = encodeURI(word);
var baseUrl = "https://od-api.oxforddictionaries.com/api/v1/entries/en/{word_id}/regions={region}";
var app_id = "app_id";
var app_key = "app_key";
var headers = {
"app_id": app_id,
"app_key": app_key
};
var options = {
"headers": headers,
"muteHttpExceptions": true
};
var url = baseUrl.replace("{word_id}", wordId)
.replace("{region}", region);
var res = UrlFetchApp.fetch(url, options);
var responseCode = res.getResponseCode();
if (responseCode == 200) {
var data = JSON.parse(res.getContentText());
} else {
Logger.log(res.getContentText());
}
}
Have tried many options to update a product in ECWID using Google Apps Script UrlFetchApp.fetch() put method but not succeeded. Following are the different ways that I've written the code and tested, but am getting different type of errors.
I guess, am missing some small thing, which am not able to figure it out. Please help me to fix this issue.
API: ECWID Products API (http://kb.ecwid.com/w/page/25285101/Product%20API#RESTAPIMethodupdateaproduct)
Method: PUT (to update the product details)
Sample Code 1:-
function updateProducts(){
var products_authkey = "xxxxxxxx";
try{
var url ="https://app.ecwid.com/api/v1/xxxxx/product?id=xxxxxxxx&secure_auth_key="+products_authkey;
var payload = {price:62755};
var options ={method:"put",ContentType:"application/json",payload:payload};
var result = UrlFetchApp.fetch(url, options);
var response = result.getContentText();
}catch(e){
Browser.msgBox(e);
}
}
Error:-
"{ "error": "OTHER", "errorMessage": "Error parsing JSON: A JSONObject text must begin with '{' at character 0" }"
Version 2:-
Tried converting the object to json stringify, but the same error.
function updateProducts_version2(){
try{
var url ="https://app.ecwid.com/api/v1/xxxx/product?id=xxxxx&secure_auth_key="+products_authkey;
var payload = {price:62755};
var payload_json = Utilities.jsonStringify(payload);
var options ={method:"put",ContentType:"application/json",payload:payload_json,muteHttpExceptions:true};
var result = UrlFetchApp.fetch(url, options);
var response = result.getContentText();
var res_code = result.getResponseCode();
var x = 1;
}catch(e){
Browser.msgBox(e);
}
}
Error:-
"{ "error": "OTHER", "errorMessage": "Error parsing JSON: A JSONObject text must begin with '{' at character 0" }"
Version 3:- (Tried passing secure_auth_key using Authorization in headers)
function updateProducts_version3(){
try{
var url ="https://app.ecwid.com/api/v1/xxxxx/product?id=xxxxx";
var payload = {price:62755};
var headers = {Authorization: 'xxxxxxx'};
var options = {headers:headers,method:"put",ContentType:"application/json",payload:payload};
var options ={method:"put",ContentType:"application/json",payload:payload,muteHttpExceptions:true};
var result = UrlFetchApp.fetch(url, options);
var response = result.getContentText();
var res_code = result.getResponseCode();
var x = 1;
}catch(e){
Browser.msgBox(e);
}
}
Error:-
{ "error": "OTHER", "errorMessage": "API key not found in request parameters" }
Also to note that, I've tried using DevHttpClient chrome plugin, it's updating properly.
Which means that there's some problem the way we're using UrlFetch. Please help me in fixing this issue...
Thanks in advance...
Credentials are needed to test this, so that's up to you. You probably need to both stringify & encode the payload. You also had incorrect capitalization on contentType, which you could check with UrlFetchApp.getRequest().
function updateProducts_version2a(){
try{
var url ="https://app.ecwid.com/api/v1/xxxx/product?id=xxxxx&secure_auth_key="+products_authkey;
var payload = {price:62755};
var payload_json = encodeURIComponent(JSON.stringify(payload));
var options ={method:"put",contentType:"application/json",payload:payload_json,muteHttpExceptions:true};
var result = UrlFetchApp.fetch(url, options);
var response = result.getContentText();
var res_code = result.getResponseCode();
var x = 1;
}catch(e){
Browser.msgBox(e);
}
}
This next version seemed to work - by suppressing the price change and using a store's ID, it mimicked a product 'get', according to the docs you referenced. This time, the error message might be indicating some level of success: "This Ecwid account doesn't have access to Ecwid API. Please, consider upgrading it."
You'll notice that the URL has been separated out, with the basic header info of product ID and auth key together.
function updateProducts_version4(){
try{
var url ="https://app.ecwid.com/api/v1/xxxx/product";
var payload = encodeURIComponent(JSON.stringify({
price:62755
}));
var headers = {id:'xxxx',
secure_auth_key: 'xxxxxxx'
};
var options = {
headers:headers,
method:"put",
contentType:"application/json",
muteHttpExceptions:true,
payload:payload
};
var request = UrlFetchApp.getRequest(url, options); // Debug: check what would be fetched
var result = UrlFetchApp.fetch(url, options);
var response = result.getContentText();
var res_code = result.getResponseCode();
var respHeaders = result.getHeaders(); ///
debugger;
}catch(e){
Logger.log(e);
//Browser.msgBox(e);
}
}
Without your creds, that's as far as I can take it... tell us how that works for you.