How to use for loop one under the last row of the other using google app script? - forms

I need to take data from a basic excel form and paste it on a data table as many times as one of the cells form the form says.
This is the form:
Form
I've tried this:
function COPIARPEGAR() {
var Libro = SpreadsheetApp.getActiveSpreadsheet();
var Form = Libro.getSheetByName("Form")
var CON = Form.getRange('J18').getValue();
var Disciplina = Form.getRange('J20').getValue();
var Masculino = Form.getRange('L22').getValue();
var TituloMasculino = Form.getRange('L20').getValue();
var Femenino = Form.getRange('N22').getValue();
var TituloFemenino = Form.getRange('N20').getValue();
var BBDD = Libro.getSheetByName("BBDD2");
var DisciplinaBBDD = BBDD.getRange('A1:A').getValues()
var UltimaFila = DisciplinaBBDD.filter(String).length
for(var filamasc=UltimaFila+1;filamasc<=Masculino+1;filamasc++) {
BBDD.getRange(filamasc,1).setValue(Disciplina)
BBDD.getRange(filamasc,2).setValue(CON)
BBDD.getRange(filamasc,3).setValue(TituloMasculino)
for(var filafem=UltimaFila+1;filafem<=Femenino+1;filafem++) {
BBDD.getRange(filafem,1).setValue(Disciplina)
BBDD.getRange(filafem,2).setValue(CON)
BBDD.getRange(filafem,3).setValue(TituloFemenino)
}
Logger.log(UltimaFila);
Logger.log(CON);
Logger.log(Disciplina)
}
And as result I always get the smaller number overwrited by the largest number like this:
result
Thanks for yur help!

Your loops are the issue in that you aren't starting at the same rows. Consider running your code in debug mode so you can see your variables value on the right hand part of the screen (such as UltimaFila = 1). I looked at your code, and I think this would work with modifications, but again look at your variables on the right side of your code, and run in debug mode.
function COPIARPEGAR() {
var Libro = SpreadsheetApp.getActiveSpreadsheet();
var Form = Libro.getSheetByName("Form")
var CON = Form.getRange('J18').getValue();
var Disciplina = Form.getRange('J20').getValue();
var Masculino = Form.getRange('L22').getValue();
var TituloMasculino = Form.getRange('L20').getValue();
var Femenino = Form.getRange('N22').getValue();
var TituloFemenino = Form.getRange('N20').getValue();
var BBDD = Libro.getSheetByName("BBDD2");
var DisciplinaBBDD = BBDD.getRange('A1:A').getValues()
var UltimaFila = DisciplinaBBDD.filter(String).length;
//Updated the ending point
for (var filamasc = UltimaFila + 1; filamasc <= Masculino + 1 + UltimaFila; filamasc++) {
BBDD.getRange(filamasc, 1).setValue(Disciplina)
BBDD.getRange(filamasc, 2).setValue(CON)
BBDD.getRange(filamasc, 3).setValue(TituloMasculino)
}
//See the starting points change
var DisciplinaBBDD = BBDD.getRange('A1:A').getValues()
var UltimaFila = DisciplinaBBDD.filter(String).length
//Updated the ending point
for (var filafem = UltimaFila + 1; filafem <= Femenino + 1 + UltimaFila; filafem++) {
BBDD.getRange(filafem, 1).setValue(Disciplina)
BBDD.getRange(filafem, 2).setValue(CON)
BBDD.getRange(filafem, 3).setValue(TituloFemenino)
}
Logger.log(UltimaFila);
Logger.log(CON);
Logger.log(Disciplina)
}
How To Debug Your Code

Related

set values after sending mail

I want the script to send an email to those mail addresses where unchecked boxes are in the row - This works fine. But I want the value of the checkbox to be set “True” after the mails were sent.
My Problem is that I need the last for-loop to stop after all checkboxes are checked. In other words: The last loop has to stop when an empty cell appears.
First of all I manually trigger the script - later I will start it with the help of a button in the menu (function onOpen...)
Appreciate any help – thanks a lot!
Check out the sheet and the code below:
function sendmail() {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Sheet1');
var r = s.getRange('C:C'); //Checkboxes
var v = r.getValues();
for(var i=v.length-1;i>=0;i--)
if(v[0,i]=='false') {
var range = ss.getRange("A1:D4");
var UserData = range.getValues();
var UserData = range.getValues();
var row = UserData[i];
var name = row[0];
var email = row[1];
MailApp.sendEmail(row[1], "Test", "Hello " + name + ", This is an email");
var response = ui.alert("mail was send to ", ui.ButtonSet.OK);
}
for (k=1; k < 20; k++) { //loop which has to stop
s.getRange(k, 3).setValue("True");
}
}
A couple of major changes in your script.
The condition for the loop is wrong. Change to:
for(var i=v.length-1;i>0;i--)
The UI response is missing the recipient name. Change to:
var response = ui.alert("mail was send to "+name, ui.ButtonSet.OK);
var UserData = range.getValues(); is declared twice: delete one row
Immediately after the UI alert (and still within the IF loop), add a line to update the checkbox: UserData[i][2] = true;
Simplify the updating of checkboxes.
Delete the existing lines:
for (k=1; k < 20; k++) {
s.getRange(k, 3).setValue("True");
}
Substitute:
range.setValues(UserData)
Revised Script
function sosendmail() {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Sheet1');
var r = s.getRange('C:C'); //Checkboxes
var v = r.getValues();
for(var i=v.length-1;i>0;i--)
if(v[0,i]=='false') {
var range = ss.getRange("A1:D4");
var UserData = range.getValues();
var row = UserData[i];
var name = row[0];
var email = row[1];
// MailApp.sendEmail(row[1], "Test", "Hello " + name + ", This is an email");
Logger.log("mail sent")
var response = ui.alert("mail was send to "+name, ui.ButtonSet.OK);
UserData[i][2] = true;
}
range.setValues(UserData)
}
Alternative Script
The following script is offered as an alternative. It avoids multiple getRange()/getValue statements and uses a more conventional top-down loop.
function sosendmail01() {
var ui = SpreadsheetApp.getUi();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName('Sheet1');
// get the number of rows (Alast)
var Avals = ss.getRange("A2:A").getValues();
var AlastRow = Avals.filter(String).length;
// Logger.log("DEBUG: number of rows = "+AlastRow)
// get the data range
var r = s.getRange(2, 1, AlastRow, 3);// get all the data
// Logger.log("DEBUG: the data range = "+r.getA1Notation())
var v = r.getValues(); // get the data
// loop through the rows of data
for (var i = 0;i<AlastRow;i++){
if (v[i][2] != false) {
// the checkbox is ticked Don't sent an email
// Logger.log("DEBUG: i:"+i+", name = "+v[i][0]+" - the checkbox is ticked");
} else{
// the checkbox IS NOT ticked - send an email
//Logger.log("DEBUG: i:"+i+", name = "+v[i][0]+" checkbox = "+v[i][2]+" - the checkbox is NOT ticked");
var name = v[i][0];
var email = v[i][1];
//MailApp.sendEmail(email, "Test", "Hello " + name + ", This is an email");
Logger.log("DEBUG: mail sent to "+name+" at "+email)
var response = ui.alert("mail was send to "+name, ui.ButtonSet.OK);
v[i][2] = true;
}
}
r.setValues(v);
}

Merging data from multiple Google Sheets into one using script with array

I have multiple projects that output daily data to their own Google spreadsheets. I would like to make one master sheet in which this data is captured. This is fairly easy to do using importrange, but the spreadsheet becomes very, very slow when a large quantity of data is imported like this, so I'm hoping to use a script to just copy and paste the data over.
I know how to do set up the script manually using the following code from another post:
var sourceSpreadsheetID = "ID HERE";
var sourceWorksheetName = "SHEET NAME HERE";
var destinationSpreadsheetID = "ID HERE";
var destinationWorksheetName = "SHEET NAME HERE";
function importData() {
var thisSpreadsheet = SpreadsheetApp.openById(sourceSpreadsheetID);
var thisWorksheet = thisSpreadsheet.getSheetByName(sourceWorksheetName);
var thisData = thisWorksheet.getDataRange();
var toSpreadsheet = SpreadsheetApp.openById(destinationSpreadsheetID);
var toWorksheet = toSpreadsheet.getSheetByName(destinationWorksheetName);
var toRange = toWorksheet.getRange(1, 1, thisData.getNumRows(), thisData.getNumColumns())
toRange.setValues(thisData.getValues());
}
But ideally, I would like to make the list easy to expand using an array. I've set up an "import" table (see the figure below), so I would guess a for loop running through it would allow me to do this, but I'm not sure how.
Image of table
I'd really appreciate any help you guys can offer. Thanks!
To answer my own question, I've managed to cobble the following together and it seems to work:
function importData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var keysSheet = ss.getSheetByName("Keys")
var targetSheet = ss.getSheetByName("Test")
var keys = keysSheet.getRange("B2:B50").getValues();
var sheets = keysSheet.getRange("C2:C50").getValues();
var ranges = keysSheet.getRange("D2:D50").getValues();
var row, startcolumn = 1;
for (row = 1; row < 50; row++) {
if (keys[row-1] != '' && sheets[row-1] != '' && ranges[row-1] != '') {
var sourceSpreadsheetID = keys[row-1];
var sourceWorksheetName = sheets[row-1];
var sourceDataRange = ranges[row-1];
var thisSpreadsheet = SpreadsheetApp.openById(sourceSpreadsheetID);
var thisWorksheet = thisSpreadsheet.getSheetByName(sourceWorksheetName);
var thisData = thisWorksheet.getRange(sourceDataRange);
var toRange = targetSheet.getRange(1, startcolumn, thisData.getNumRows(), thisData.getNumColumns());
toRange.setValues(thisData.getValues());
startcolumn = startcolumn + thisData.getNumColumns();
}
}
}
I am sure that this can be done more efficiently using arrays, a while loop (rather than a for loop), and a keys table range that updates automatically based on its size, but I couldn't figure out how to do that with my high school coding skills.
Hopefully what I've figured out so far will help someone else!

