I'm trying to teach myself Google app scripts and I've run into a problem I can't figure out. I have a script that gets data from a user form in google sheets and uses that data to create contact.
I am able to create contact and put it in the right group.
The trouble begins when I try and put a custom field on the contact and populate the custom field with data.
I get the following error:
TypeError: Cannot read property 'setLabel' of undefined
at createPrimaryContact(Code:82:9)
at createContacts(Code:27:24)
I've tried following along with the documentation at:
https://developers.google.com/apps-script/reference/contacts/custom-field without any success.
function createPrimaryContact(contactsApp, data, group, groupName) {
var contact = contactsApp.getContact(data.emailAddy);
if (contact == null) {
var contact = contactsApp.createContact(
data.fName,
data.lName,
data.emailAddy
);
if (data.tel !== "") {
contact.addPhone(ContactsApp.Field.MOBILE_PHONE, data.tel);
}
if (data.addy !== "") {
var addyString =
data.addy + " , " + data.cty + " , " + data.st + " " + data.postcode;
contact.addAddress(ContactsApp.Field.HOME_ADDRESS, addyString);
}
}
var group = contactsApp.getContactGroup(groupName);
group.addContact(contact);
var searchName = data.fName + " " + data.lName;
var contacts = contactsApp.getContactsByName(searchName);
var field = contacts[0].getCustomFields()[0];
field.setLabel("Opportunity Name"); //this is line 82 that is generating the error mentioned above.
field.setValue(data.oName);
return { addyString };
}
I can't figure out what the problem is, even after many web searches later.
Can you see what I'm doing wrong ?
Any links or recommendations would be appreciated.
If you are trying to .getCustomFields() and set a label, it implies that there are already custom fields present in your contact. If there are no custom fields available, the .getCustomFields() method will return an empty array. If you are trying to access the empty array as you do it here:
var field = contacts[0].getCustomFields()[0];
The var field will be equal to undefined, because there is no entry at position 0. That's why it is throwing the TypeError.
To solve this issue, just use the .addCustomField(label, content)method to create a custom field.
Applying it to your case:
var searchName = data.fName + " " + data.lName;
var contacts = contactsApp.getContactsByName(searchName);
contacts[0].addCustomField("Opportunity Name", data.oName)
Documentaion can be found here.
Related
I found this very useful script on here for iteratively returning a list of file metrics by directory in GDrive. My problem is I want to add columns that exclude emails from a give domain. For example on the fileItem.getEditors I might want to return a list excluding editors in the "#mycompany.com" domain.
var childFolders = parent.getFolders();
var childFiles = parent.getFiles();
var allValues = []; // Added
while (childFiles.hasNext()){
var fileItem = childFiles.next();
data = [
parentName + "/" + fileItem.getName() + "/" + fileItem.getName(),
fileItem.getName(),
fileItem.getMimeType(),
fileItem.getUrl(),
fileItem.getAccess(Session.getActiveUser()),
fileItem.getSharingPermission(),
fileItem.isShareableByEditors(),
fileItem.getOwner().getEmail(),
fileItem.getEditors().map(function(e){return [e.getEmail(), e.getName()]}).join(","),
fileItem.getViewers().map(function(e){return [e.getEmail(), e.getName()]}).join(","),
];
allValues.push(data); // Added
}
sheet.getRange(sheet.getLastRow() + 1, 1, allValues.length, allValues[0].length).setValues(allValues); // Added
Cooper's answer is already great but you don't need to include # on the comparison.
Filter your data by adding filter before the map that gets the email and name:
.filter(function(e){e.getDomain() != "mycompany.com"})
Output:
fileItem.getEditors().filter(function(e){e.getDomain() != "mycompany.com"})
.map(function(e){return [e.getEmail(), e.getName()]}).join(","),
So I'm building this web forecast app using OpenWeatherMap API, and so far I'm being able to fetch the data from the first iteration of the list's output, however I need to obtain the data of other specific fields aswell. Here's a bit of my code:
ajaxGet("https://api.openweathermap.org/data/2.5/onecall?lat=4.6097&lon=-74.0817&exclude=current,minutely,hourly,alerts&appid=APPID&units=metric", function (response) {
var data = JSON.parse(response);
console.log(data);
var temperature = document.createElement("h6");
temperature.textContent = data.daily[0].temp.max + "°" + " / " + data.daily[0].temp.min + "°";
document.getElementById("temperaturaBogVier").appendChild(temperature);
});
And here's an example of what the API's output looks like (I'm only showing the first iteration in here, but there are at least 6 in total, https://api.openweathermap.org/data/2.5/onecall?lat=4.6097&lon=-74.0817&exclude=current,minutely,hourly,alerts&appid=APPID&units=metric):
{"lat":4.61,"lon":-74.08,"timezone":"America/Bogota","timezone_offset":-18000,"daily":
[
{"dt":1600876800,
"sunrise":1600857917,
"sunset":1600901504,
"temp":{"day":18.14,"min":8.99,"max":18.14,"night":12.08,"eve":15.45,"morn":8.99},
"feels_like":{"day":17,"night":11.02,"eve":14.6,"morn":7.58},
"pressure":1017,"humidity":54,
"dew_point":8.69,
"wind_speed":1.2,
"wind_deg":164,
"weather":[{"id":501,"main":"Rain","description":"moderate rain","icon":"10d"}],
"clouds":82,
"pop":0.94,
"rain":5.85,
"uvi":15.14}
]
}
So as you can see, I'm being able to print into my HTML the data contained into "data.daily[0].temp.", but it only works for the first set of fields and I got no clue how to select a specific iteration. I'm sure I'm missing something into the concat, but nothing I've tried has worked so far.
Any help would be greatly appreciated, and rewarded with an imaginary waffle. THX :D
The temperatures for each day data.daily are defined as an JavaScript array of objects. You can simply access them by their index, which indicates their position in the array.
data.daily[0] // First element
data.daily[1] // Second element
data.daily[2] // Third element
Once you have selected an object within the array, you can then access certain values like data.daily[2].temp.max.
The cool thing about arrays is that you can iterate them with a loop. This will save you a lot of writing, if you want to print out each temperatures for every day:
ajaxGet("https://api.openweathermap.org/data/2.5/onecall?lat=4.6097&lon=-74.0817&exclude=current,minutely,hourly,alerts&appid=YOUR_API_KEY_HERE&units=metric", function (response) {
var data = JSON.parse(response);
console.log(data);
data.daily.forEach(function (date) {
var temperature = document.createElement("h6");
temperature.textContent = date.temp.max + "°" + " / " + date.temp.min + "°";
document.getElementById("temperaturaBogVier").appendChild(temperature);
})
});
Please note: I've removed the appid=XXXXX part of the request URL, because it contains your personal API key for OpenWeather, which you should not share publicly.
If I understand the question correctly, you want to take all daily max/min-values and put them into elements that you want to append to another element.
Here is a way to do that
ajaxGet("https://api.openweathermap.org/data/2.5/onecall?lat=4.6097&lon=-74.0817&exclude=current,minutely,hourly,alerts&units=metric", function (response) {
var data = JSON.parse(response);
console.log(data);
data.daily
.map(datapoint => datapoint.temp) //get the temp value/object from each datapoint
.map(temp => { //create an element and add each max/min value to that element's textContent
const temperature = document.createElement("h6");
temperature.textContent = temp.max + "° / " + temp.min + "°";
return temperature;
})
.forEach(element => { //add each of the elements created in the previous map to the desired element
document.getElementById("temperaturaBogVier").appendChild(element);
});
});
As pointed out in the other answer, I've also removed the app-id query parameter
I am simply trying to obtain the "numFound" figure from a Solr query in a piece of javascript.
At present the code I have outputs the number of responses, limited to X rows I specify, as well as X number of items.
What I want instead is the "numFound" value in the response, and to store it as a var in my javascript.
In the example below it would be 394.
{
"responseHeader":{
"zkConnected":true,
"status":0,
"QTime":31,
"params":{
"q":"names:\"Leo Varadkar\" AND region:\"ROI\""}},
"response":{"numFound":394,"start":0,"maxScore":11.911881,"docs":[
I don't want any info from the fields of a specific entry or anything like that. In my python code I can obtain such a figure by something like "solr.search(query).hits". However I have been unable to find an equivalent from poking around with this. I have tried to guess something like "data.response.hits" and the like but to no avail. I am really in the dark here!
I have been unable to find clear documentation on how to do this, or an example of someone doing the same thing, despite it seeming like quite an important aspect of the whole point of queries in Solr. Top 50 results are no use to me. I am dealing with tens of thousands of items. My confusion might suggest I am failing to understand some key aspect of the whole thing...but I don't think so?
All I want is that figure. Surely somebody knows how to get it? I bet it's very simple.
My javascript below:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>
function on_data(data) {
$('#results').empty();
var docs = data.response.docs;
$.each(docs, function(i, item) {
$('#results').prepend($('<div>' + item.name + '</div>'));
});
var hits = 'Found ' + data.response. + ' hits'
$('#hits').prepend('<div>' + hits + '</div>');
var total = 'Found ' + docs.length + ' results';
$('#results').prepend('<div>' + total + '</div>');
}
function on_search() {
var query = $('#query').val();
if (query.length == 0) {
return;
}
var url='http://localhost:8983/solr/articles/select?q=text:'+query+'&version=2.2&start=0&rows=10000&indent=on&wt=json&callback=?&json.wrf=on_data';
var urlB='http://localhost:8983/solr/articles/select?q=text:'+query+'&version=2.2&start=0&rows=50&indent=on&wt=json&callback=?&json.wrf=on_data';
$.getJSON(urlB);
}
function on_ready() {
$('#search').click(on_search);
/* Hook enter to search */
$('body').keypress(function(e) {
if (e.keyCode == '13') {
on_search();
}
});
}
$(document).ready(on_ready);
The structure is {"response":{"numFound":394 ... }}, which is loaded into your data variable.
var hits = 'Found ' + data.response.numFound + ' hits'
.. should give you the number you're looking for. The hits name is just given by various libraries (probably pysolr in your case) to the same value.
You can also use console.log(data) to see the parsed data structure in your developer tools' console window.
I have a form with a textbox title, dropdown menu year and a button. When I click the button, I want to get the values of title and year as properties to an object Movie. Then save them to a table on parse.com. The code below adds a recording to the table with values undefined.
<script>
function saveValues() { // function is appended as onclick to button
var $titleValue = $('#inputTitle').val();
var $select = $('#select');
var $yearValue = $select.val();
var Movie = Parse.Object.extend("Movie");
var movie = new Movie();
// movie.set('title', $titleValue); // Doesn't work. Returns undefined
// movie.set('year', $yearValue); // Doesn't work. Returns undefined
movie.title = $titleValue; // Works
movie.year = $yearValue; // Works
alert(movie.title); // Returns the value
alert(movie.year); // Returns the value
alert(movie); // Returns [object Object]. I was expecting {title: '<SOMETITLE>', year: '<SOMEYEAR>'}
console.log(movie); // This prints a lot of stuff and title and year are there with the respective values.
movie.save()
.then(function(object) {
alert("yay! it worked");
})
}
</script>
Note that when I try to save only the title to the table, it works fine.
Without seeing your full code, I can't guarantee that this will work, but give this a try:
movie.save({
title : $titleValue,
year : $yearValue,
}, {
success: function(movie) {
alert("movie saved successfully with title: " + movie.get("title") +
", and year: " + movie.get("year"));
},
error: function(error) {
alert("error, movie save failed. error code: " + error.code + ", " error.message);
}
});
At the very least you will have a descriptive error message that will tell you what went wrong. Based on the fact that you said it works when you only save the title and not the year, I suspect it may be because your 'year' field in Parse is stored as a number, but you are passing it in as a string (since it came from an HTML form, I'm assuming).
If that doesn't work, I also suspect it may have something to do with appending this function to your button onload rather than as a click or a submit. But that wouldn't explain why it still works if you just leave out the year.
Finally, I wonder if Parse's SDK is confused by the '$' symbol at the beginning of your variable names, but I don't see why that would be the case.
OK, after some time I found out what the problem was. And it was a silly one. It turns out that the value in option was of type 'string'. By adding parseInt() like so: var $yearValue = parseInt($select.val());. And then movie.save({title: titleValue, year: yearValue})..... This way everything works. Initially, I had tried putting key-value pairs in the save() but the year value wasn't the right type.
So note to anyone out there - check your data types!
I am trying to access the ID of Library using client-side object model in SharePoint 2013. But I am getting error as:
The property or field 'Id' has not been initialized. It has not been requested or the request has not been executed. It may need to be explicitly requested.
Below is my code:
var context = SP.ClientContext.get_current();
var web = context.get_web();
var items = SP.ListOperation.Selection.getSelectedItems(context);
var currentLibrary = web.get_lists().getById(SP.ListOperation.Selection.getSelectedList(context));
context.load(currentLibrary, 'id'); // Tried with 'Id' but still throws error
console.log(currentLibrary);
console.log("currentLibrary.get_id = " + currentLibrary.get_id()); // THROWS ERROR!
What am I doing wrong here?
The error:
The property or field 'Id' has not been initialized. It has not been
requested…
occurs since List object has not been requested.
Use SP.ClientContext.executeQueryAsync method to execute the current pending request asynchronously on the server
A working example:
var context = SP.ClientContext.get_current();
var web = context.get_web();
var listId = SP.ListOperation.Selection.getSelectedList(context);
var list = web.get_lists().getById(listId);
context.load(list, 'Id'); //tell SharePoint to load List Id property
context.executeQueryAsync( //submit query to the server
function(){
console.log("ID:" + list.get_id()); //process result in success callback
},
function(sender,args){
console.log(args.get_message()); //handle error in error callback
}
);
my issue happened to be a silly one, the column I was returning was originally created with the name Requestor_DisplayName, and later changed to Employee_DisplayName so when using:
oListItem.get_item('Employee_DisplayName');
I got the >
"The property or field 'Id' has not been initialized. It has not been requested…" error
The issue had nothing to do with the SP.ClientContext.executeQueryAsync method itself...
When I changed the code to:
oListItem.get_item('Requestor_DisplayName');
It ran with out issue. You can use SP CAML Query Helper Online to inspect your your list and columns (as well as build CAML Queries) this is how I discovered my issue:
Hope this helps someone in the future!
Thanks.
SG.
Well back again editing this answer as today made another discovery about this error message similar in concept, I did not realize SharePoint will trim your column names after 32 Characters in length...
I got the exact same error message as before in the Developers Tool > debug console (IE f12) but about a different column of course.
"The property or field 'Operations_Approver1_Display_Name' has not been initialized. It has not been requested…"
I was left scratching my head after checking column names in list settings as I had in my JSOM, the column name was "Operations_Approver1_Display_Name" (Yes I was once a COBOL developer so I like long and Meaningful Names LOL)
oListItem.get_item('Operations_Approver1_Display_Name');
All seemed to check out, I thought "Well maybe I have a type in original column name and don't remeber fixing it" So of course I naturally opened up, SP CAML Query Helper Online (man I lobe this tool, yes the b was on purpose LOL).
This is how I discovered that SharePoint has a limit of 32 Characters for column names, just wanted to update this answer since it is highly ranked on search. As you can see in the screenshot below that the InternalName name of the column has been cut short by one character from its "Title" column name (Leave it to me to make this Name 33 characters long just 1 over the limit)
using Vadim answer:
var oItem ='';
function retrieveWebSite() {
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function(){
var clientContext = new SP.ClientContext.get_current();
this.oWebsite = clientContext.get_web();
clientContext.load(this.oWebsite);
var lstObject = oWebsite.get_lists().getByTitle('Listname');
oItem = lstObject.getItemById(5);
clientContext.load(oItem);
clientContext.executeQueryAsync(
Function.createDelegate(this, this.onQuerySucceeded),
Function.createDelegate(this, this.onQueryFailed)
);
});
}
function onQuerySucceeded(sender, args) {
var look = oItem.get_item('LookupColumnName').get_lookupValue();
var title = oItem.get_item('Title');
var id = oItem.get_id();
alert("Loook up column value: "+look);
alert("Title column: "+title);
alert("Id column value: "+id);
}
function onQueryFailed(sender, args) {
alert('Request failed. ' + args.get_message() +
'\n' + args.get_stackTrace());
}
you are looking for ids then do like this:-
var context = SP.ClientContext.get_current();
var web = context.get_web();
var items = SP.ListOperation.Selection.getSelectedItems(context);
for (var i = 0; i < items.length; i++) {
var id= items[i].id;
}
Thanks :)