I have a code that retrieves project ID from specific column and uses it on API call to get more data that needs to be appended starting from the last column with data.
Here is the code that reads above column and uses it for API call
function readDates() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getRange("F2:F" + sheet.getLastRow()).getValues();
var searchString = "Project";
var contents = [];
var team_array = [];
for (var i = 0; i < range.length; i++) {
var lastRow = sheet.getRange(2 + i, 1, 1, 8).getValues();
var data = {'project_id': lastRow[0][3]};
var options = {method: 'get',headers: {Authorization: 'Bearer ' + TKF_AUTH}};
var url = TKF_URL + Endpoint + data.project_id + '/users?auth=' + TKF_AUTH
var response = UrlFetchApp.fetch(url, options);
var team = JSON.parse(response);
var content = team.data;
team_array.push(content);
contents = contents.concat(content);
}
The response needs to be appended from column G, row 2 but this is what I find challenging to do and any help will be appreciated here. Take a look at my code blow does, which is not what I intended.
if (contents.length > 0 ) {
var dstSheet = SpreadsheetApp.getActive().getSheetByName('Projects');
var values = contents.map(e => ([e.id, e.first_name, e.last_name, e.display_name, e.email, e.user_type_id, e.role]));
var new_values=values.filter(item=>{
if(item[6] == 'Project Leader' || item[6] == 'Senior Project Leader')
{
return true
}
})
dstSheet.getRange(7, 1, new_values.length, new_values[0].length).setValues(new_values);// How do I structure this part to ensure it starts seting values from column G
}Logger.log(contents.map)
}
Is this what you're looking for:
function readDates() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var vA = sheet.getvA(2,1,sheet.getLastRow()-1,sheet.getLastColumn()).getValues();
var w=sheet.getLastColumn();
for (var i = 0;i<vA.length;i++) {
var options = {method: 'get',headers: {Authorization: 'Bearer ' + TKF_AUTH}};
var url = TKF_URL + Endpoint + vA[i][3] + '/users?auth=' + TKF_AUTH
var response = UrlFetchApp.fetch(url, options);
var team = JSON.parse(response.getContentText());
var v=vA.slice(0,7);
vA[i]=v.concat(team.data);//assume team.data is an array
if(vA[i].length>w){w=vA[i].length;}
}
sh.getRange(2,1,vA.length,w).setValues(vA);
}
It would be nice to see what the return data looks like and if possible could we create headers that we can use to place the data correctly in the extended columns.
Related
I am sending a Google sheet Tab to students and it is working fine. But before sending it to them, I need to sort the sheet using Column3 value and then remove column2, column4, column5, column7. But it shows errors:
"TypeError: The comparison function must be either a function or
undefined" at contents.sort() and contents.delete() in the codes
below.
I reviewed many posts but can't figure out the issue.
Function sendEmails(){
var sss = SpreadsheetApp.getActiveSpreadsheet();
var ssID = sss.getId();
var sheetName = sss.getName();
var sh = SpreadsheetApp.getActive();
var sheet1 = sh.getSheetByName("TempDataSet");
var shID = sheet1.getSheetId().toString();
var subject = 'Your Attendance Record at BDU';
var body = 'Dear Student,'+ '\n\n' + 'Greetings! Please find the attendance record attached for your reference.' + '\n\n' + 'Thank you.';
var requestData = {"method": "GET", "headers":{"Authorization":"Bearer "+ScriptApp.getOAuthToken()}};
var url = "https://docs.google.com/spreadsheets/d/"+ ssID + "/export?format=xlsx&id="+ssID+"&gid="+shID;
var result = UrlFetchApp.fetch(url , requestData);
var contents = result.getContent();
var column = 3;
contents.sort({column: column, ascending:true});
contents.delete({column: column2, column4, column5, column7});
var sheet2 = sh.getSheetByName('StudentList');
var data = sheet2.getLastRow();
var students = [];
var students = sheet2.getRange(2, 6, data).getValues();
for (var i=0; i<students.length; i++){ // you are looping through rows and selecting the 1st and only column index
if (students[i][0] !== ''){
MailApp.sendEmail(students[i][0].toString(), subject ,body, {attachments:[{fileName:sheetName+".xlsx", content:contents, mimeType:"application//xlsx"}]});
}
}
}
Explanation:
My suggestion would be to just create a copy of the TempDataSet sheet and do all the sort and delete columns operations on that sheet:
var sh = SpreadsheetApp.getActive();
var sheet = sh.getSheetByName("TempDataSet");
var sheet1 = sheet.copyTo(sh).setName('TempDataSet_temp');
var shID = sheet1.getSheetId().toString();
sheet1.getRange(2, 1, sheet.getLastRow() -1, sheet.getLastColumn()).sort({column: 3, ascending: true});
var columns_delete = [7,5,4,2];
columns_delete.forEach(col=>sheet1.deleteColumn(col));
then you can delete the temporary sheet after you saved it in the result variable:
sh.deleteSheet(sh.getSheetByName('TempDataSet_temp'))
Solution:
function sendEmails(){
var sss = SpreadsheetApp.getActiveSpreadsheet();
var ssID = sss.getId();
var sheetName = sss.getName();
var sh = SpreadsheetApp.getActive();
var sheet = sh.getSheetByName("TempDataSet");
var sheet1 = sh.insertSheet('TempDataSet_temp');
sheet.getDataRange().copyTo(sheet1.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_VALUES, false);
sheet.getDataRange().copyTo(sheet1.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_FORMAT, false);
var shID = sheet1.getSheetId().toString();
sheet1.getRange(2, 1, sheet.getLastRow() -1, sheet.getLastColumn()).sort({column: 3, ascending: true});
var columns_delete = [7,5,4,2];
columns_delete.forEach(col=>sheet1.deleteColumn(col));
var subject = 'Your Attendance Record at BDU';
var body = 'Dear Student,'+ '\n\n' + 'Greetings! Please find the attendance record attached for your reference.' + '\n\n' + 'Thank you.';
var requestData = {"method": "GET", "headers":{"Authorization":"Bearer "+ScriptApp.getOAuthToken()}};
var url = "https://docs.google.com/spreadsheets/d/"+ ssID + "/export?format=xlsx&id="+ssID+"&gid="+shID;
var result = UrlFetchApp.fetch(url , requestData);
var contents = result.getContent();
sh.deleteSheet(sh.getSheetByName('TempDataSet_temp'))
var sheet2 = sh.getSheetByName('StudentList');
var data = sheet2.getLastRow();
var students = [];
var students = sheet2.getRange(2, 6, data).getValues();
for (var i=0; i<students.length; i++){ // you are looping through rows and selecting the 1st and only column index
if (students[i][0] !== ''){
MailApp.sendEmail(students[i][0].toString(), subject ,body, {attachments:[{fileName:sheetName+".xlsx", content:contents, mimeType:"MICROSOFT_EXCEL"}]});
}
}
}
first time poster so I apologise if if im not following the correct etiquette.
So I have code that, in essence, creates 70 forecast docs in specified folders. This works fine.
I have used the same code, repointed the all the folder references, but now times out.
Code is as follows, any suggestions on how I can make this run faster?
function createFiles(weeknr, masterIDs, masterfolders, mastercodes, archivefolders) {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var date = new Date()
var textdate = Utilities.formatDate(date, "Europe/London", "dd/MM/YYYY HH:mm")
var fileslog = ss.getSheetByName("FileList")
var year = date.getYear()
var mainfolder = DriveApp.getFolderById("1HdG3eJZrIMF-CRpx17Reqdyd7JM5v5ZW")
var weekfolder = mainfolder.createFolder('Week ' + weeknr + ' ' + year)
var tempArray = []
for (var i = 0; i < masterIDs.length; i++) {
// for (var i=0;i<masterIDs.length;i++){
var folderID = masterfolders[i]
var masterID = masterIDs[i]
var code = mastercodes[i]
var archivefolder = archivefolders[i]
var newfile = DriveApp.getFileById(masterID).makeCopy(code + ' DCS WK' + weeknr,
DriveApp.getFolderById(folderID))
var newID = newfile.getId()
tempArray.push([newfile.getName(), newID, newfile.getUrl(),
newfile.getDateCreated(), "Created", folderID, archivefolder, weeknr])
SpreadsheetApp.openById(newID).getSheetByName("Main").getRange(3, 3).setValue(weeknr)
weekfolder.addFile(newfile)
//NEW UPDATE 14/02 to set the owner to network finance
newfile.setOwner('network.finance#dpdgroup.co.uk')
//End of UPDATE
fileslog.getRange(fileslog.getLastRow() + 1, 1, 1, 8).setValues([tempArray[i]])
}
// Logger.log(tempArray )
// if(tempArray.length>0){
// fileslog.getRange(fileslog.getLastRow()+1, 1, tempArray.length,
8).setValues(tempArray)
// }
}
function archiveFiles(weeknr, fileIDs, masterfolders, mastercodes, archivefolders) {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var date = new Date()
var textdate = Utilities.formatDate(date, "Europe/London", "dd/MM/YYYY HH:mm")
var fileslog = ss.getSheetByName("FileList")
//var year = date.getYear()
//var mainfolder = DriveApp.getFolderById("1HdG3eJZrIMF-CRpx17Reqdyd7JM5v5ZW")
//var weekfolder = mainfolder.createFolder('Week '+weeknr+' '+year)
var tempArray = []
for (var i = 0; i < fileIDs.length; i++) {
// for (var i=0;i<masterIDs.length;i++){
var folderID = masterfolders[i]
var fileID = DriveApp.getFileById(fileIDs[i])
var code = mastercodes[i]
var archivefolder = archivefolders[i]
DriveApp.getFolderById(archivefolder).addFile(fileID)
DriveApp.getFolderById(folderID).removeFile(fileID)
//var newfile = DriveApp.getFileById(masterID).makeCopy(code + ' DCS WK'+weeknr,
DriveApp.getFolderById(folderID))
//var newID = newfile.getId()
tempArray.push([fileID.getName(), fileIDs[i], fileID.getUrl(),
fileID.getLastUpdated(), "Archived", masterfolders[i], archivefolders[i], weeknr])
//weekfolder.addFile(newfile)
}
Logger.log(tempArray)
if (tempArray.length > 0) {
fileslog.getRange(fileslog.getLastRow() + 1, 1, tempArray.length, 8).setValues(tempArray)
}
}
Posted the answer for documentation purpose.
As discussed in the comments the problem was the file size, splitting the copied files in batches did the trick:
So turns out, the file was simply too large to create 70 files in the allotted time. So I split it down to batches of 30 and its worked perfectly. thanks for your help
I want to fetch data from a google sheet data dump/master sheet. There is a sheet for each month. Import/match the data to columns that are in a different order in another sub spreadsheet and put all months on one sheet. Lastly, I want to filter the data by person, status and date, so only these items will show unless Cell H1 is populated. If cell H1 is populated and not null, all data that meets the criteria will be shown.
Master: https://docs.google.com/spreadsheets/d/1nIzCqQUL1K4HwYUGV0jxjJjLKSFaeqVn27f_pkoL9j0/edit?usp=sharing
Subsheet:https://docs.google.com/spreadsheets/d/1-V0F_pJTKFmP8jRBwpIzBe_sP7GbC-314oUB97N0K-0/edit#gid=0
function Importmatchfilter() {
// source sheet
var ss = ('1nIzCqQUL1K4HwYUGV0jxjJjLKSFaeqVn27f_pkoL9j0/edit#gid=1395833187');
var ssn1 = ss.getSheetByName('April'); ('A:Z')
var ssn2 = ss.getSheetByName('May'); ('A:Z')
var ssn3 = ss.getSheetByName('June'); ('A:Z')
var ssn4 = ss.getSheetByName('July'); ('A:Z')
var ssn5 = ss.getSheetByName('August'); ('A:Z')
var ssn6 = ss.getSheetByName('September'); ('A:Z')
var ssn7 = ss.getSheetByName('October'); ('A:Z')
var ssn8 = ss.getSheetByName('November'); ('A:Z')
var ssn9 = ss.getSheetByName('December'); ('A:Z')
// Get full range of data
var SRange1 = ssn1.getDataRange();
var SRange2 = ssn2.getDataRange();
var SRange3 = ssn3.getDataRange();
var SRange4 = ssn4.getDataRange();
var SRange5 = ssn5.getDataRange();
var SRange6 = ssn6.getDataRange();
var SRange7 = ssn7.getDataRange();
var SRange8 = ssn8.getDataRange();
var SRange9 = ssn9.getDataRange();
// get A1 notation identifying the range
var A1Range = SRange1.getA1Notation();
var A1Range1 = SRange1.getA1Notation();
var A1Range2 = SRange2.getA1Notation();
var A1Range3 = SRange3.getA1Notation();
var A1Range4 = SRange4.getA1Notation();
var A1Range5 = SRange5.getA1Notation();
var A1Range6 = SRange6.getA1Notation();
var A1Range7 = SRange7.getA1Notation();
var A1Range8 = SRange8.getA1Notation();
var A1Range9 = SRange9.getA1Notation();
// get the data values in range
var SData1 = SRange1.getValues();
var SData2 = SRange2.getValues();
var SData3 = SRange3.getValues();
var SData4 = SRange4.getValues();
var SData5 = SRange5.getValues();
var SData6 = SRange6.getValues();
var SData7 = SRange7.getValues();
var SData8 = SRange8.getValues();
var SData9 = SRange9.getValues();
// target sheet
var ts = tss.getSheetByName('Sheet1');
function listMajors() {
gapi.client.sheets.spreadsheets.values.get({
spreadsheetId: '1-V0F_pJTKFmP8jRBwpIzBe_sP7GbC-314oUB97N0K-0',
range: A1
}).then(function(response) {
var range = response.result;
if (range.values.length > 0) {
appendPre('Due date, Status, Address:');
for (i = 0; i < range.values.length; i++) {
var row = range.values[i];
appendPre(row[0] + ', ' + row[4]);
function getheaderValues(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet2');
var range = sheet.getRange("A:Z");
var allOfColumnAz = range.getValues()
for (var i = 1; i < 10 ; i++){
var sData = eval("SData"+i);
var lastRow = ts.getLastRow();
var numRows = sData.length;
var numCols = sData[0].length;
ts.getRange(lastRow+(lastRow > 0 ? 2 : 1), 1, numRows, numCols).setValues(sData);
}}
So I've been working on this code that will check a google sheet for a date two weeks from now and send a reminder. The first time I run the code, it works great. The problem is, the second time I run the code it ignores the duplicate checker and then sends an email using data from a row that has already been sent. I'm trying to figure out A) why is it doing that, and B) how do I fix it.
function sendEmails3() {
var today = new Date();
today.setDate(today.getDate() + 14); // Today's date, without time
today = today.toLocaleDateString();
var EMAIL_SENT = "EMAIL_SENT";
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow() - 1; // Number of rows to process
// Fetch the range of cells A2:B999
var dataRange = sheet.getRange(startRow, 1, numRows, 999)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[0]; // First column
var firstName = row[1]; // Second column
var lastName = row[2]; // Third column
var event1 = row[4];
var event2 = row[6];
var event3 = row[8];
var emailSent = row[9];
var sheetDate1 = row[13].toLocaleDateString();
var sheetDate2 = row[14].toLocaleDateString();
var sheetDate3 = row[15].toLocaleDateString();
Logger.log(sheetDate1)
if (sheetDate1 == today) {
var event = event1;
var sheetDate = sheetDate1;
} else if (sheetDate2 == today) {
var event = event2;
var sheetDate = sheetDate2;
} else if (sheetDate3 == today) {
var sheetDate = sheetDate3;
var event = event3;
}
if (sheetDate != today) {
continue;
}
Logger.log(sheetDate)
Logger.log(event)
Logger.log(emailAddress)
if (emailSent != "EMAIL_SENT") { // Prevents sending duplicates
var subject = "Reminding you that your " + event + " is coming up on " +
sheetDate + "!";
MailApp.sendEmail(emailAddress, subject, "", {
htmlBody: slsdf
});
sheet.getRange(startRow + i, 10).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
var sheetDate = "";
Logger.log(sheetDate)
var event = "";
}
}
}
please ignore the garbage in the part where its supposed to be emailing html, it's juts a huge pile of html and shouldn't effect anything.
Hello all I'm having trouble implementing array loops in my project... Here is what I want to do.
I have a spreadsheet called "Red Book" this sheet gets updated regularly once the staff have updated it I have a column where they can select to submit the data they've just entered on that specific row (editing this column calls an onEdit function).
The data will then be written to another spreadsheet (different file) called "Raw Data"
For each submit I have a unique identifier. I need the onEdit code to do the following...
Iterate through the column A to find the unique identifier
Once found update the data in columns 1 through 5
Below is the script I have so far:
function TransferToAppData(e) {
var destFile = SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx');
var destSheet = destFile.getSheetByName("Raw App Data");
var ss = e.source;
var s = ss.getActiveSheet();
var uniConstRng = s.getRange("A1");
var uniqueConstVal = uniConstRng.getValue();
var NextOpenRow = destSheet.getLastRow() + 1;
var ActiveRow = e.range.getRow();
Logger.log(ActiveRow);
var uniqueVal = s.getRange(ActiveRow,1).getValue();
var add = s.getRange(ActiveRow,2).getValue();
var name = s.getRange(ActiveRow,3).getValue();
var dt = s.getRange(ActiveRow,5).getValue()
if (uniqueVal == "") {
s.getRange(ActiveRow,1).setValue(uniqueVal + 1);
uniConstRng.setValue(uniqueVal + 1);
var transferVals = s.getRange(ActiveRow,1,1,5).getValues();
Logger.log(transferVals);
destSheet.getRange(NextOpenRow,1,1,5).setValues(transferVals);
destSheet.getRange(NextOpenRow, 6).setValue("Applicant");
}
else {
var destLastRow = destSheet.getLastRow();
var destDataRng = destSheet.getRange(2,1,destLastRow,5)
var destValues = destDataRng.getValues();
var sourceValues = s.getRange(ActiveRow,1,1,5).getValues();
for( var i = 0; i < destValues.length; ++i){
if (destValues([i][0])==uniqueVal) {
for(n=0;n<destValues[0].length;++n){
///I"m stuck!!!
}
}
}
}
}
As you can see I have the first array loop going, but I'm having trouble figuring out how to do a second loop that iterates only on the row where the unique value is found and write the source data to ONLY to row where the unique value was found not the whole sheet.
I figured it out...
Below is the code and here is how it works...
When values in certain columns are edited this code is fired.
1--It finds the unique identifier located in the row which was edited.
2--Compares that identifier with a column of unique identifiers in another spreadsheet.
3--When a match is found it writes the change to the new spreadsheet and exits the loop
function TransferToAppData(e) {
var destFile = SpreadsheetApp.openById('1V3R2RnpA8yXmz_JDZSkBsK9tGR2LjHZp52p5I1CuQvw');
var destSheet = destFile.getSheetByName("Raw App Data");
var ss = e.source;
var s = ss.getActiveSheet();
var uniqueConstRng = s.getRange("A1");
var uniqueConstVal = uniqueConstRng.getValue();
var NextOpenRow = destSheet.getLastRow() + 1;
var ActiveRow = e.range.getRow();
var uniqueVal = s.getRange(ActiveRow,1).getValue();
if (s.getRange(ActiveRow,2).getValue() == "" || s.getRange(ActiveRow,3).getValue()=="" || s.getRange(ActiveRow,4).getValue()=="" || s.getRange(ActiveRow,5).getValue()=="") {
s.getRange(ActiveRow,13).clearContent();
Browser.msgBox("Address, Name, Date Entered & Rent are required fields!");
} else{
if (uniqueVal == "") {
s.getRange(ActiveRow,1).setValue(uniqueConstVal + 1);
uniqueConstRng.setValue(uniqueConstVal + 1);
var transferVals = s.getSheetValues(ActiveRow,1,1,5);
destSheet.getRange(NextOpenRow,1,1,5).setValues(transferVals);
destSheet.getRange(NextOpenRow, 6).setValue("Applicant");
}
else {
var destLastRow = destSheet.getLastRow();
var destValues = destSheet.getSheetValues(2,1,destLastRow,5);
var sourceValues = s.getSheetValues(ActiveRow,1,1,5);
for(var i = 0; i < destValues.length; ++i){
if (destValues[i][0]===uniqueVal) {
destSheet.getRange(i+2,1,1,5).setValues(sourceValues);
break;
}
}
}
s.sort(1,false);
destSheet.sort(1,false);
}
}