I am fairly new to app script so sorry for the beginner question...
I have this script (see below) which works well to add calendar events to my team calendar and to invite my colleagues as guests. The issue is that I ran the script and sent the invites but now I have to edit the dates.. When I run the script again it just add the new dates without deleting the wrong previous entries...
Could you try help me modifying this script to ensure it will edit or delete previous entries instead of creating new ones? I have created another column called "event id" in order to capture events id but I don't really know how to make use of it in the script...
Let me know
thanks a lot for your help
function CalendarTest() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var index = 2;
var lastrow = sheet.getLastRow();
for (;index <= lastrow; index++){
var title = sheet.getRange(index,1,1,1).getValue();
var startTime = sheet.getRange(index,2,1,1).getValue();
var endTime = sheet.getRange(index,3,1,1).getValue();
var description = sheet.getRange(index,4,1,1).getValue();
var location = sheet.getRange(index,5,1,1).getValue();
var guests = sheet.getRange(index,6,1,1).getValue();
var sendInvites = true;
var calendar = CalendarApp.getCalendarById("mycalendarID").createEvent(title,startTime, endTime,
{description: description, location: location, guests: guests, sendInvites });
}
}
Related
The situation:
I am trying to load a dataset and then add additional criteria (filters) to the dataset based off users selected fields. The whole dev is a "Custom Report" build using a suitlete that has some fields the user can populate to choose "dynamic filters". When they click on the generate button I add the criteria/filters to a search and dataset and then join the results and display them.
The issue is that while I am able to add filters to the search after I load it no matter what I try I can't seem to add filters to the Dataset.
This code gets the dataset Data:
var datasetData = datasetLib.load({ id: datasetId });
resultSet.pageRanges.forEach(function (pageRange) {
// Fetch the results on the current page
var myPage = resultSet.fetch({ index: pageRange.index });
res.data = res.data.concat(myPage.data.results);
if (res.columns.length < 1) {
var columns = JSON.parse(myPage.pagedData.queryDefinition).columns;
for (var i = 0; i < columns.length; i++) {
res.columns.push(columns[i].label);
}
}
});
I attempted many different iterations to create the condition... here is one:
dataset.createCondition({
column: datasetData.columns[0], // I loaded the dataset and use it to reference the column
operator: query.Operator.ANY_OF,
values: params.customer.split(',')
})
Now the above code DOSE create a condition but when I attempt to add it into the dataset's current conditions I receive errors.I am attempting to push it into the child parameter of the parent criteria.
Please ask if you need more info...
If using a workbook is fine then I would suggest you to load the workbook using your above dataset using the query module and then use the above createCondition to add the condition to the loaded query dynamically.
var myLoadedQuery = query.load({
id: 'custworkbook237'
});
var mySalesRepJoin = myLoadedQuery.autoJoin({
fieldId: 'salesrep'
});
var thirdCondition = mySalesRepJoin.createCondition({
fieldId: 'email,
operator: query.Operator.START_WITH_NOT,
values: 'foo'
});
I would also urge to ensure the joins are accurately represented by looking at the Records catalog via Setup>Records Catalog. Hope this helps.
I have set up a Google sheet for attendance of Employees on which clicking on the checkbox, the current time is recorded.
I cannot get the specific timestamp in the respective columns when the checkbox is ticked.
Clicking on a different checkbox also change the timestamp for previously checked checkboxes.
I have used this formula here : =If(B2 = TRUE,now(),"")
and used filter handle to apply the formula for other rows underneath.
I have used this formula: =If(B2 = TRUE,now(),"")
The sheet can be seen here: https://docs.google.com/spreadsheets/d/1p6jmnHXtCu2m7BdLfC-23A51MrwkJJJpXidpbsDwxfU/edit?usp=sharing
I want to record the current timestamp, for each row.
i.e on clicking of the checkbox the current time should be changed/recorded only for the column in the same row and not for other records.
this needs to be done with the script:
function onEdit(e) {
var s = SpreadsheetApp.getActiveSheet();
{
var r = s.getActiveCell();
if( r.getColumn() == 2 ) {
var nextCell = r.offset(0, 1);
var newDate = Utilities.formatDate(new Date(),
"GMT+1", "dd/MM/yyyy hh:mm:ss");
nextCell.setValue(newDate);
}
}
how to add a script to your spreadsheet
go to Tools
select Script editor
copy paste the script
save the project under some name
click on run icon and authorise it...
select your account
click on Advanced
select Go to * (unsafe)
click on Allow and return to your sheet (you can close script window/tab)
I am writing an application that pulls task data (for a task management system) from rows in a Google Spreadsheet with conditions matching a query. I then send this data into a flexTable next to a checkbox with an onClickHandler as well as a textbox to enter in hours data. Below is the simplest example of how I have achieved this:
\\establish handler for checkboxes that are generated in flexTable
var updateHandler = app.createServerClickHandler('updateTasksfunc');
updateHandler.addCallbackElement(taskTable);
\\search Google Spreadsheet for rows matching condition
for(var i=1; i< taskData.length; i++){
if (taskData [i][1] !=employee){
continue;
}
\\look up if task is already completed, and set checkbox value to true/false
var complete = taskData[i][8].toString();
if(complete==="true"){var checkbox=true;}else{var checkbox=false;}
\\populate flexTable with values from spreadsheet query
taskTable.setWidget(i,0,app.createTextBox().setName('hours'+i).setWidth('50').setId("hour"+i)).setWidget(i,1,app.createCheckBox().setValue(checkbox).setName('complete'+i).addClickHandler(updateHandler)).setWidget(i,2,app.createLabel(taskData[i][2]).setWidth('250')).setWidget(i,3,app.createLabel(taskData[i][3]).setWidth('250')).setWidget(i,4,app.createLabel(taskData[i][4])).setWidget(i,5,app.createLabel(taskData[i][5])).setWidget(i,6,app.createLabel(taskData[i][6])).setWidget(i,7,app.createLabel(taskData[i][7])).setWidget(i,8,app.createTextBox().setVisible(false).setName("dataRow"+i).setValue(i))
}
\edits to doGet()
var numberOfItems = app.createTextBox().setName('rows').setValue(i).setVisible(false);
var rows1 = i+1;
taskTable.setWidget(rows1,0,numberOfItems)
I have stored the spreadsheet data row in the invisible textbox in column 8 of the flex table that I intend to use in the clickHandler function to update the Google Spreadsheet.
I have successfully activated a click handler that runs when a checkbox is clicked; however, I have not yet successfully figured out a way to grab data from the flexTable that I can use to update the Spreadsheet.
//Functional code below
function updateTasksfunc(e){
var app = UiApp.getActiveApplication();
var taskSS = SpreadsheetApp.openById('SPREADSHEETID');
var taskSH = taskSS.getSheets()[0];
var taskData = taskSS.getDataRange().getValues();
var results = [];// an array to collect results
var numberOfItems = e.parameter.rows;
app.add(app.createLabel(numberOfItems));
for(var n=0;n<numberOfItems;n++){
results.push([e.parameter['check'+n]]);// each element is an array of 2 values
}
for(var i=1;i<results.length;i++){
var check = results[i][0];
var row = i+1;
taskSH.getRange(row,9,1,1).setValue(check);
}
return app;
}
I am getting a generic error: cannot find function getRowCount() from generic.
I assume that this means that I am not properly calling my flexTable.
Any thoughts??
flextables are not working like spreadsheets, you can't get widgets values directly as part of the table. You have to get every textBox and checkBox separately using e.parameter.Name.
You can do that easily in a loop but you'll have to know the number of textBoxes to be able to rebuild the names just as you did to create them in the doGet function.
I would suggest to store this number in a tag on one of your widget or in a separate hidden widget (hidden class or invisible textBox). Then you will be able to get the values like this :
...
var results = [];// an array to collect results
var numberOfItems = Number(e.parameter.itemNumbers); // this is the var you are missing right now and need to add. This is the solution of a separate hidden widget
for(var n=0;n<numberOfItems;n++){
results.push([e.parameter['hours'+n],e.parameter['complete'+n]]);// each element is an array of 2 values
}
... // from here you will have an 2D array with all your values and you can continue like you did=.
I have a Google Sites site with a List page.
I want to get the data from the ListItems into a database (ScriptDB or JDBC to MySQL/SQL Server.)
I'd like to fire an update as a result of an onUpdate type event, but can't find anything like that. Is the solution to run a script every so often?
The downside of running a script periodically is that I can't capture all changes, only the current state when the script runs. I would like a full audit of changes if possible. I'd also have to interrogate each ListItem to check the lastUpdated date to see if it is newer than the records already in the database, which seems like a lot of redundant processing.
Any advice?
Indeed you cannot run an onUpdate event as they are reserved for Spreadsheets.
However you have the information on the listItems and you can run a loop like this to get the update time and publication time of your items:
function getChanges(){
var listItems=page.getListItems();
var update;
var datePublished;
for(var i=0;i<listItems.length;++i){
update=item[i].getLastUpdate();
datePublished=item[i].getDatePublished();
list of stuff to do like compare with the content of your database;
}
}
A clock trigger is then the best solution to capture the changes (like a 10 minute trigger).
Unfortunately you cannot do more than this.
Cheers
Nicolas
Thanks Nicolas. In the end I already implemented something pretty similar:
function updatePeople(){
for(var j in peopleList){
// Check if the record in the peopleList is newer than the last database (not record) update.
var personUpdated=peopleList[j].getLastUpdated().getTime();
var dbUpdated= db.query({Type:"dbUpdated"}).next().dbUpdated;
// If the record is newer than the last database update...
if(personUpdated>dbUpdated)
{
// ...check if the record exists in the database (check for current record using Is_Current = 1)
// If it does, set the Valid_To date on the old record to be 1 second before the Valid_From date of the new record.
var result = db.query({Type:"Person", Initials: peopleList[j].getValueByName("Initials"), Is_Current:1}).getSize();
if(result>0){
var oldPerson = db.query({Type:"Person", Initials: peopleList[j].getValueByName("Initials"), Is_Current:1}).next();
var validTo = personUpdated-1000;
oldPerson.Valid_To = validTo;
oldPerson.Is_Current = 0;
db.save(oldPerson);
// now add a new Person record.
addPerson(j);
}
else {
addPerson(j);
}
}
}
updateDbUpdatedDate();
}
The addPerson() function is a pretty simple function to add a new record.
function addPerson(j){
var person={};
person["Valid_From"]=peopleList[j].getLastUpdated().getTime();
person["Valid_To"]=9999999999999;
person["Is_Current"]=1;
person["Type"]="Person";
person["Initials"]= peopleList[j].getValueByName("Initials");
person["Name"]=peopleList[j].getValueByName("Name");
person["Email_Address"]= peopleList[j].getValueByName("Email Address");
person["Team"]=peopleList[j].getValueByName("Team");
person["Grade"]=peopleList[j].getValueByName("Grade");
person["Admin"]=peopleList[j].getValueByName("Admin");
db.save(person);
}
I'm trying to create a website where users can come and look for a set of resources, something like a portal, or a database like JSTOR. I am using Weebly; this website will eventually be turned over to someone who does not know computers well, so I'm trying to keep things simple (and free, where doable).
My thought was to use Google Spreadsheets/Forms to handle the input and storage of the data for each individual resources (Title, Author, Type, Topic, Country, etc.), and then find some some method of creating a search function that could placed on the website. Any user could arrive at the site, put in whatever criteria they want to look for, and any resources in the database would be listed out for the user to further investigate. Users would not be adding data to the spreadsheets; only querying it for data.
My first question is such a script/arrangement possible and can it be embedded into a website page? My second question is what would the best approach be?
Yes this is certainly possible, but can achieved in a variety of ways.
One approach you could take with this is to retrieve all the data from the spreadsheet as JSON format and add it to the DOM as a HTML table. Then you can use a nice plugin like dataTables which has a pretty good native search function. I'll give a basic example below.
To retrieve the data you can use Googles spreadsheet JSON API. A basic example is below.
<script src="http://spreadsheets.google.com/feeds/cells/*ID*/*WS*/public/values?alt=json-in-script&callback=*FN*"></script>
Where ID is the spreadsheet's long ID.
Where WS is the worksheet number e.g. 1,2,3 etc.
Where FN is the function you want to call. In my below function i use importGSS
Then I've written the below script that adds the data to a HTML table. It first adds the first row to a <thead> section and then adds the rest to the <tbody> section.
function cellEntries(json, dest) {
var table = document.createElement('table');
var thead = document.createElement('thead');
var tbody = document.createElement('tbody');
var thr;
var tr;
var entries = json.feed.entry;
var cols = json.feed.gs$colCount.$t;
for (var i=0; i <cols; i++) {
var entry = json.feed.entry[i];
if (entry.gs$cell.col == '1') {
if (thr != null) {
tbody.appendChild(thr);
}
thr = document.createElement('tr');
}
var th = document.createElement('th');
th.appendChild(document.createTextNode(entry.content.$t));
thr.appendChild(th);
}
for (var i=cols; i < json.feed.entry.length; i++) {
var entry = json.feed.entry[i];
if (entry.gs$cell.col == '1') {
if (tr != null) {
tbody.appendChild(tr);
}
tr = document.createElement('tr');
}
var td = document.createElement('td');
td.appendChild(document.createTextNode(entry.content.$t));
tr.appendChild(td);
}
$(thead).append(thr);
$(tbody).append(tr);
$(table).append(thead);
$(table).append(tbody);
$(dest).append(table);
$(dest + ' table').dataTable();
}
You can then call back the function with ... where #Destination is the <div> you want to add the HTML table to.
function importGSS(json){
cellEntries(json, '#Destination');
};
Once all completed you'll see something like the below screenshot, the top the final results and the bottom the original spreadsheet. I've edited out some information. I hope this has been of some help.