xpages typeahead autocomplete

i couldnt do aautocopmlete edit box. i want to take names from another database. i wrote my code to typeahead's value list. but it dont work. i am using same server but different database.anybody help me ? here is my code:
//Getting the view containing a document for each of the employees
var searchView:NotesView = session.getDatabase("servername","test/application name.nsf")
.getView("viewname");
// Creating a Lotus Notes search query. Notice the reference to lupkey!
var query = "(FIELD Ad Soyad CONTAINS *" + lupkey +"*)";
// Creating an array to store hits in
var searchOutput:Array = ["å","åå"];
// Doing the actual search
var hits = searchView.FTSearch(query);
var entries = searchView.getAllEntries();
var entry = entries.getFirstEntry();
//Sort the array manually, since Notes doesn't want to sort them alphabetically
for (i=0; i<hits; i++) {
searchOutput.push(entry.getColumnValues()[0]);
entry = entries.getNextEntry();
}
searchOutput.sort();
// Build the resulting output HTML code
var result = "<ul><li><span class='informal'>Suggestions:</span></li></ul>";
var limit = Math.min(hits,20);
for (j=0; j<limit; j++) {
var name = searchOutput[j].toString();
var start = name.indexOfIgnoreCase(lupkey)
var stop = start + lupkey.length;
//Make the matching part of the name bold
name = name.insert("</b>",stop).insert("<b>",start);
result += "<li>" + name + "</li>";
}
result += "</ul>";
return result;
There are plenty of issues with your code:
the query can't return any result since your field has a space in it
Do you really need an FTSearch to return values and not a sorted view?
the typeahead -as the name suggest- presents values that match left to right and not somewhere substring. If you need that you need to roll your own typeahead function using Ajax
The typeahead function doesn't take a parameter, so your lupkey doesn't go anywhere. The function needs to return all values and XPages will do the matching
Instead of copying one by one into an array for sorting, copy the returning Vector() into a TreeSet(). This is one line, sorts it and removes duplicates
To get it working check this example based on dojo, previously asked here. You will need the REST control
i do it like that
var directoryTypeahead = function (searchValue:string) {
// update the following line to point to your real directory
//var directory:NotesDatabase = session.getDatabase(database.getServer(), "names.nsf");
var directory:NotesDatabase = session.getDatabase(database.getServer(), "org/test.nsf");
var allUsers:NotesView = directory.getView("SVFHP2");
var matches = {};
var includeForm = {
Person: true,
Group: true
}
searchValue = searchValue.replace("I","i")
var matchingEntries:NotesViewEntryCollection = allUsers.getAllEntriesByKey(searchValue, false);
var entry:NotesViewEntry = matchingEntries.getFirstEntry();
var resultCount:int = 0;
while (entry != null) {
var matchDoc:NotesDocument = entry.getDocument();
var matchType:string = matchDoc.getItemValueString("Form");
//if (includeForm[matchType]) { // ignore if not person or group
var fullName:string = matchDoc.getItemValue("Name").elementAt(0) + " " + matchDoc.getItemValue("Title").elementAt(0);
if (!(matches[fullName])) { // skip if already stored
resultCount++;
var matchName:NotesName = session.createName(fullName);
matches[fullName] = {
cn: matchName.getCommon(),
photo: matchDoc.getItemValueString("Photo"),
job: matchDoc.getItemValueString("sum"),
email: matchDoc.getItemValueString("email"),
}
}
// }
/*if (resultCount > 15) {
entry = null; // limit the results to first 10 found
}
else {*/
entry = matchingEntries.getNextEntry(entry);
//}
};
}

