I have a google sheet with columns set up as dates.
So, A2=1/1/2021, A3 = 1/2/2021, A4 = 1/3/2021 and so on. This is (m/d/yyyy)
This is how it looks like:
Dates
I wish to do a lookup to find the date matching it with my calendar event.
I extract my calendar event with below.
var id_cal = sheet.getRange("A1").getValue();
var cal= CalendarApp.getCalendarById(id_cal);
var start_time = sheet.getRange("A2").getValue();
var end_time = sheet.getRange("B2").getValue();
var events = cal.getEvents(new Date(start_time), new Date(end_time))
for(var i = 0;i<events.length;i++){
var start_time = events[i].getStartTime();
...
}
*EDIT:
The script pulls calendar events from G.Cal.
The event title need to be placed in the second row in the google sheet (see image)
So if the calendar event starts on 3rd Jan, it will be placed below the cell that shows '3' in the image.
So,
var detail = events[i].getTitle();
sheet.getRange(row=2,column= X ) = "My event : " + detail ;
I need to find 'X', based on the date in start_time().*
Without app script, match function works best. but it doesn't work in app script. I would really like to avoid 365 iterations of the for loop for every event. It would be nice if there was a way to use match() or hlookup(), within the appscript.
EDIT2: This is how the image must look like:
Target
How do I fill the events in Row 2 from my google calendar. So that they appear below the cell with correct date.
Example: There is a meeting with A on 1/1/2022.
Related
CURRENT SITUATION
As an owner I've created a spreadsheet that makes an editor of everyone who has received the link. However there are some partially protected sheets with a few unprotected columns, making it possible for these editors to change values. I have an onEdit function that automatically sorts the entire range of a sheet when a cell has been edited by user.
PROBLEM
Unfortunately, since these sheets are partially protected, the AUTOSORT does not work. I need to add something to the script so that when the onEdit is triggered, the activesheet becomes unprotected and the AUTOSORT can do its job. After that the protection is added again (with a few columns as an exception). I don't want everyone to lose their editors rights after this. So it needs to go back to normal.
Script that I tried so far but not working:
function onEdit() {
if (e.range.columnStart == 3 && e.range.getValue() != '') {
var sheets = ["FASHION NL", "FASHION BE","KIDS & UNDERWEAR BNL" ,"NEW BUSINESS BNL" ,"SPORTS & SHOES BNL", "HD&E BNL"]; // Please set your expected sheet names.
var sheet = e.range.getSheet();
if (sheets.includes(sheet.getSheetName())) {
var range = sheet.getRange("A5:bY600");
var spreadsheet = SpreadsheetApp.getActive();
var allProtections =
spreadsheet.getActiveSheet().getProtections(SpreadsheetApp.ProtectionType.SHEET);
var protection = allProtections[0];
protection.remove();
range.sort({ column: 11, ascending: true });
e.source.toast('Sort complete.');
}
}
var protection = spreadsheet.getActiveSheet().protect();
protection.setUnprotectedRanges([spreadsheet.getRange('AK:AK'),
spreadsheet.getRange('BN:BN')])
var editors = SpreadSheet.getEditors();
for (var i = 0; i < editors.length; i++) {
SpreadSheet.removeEditor(editors[i])
}
}
CLARIFICATION PROBLEM
It does not give me an error, but script fails to sort the data range.
SAMPLE SHEET STRUCTURE
Trigger is on column C (3)
Script is created in a way that it reflects whether the Activesheet where the edit takes place is one of the predetermined range of sheets.
You should keep all your permissions as they're and set the function as if it's run by yourself (delete all the parts that have to do with removing and adding permissions). Call it other way than onEdit, for example autoSort(), and set an installable trigger run by event. You can read about it here
The sorting then would be run as it was done by you but triggered by other users' changes. Give it a try and let me know!
I am doing a dependant dropdown list in google sheets using a script.
The source sheet data is read into an array, The destination sheet pulls the dropdown options from the aray.
The numbers from the source sheet are formatted as degrees; 0°, 45°, 90°, 180°.
When the are displayed in the dropdown on the destination sheet the degree symbol is removed and the 0 option doesn't show as an option at all. so I get 45, 90, 180. If I format the destination cell as percent, the the chosen option doesn't match the validation. and I still can't get the 0°.
How can I pass the formatting with the numbers so everything works correctly?
I was thinking I need to do something with setNumberFormat('##0"°"'), but I don't know how.
This is how I am creating the data from the array:
var ws = SpreadsheetApp.getActiveSpreadsheet() .getSheetByName(mainWsName) ;
var wsOptions = SpreadsheetApp.getActiveSpreadsheet() .getSheetByName(optionsWsName) ;
var options = wsOptions.getRange(3, 2,wsOptions.getLastRow()-2, 5).getValues();
var optionsFormat = wsOptions.getRange(3, 2,wsOptions.getLastRow()-2, 5).getNumberFormat()
This is how the data is being retrieved from the array:
var filteredOptions = options.filter(function(o){ return o[0] === firstLevelColValue && o[1] === val });
var listToApply = filteredOptions.map(function(o){ return o[2] });
var cell = ws.getRange(r, thirdLevelColumn) ;
applyValidationToCell(listToApply,cell);
This is my first time asking a question here, I hope I have given the information necessary to solve my problem. Let me know if there is additional information needed.
Thanks
Use getDisplayValues() instead of getValues()
This will allows you to retrieve the values in exactly the same way as they are displayed in the spreadsheet.
I'm trying to query Episerver Community to get paged approved topics within a date range (e.g. within the last 2 days) that are ordered by the thread's last activity (activity being the thread's last approved reply or the thread's creation date if approved replies are 0).
I've tried using the GetTopics() method and aside from not being able to pass a date range, LastReply includes replies that are still in the moderation queue so the sort doesn't work correctly.
I've also tried to use the Query API but I'm unsure if it's possible to construct a query as complex as this. Is there any way of including AND/OR in the sort as well as making sure that the LastReply is approved? This is as far as I've got:
var topicQuery = new TopicQuery
{
Created = new DateTimeCriterion(),
Status = new EntityStatusCriterion
{
Operator = FlagsOperator.Equal,
Value = EntityStatus.Approved
},
LastReply = new ReplyCriterion{
Status = new EntityStatusCriterion(),
Created = new DateTimeCriterion()
}
};
//filter by days
if (withinDays > 0)
{
topicQuery.Created.Operator = ComparisonOperator.GreaterThan | ComparisonOperator.Equals;
topicQuery.Created.Value = DateTime.Now.AddDays(-withinDays);
}
//sort, this is incorrect, I am trying to sort by last approved reply date or created date if not available
//Last reply is sometimes not approved and it needs to be...
topicQuery.OrderBy.Add(new CriterionSortOrder(topicQuery.Created, SortingDirection.Descending));
topicQuery.OrderBy.Add(new CriterionSortOrder(topicQuery.LastReply.Created, SortingDirection.Descending));
var result = QueryHandler.GetQueryResult<Topic, MessageCollection>(topicQuery, page, pageSize);
I've built a google form for a multiple choice quiz, with a linked spreadsheet for results, which works very well. I have a specific problem, which is that I'd like to present the user's results to them (i.e. how many answers they got right/wrong). The approach I've taken so far is:
create an extra sheet on the spreadsheet with a formula to calculate the number of correct answers for each response. This gives me two columns "Full Name" and "Scores"
embed the form into a google site
create a google apps script to read the results sheet and display output
embed the above into the same site below the form as an Apps Script Gadget
Currently I am able to display all of the results recorded so far. See here:
https://sites.google.com/site/mcqtest123/home
The script looks like:
// Script-as-app template.
function doGet() {
var app = UiApp.createApplication();
var title = app.createLabel("Survey Results").setStyleAttribute("fontSize","16px");
app.add(title);
//readRows(app);
calculateScores(app);
return app;
};
function calculateScores(app) {
var sheet = SpreadsheetApp.openById("0AlNR-ou0QtandFFzX1JCU1VRdTl0NVBRNTFjOUFhd1E");
var responseSheet = sheet.getSheetByName("Form Responses");
var allData = responseSheet.getDataRange().getValues();
var correct = allData[1];
var responses = allData.slice(2);
//Logger.log("Timestamp, name, score");
Logger.log("Name, Score");
for (var i = 0; i < responses.length; i++) {
var timestamp = responses[i][0];
var name = responses[i][1];
var score = 0;
for (var j = 2; j < correct.length; j++) {
if(responses[i][j] == correct[j]) {
score += 1;
}
}
//var output = timestamp + ", " + name + ", " + score + "/" + correct.length
var output = name + ", " + score + "/" + correct.length
print(app, output);
}
};
function print(app, line) {
Logger.log(line);
app.add(app.createLabel(line));
};
So this leaves two problems:
When the page loads, it loads the scores for all the respondents. I'd like to be able to present only the score for the person who filled out the form.
The scores don't get updated when the form is completed - only when the page is refreshed.
For problem 1), I wondered if there was some way to access the data in the form iframe (e.g. using document.getElementById('targetFrame'), except that google scripts don't seem to have access to the document model) to only display results of the person whose full name matches the name in the form (of course you could then view someone else's results if you know what they'd put as their full name, but without using the timestamp I don't see away round this).
For problem 2), I wondered if there was some way to trigger the script when the responses sheet was updated. However when I go to the spreadsheet and Tools->Script Manager I get the message "No scripts found", so I don't know how to add this trigger.
If you make your own form using HtmlService or UiApp and then that POSTing to your script to populate the spreadsheet, then you can generate a UID in a hidden field and use this to determine the results someone needs to see.
This will be the results as instant feedback to their answers to the quiz. To see these at a later date, you could then also add a bookmarkable link that also included that UID as a parameter. So your doGet() would look for a e.parameters.uid for example.
From Google Forms as they stand I am not so sure. you could potentially, with the new form styles, offer a pre-filled field with such a UID, but the route from form submission to your webapp is again unclear.
I have Google form that gets filled in by a few users. Works great but has it's limitations.
I'd like to copy the data entered from the active sheet to a new sheet called "work", all information except the first row that is. In the first row I have a few array formulas that populate some cells as new data is entered on the active sheet.
The second sheet (work) has a header row with all the formatting, data validation, some formulas etc (row 1). This information can not be applied when a new record is added via the form.. so I am told..
Thus, once the data has been copied from the active sheet (called active) I'd like the new data to be formatted as per the heading row (row 1) of the "work" sheet with all the formatting, validation, formulas etc being applied to the new data.
Is this doable? I am a noob when it comes to scripting so a complete solution would be highly appreciated.
here is a sample form you can play with
https://docs.google.com/spreadsheet/ccc?key=0AplugTacg-08dFNRUHROSW82bDhESkxBdjVTV0NOLUE
First thing i noticed one can not just copy/paste as the array formulas will bong things up so it has to be a paste special - values only
Any help greatly appreciated.
I'm struggling a bit with the logic behind what you're doing, but I've attempted a solution in sheet 'work2' in this copy of your spreadsheet. Perhaps have a play and report back what's not right or missing.
The script is this:
function onFormSubmit(e) {
var sheet = SpreadsheetApp.getActive().getSheetByName('work2');
var nextRow = sheet.getRange(sheet.getLastRow() + 1, 1, 1, 9);
sheet.getRange(2, 1, 1, 9).copyTo(nextRow);
var sLength = e.values[2].length;
var huuh = e.values[3] * sLength;
var pending = e.values[3] * e.values[3] / huuh;
var nextMonth = e.values[3] + pending;
nextRow.setValues([[e.values[0], e.values[1], huuh, e.values[2], sLength, e.values[3], 'Please select action', pending, nextMonth]]);
}
and has an "on form submit" trigger attached to it.