From Google Forms to Google Calendar - Date and TIme issues

I am trying to modify a script I found online that seems to make the event an all day event, which I don't want, I want it to be just the time specified in the form/spreadsheet.
The spreadsheet is located here - https://docs.google.com/spreadsheet/ccc?key=0ApxazoOhNSK-dGFvZVhVOTQ1X3F3aWh4QTh3Wm9sbFE#gid=0
Here is the script I am using, but its not adding...
//this is the ID of the calendar to add the event to, this is found on the calendar settings page of the calendar in question
var calendarId = "<removed for privacy>";
//below are the column ids of that represents the values used in the spreadsheet (these are non zero indexed)
var startDtId = 4;
var endDtId = 4;
var titleId = 2;
var titleId2 = 3;
var descId = 7;
var tstart = 4;
var tstop = 5;
var formTimeStampId = 1;
function getLatestAndSubmitToCalendar() {
var start = new Date(sheet.getRange(lr,tstart,1,1).getValue());
var end = new Date(sheet.getRange(lr,tstop,1,1).getValue());
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var lr = rows.getLastRow();
var subOn = "Submitted on :"+sheet.getRange(lr,formTimeStampId,1,1).getValue()+" by "+sheet.getRange(lr,titleId,1,1).getValue();
var desc = "Comments: "+sheet.getRange(lr,descId,1,1).getValue()+"\n"+subOn;
var title = sheet.getRange(lr,titleId,1,1).getValue()+" "+sheet.getRange(lr,titleId2,1,1).getValue();
createEvent(calendarId,title,start,end,desc);
}
function createEvent(calendarId,title,start,end,desc) {
var cal = CalendarApp.getCalendarById(calendarId);
var start = new Date(sheet.getRange(lr,tstart,1,1).getValue());
var end = new Date(sheet.getRange(lr,tstop,1,1).getValue());
var loc = 'Computer Center';
var event = cal.createEvent(title, start, end, {
description : desc,
location : loc
});
};
The original article is located here: http://bruceburge.com/2012/09/05/automatically-adding-events-to-a-google-calendar-from-a-google-form-submission/
I just can't seem to get the dates to work at all... If I use the original code it works fine, but the time is the full day, not the specified time... I seem to have broken it in an attempt to make it work... Any help would be appreciated...
It was a lot simpler than I though... I just removed some of his lines (the ones that set the hour and minutes to 0. Once I removed that and changed a few things, I get the following which works just great:
//this is the ID of the calendar to add the event to, this is found on the calendar settings page of the calendar in question
var calendarId = "alcc.ccenter#gmail.com";
//below are the column ids of that represents the values used in the spreadsheet (these are non zero indexed)
var startDtId = 4;
var endDtId = 5;
var titleId = 2;
var titleId2 = 3;
var descId = 7;
var formTimeStampId = 1;
function getLatestAndSubmitToCalendar() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();
var lr = rows.getLastRow();
var startDt = sheet.getRange(lr,startDtId,1,1).getValue();
//set to first hour and minute of the day.
var endDt = sheet.getRange(lr,endDtId,1,1).getValue();
//set endDt to last hour and minute of the day
var subOn = "Added :"+sheet.getRange(lr,formTimeStampId,1,1).getValue()+" by: "+sheet.getRange(lr,titleId,1,1).getValue();
var desc = "Comments :"+sheet.getRange(lr,descId,1,1).getValue()+"\n"+subOn;
var title = sheet.getRange(lr,titleId,1,1).getValue()+" - "+sheet.getRange(lr,titleId2,1,1).getValue();
createEvent(calendarId,title,startDt,endDt,desc);
}​
function createEvent(calendarId,title,startDt,endDt,desc) {
var cal = CalendarApp.getCalendarById(calendarId);
var start = new Date(startDt);
var end = new Date(endDt);
var loc = 'Computer Centre';
var event = cal.createEvent(title, start, end, {
description : desc,
location : loc
});
};
My form has the following Columns - Timestamp, Name, Absence, Start, End, Reason, Comments. They didn't need to be ne word but I changed them to one word headings because of the video example I was trying to follow... But the above code works miracles.
I had to modify the way Forms handles dates to accommodate Calendar
function createEvent() {
var form = FormApp.getActiveForm();
var cal = CalendarApp.getDefaultCalendar();
var responses = form.getResponses();
var len = responses.length;
var last = len – 1;
var items = responses[last].getItemResponses();
var email = responses[last].getRespondentEmail();
var name = items[0].getResponse();
var bring = items[1].getResponse();
var date = items[2].getResponse();
Logger.log(date);
var replace = date.replace(/-/g,”/”);
Logger.log(replace);
var start = new Date(replace);
Logger.log(‘start ‘+start);
//Logger.log(newStart.getHours());
var endHours = 2+0+start.getHours();
//Logger.log(start.getDay());
var day = start.getDate();
var minutes = start.getMinutes();
var year = start.getFullYear();
var month = start.getMonth();
var hours = start.getHours();
var d = new Date(year, month, day, endHours, minutes);
Logger.log(d);
var event = cal.createEvent(‘Class Party ‘+name+’ brings ‘+bring, start, d)
.addGuest(email)
.setDescription(name+’ you will be bringing ‘+bring+’ to the party.’);
GmailApp.sendEmail(email, name + ’ a Google Calendar invite has been created for you’, name + ’ You filled out the Google Form for the date of ‘ + start + ’. Check your Google Calendar to confirm that you received the invite.\n’);
}

Flex 4 Send and load variables to a new window

I want to post some variables to a new window.
The receiving c# will then generate a CSV which will stream as a download.
In flex this used to be achieved using loadVars and specifying _blank as the target.
I currently use the following:
var myRequest:URLRequest = new URLRequest(url);
var myLoader:URLLoader = new URLLoader();
var myVariables:URLVariables = new URLVariables();
myVariables.CurrentActiveUserID = currentUserID
myVariables.ReportRuleListID = SingleChartID
myRequest.method = URLRequestMethod.POST;
myRequest.data = myVariables;
myLoader.load(myRequest);
But it does not seem to support targeting of new windows.
Any ideas.
Please and thank you.
I finally sorted it with:
private function sendAndLoadCSVData():void {
var swfURL:String = this.loaderInfo.url;
swfURL = swfURL.substr(0,swfURL.lastIndexOf("/") + 1);
var tempDom:Array = swfURL.split("/");
var domURL:String = tempDom.slice(0,3).join("/") + "/";
var url:String = swfURL + "../Reporting/ExportChartCSV.aspx"
// var post_variable:LoadVars = new LoadVars();
var myRequest:URLRequest = new URLRequest(url);
var myLoader:URLLoader = new URLLoader();
var myVariables:URLVariables = new URLVariables();
myVariables.CurrentActiveUserID = currentUserID
myVariables.ReportRuleListID = SingleChartID
myRequest.method = URLRequestMethod.POST;
myRequest.data = myVariables;
navigateToURL(myRequest, '_blank')
//myLoader.load(myRequest);
// Alert.show(url);
}