I'm trying to fetch stock prices from the web and save them automatically every five minutes or so. I've succeeded with the importXML() and the Google Sheets triggers but I do encounter ERRORS quite often. The problems seem to rise when saving the values from the imported cells to a new column at the end of the spreadsheet. Sometimes it all works fine, but sometimes some cells get an error and sometimes I get ERROR in all the cells.
This is the Google script I'm using:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var queryString = Math.random();
for (var i=2; i <= 14; i++) {
var cell = '=IMPORTXML("' + 'http://www.netfonds.no/quotes/ppaper.php?paper=' + sheet.getRange('B' + i + '').getValue() + '.ST&' + queryString + '","' + sheet.getRange('A' + i + '').getValue() + '")';
sheet.getRange('C' + i + '').setValue(cell);
}
var datarange = sheet.getDataRange();
var numColumns = datarange.getNumColumns();
var nextColumn = numColumns + 1;
sheet.getRange(1, nextColumn).setValue(new Date());
SpreadsheetApp.flush();
sheet.getRange(2, numColumns + 1, 13, 1).setValues(sheet.getRange(2, 4, 13, 1).getValues());
}
And here is the spreadsheet.
In this Question I found out that adding a Browser.msgBox("hey!") and a clear() could help. But it still gives me errors trying it out unfortunately.
Related
been using MailApp script to automatically send emails from within a google sheet for several years. developed my script from an example i found online and reverse engineered it until i could make it work (i am not a coder!). worked brilliantly for months/years...
but recently it is no longer functioning. i get a daily email summary of errors which states that EMAIL_SENT is not defined, but when running the script in debug mode it times out after the logger.log(user) - so does appear to hang on the EMAIL_SENT variable.
As i say, this has been running brilliantly for many months, but appears to have stopped around july 22nd.
i have included the script below in case it is something simple:
function autoemailES() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("ESautoemail");
//var lastRow = sheet.getLastRow();
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow() -1; // Number of rows to process
var EMAIL_SENT = 'EMAIL_SENT';
// Fetch the range of cells A2:G
var dataRange = sheet.getRange(startRow, 1, numRows, 30);
// 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 emailSent = row[7]; // 8th column
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates
var superMail = row[2]; // 3rd column
var responseNo = row[3]; // 4th column
var user = row[0]; // 1st column
var firstName = row[1]; // 2nd column
var pdfLink = row[5]; // 6th column
var pdfID = row[6]; // 7th column
Logger.log(responseNo) //these logger lines just display the values for each of the variables in debugging
Logger.log(superMail)
Logger.log(user)
Logger.log(pdfLink)
Logger.log(pdfID)
var file = DriveApp.getFileById(pdfID);
var subject = 'IBTPHEM MSF results for ' + user;
var message = 'Dear Educational Supervisor,' + "\n" +
'This is an automated notification that your trainee, ' + firstName + ', has now received a quorate number of MSF responses.'+"\n"+
'The anonymised summary of responses is attached in PDF format, or can be downloaded from the link below.'+"\n" + pdfLink +"\n"+
'Further submissions will be added automatically (the trainee is notified for each), but the pdf will need downloading again'+"\n"+
'Please feel free to share this with your trainee however you see fit - we are now releasing the results via the ES in case there is any feedback that may require debriefing or handling more delicately.'+"\n"+
'Please do let me know of any problems or concerns?'+"\n"+
'Kind Regards,' + "\n" +
'IBTPHEM MSF'
MailApp.sendEmail(superMail,subject, message,{
name: 'IBTPHEM MSF',
replyTo: 'dr_nick#doctors.org.uk',
attachments: [file.getAs(MimeType.PDF)]});
sheet.getRange(startRow + i, 8).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
}
I would be really grateful for any help to identify my problem.
thanks!
dr_nick
(i cannot easily share the sheet in its entirity as it contains a fair bit of senstive/confidential information - though I suppose I could make an anonymised version if this is necessary/helpful?)
This is the same script with a try catch block. It will only log things if you have an error.
function autoemailES() {
const ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("ESautoemail");
var startRow = 2;
var EMAIL_SENT = 'EMAIL_SENT';
var dataRange = sheet.getRange(startRow, 1, sheet.getLastRow() - startRow + 1, 30);
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
try{
var row = data[i];
var emailSent = row[7];
if (emailSent !== EMAIL_SENT) {
var superMail = row[2];
var responseNo = row[3];
var user = row[0];
var firstName = row[1];
var pdfLink = row[5];
var pdfID = row[6];
var file = DriveApp.getFileById(pdfID);
var subject = 'IBTPHEM MSF results for ' + user;
var message = 'Dear Educational Supervisor,' + "\n" +
'This is an automated notification that your trainee, ' + firstName + ', has now received a quorate number of MSF responses.' + "\n" +
'The anonymised summary of responses is attached in PDF format, or can be downloaded from the link below.' + "\n" + pdfLink + "\n" +
'Further submissions will be added automatically (the trainee is notified for each), but the pdf will need downloading again' + "\n" +
'Please feel free to share this with your trainee however you see fit - we are now releasing the results via the ES in case there is any feedback that may require debriefing or handling more delicately.' + "\n" +
'Please do let me know of any problems or concerns?' + "\n" +
'Kind Regards,' + "\n" +
'IBTPHEM MSF'
MailApp.sendEmail(superMail, subject, message, {
name: 'IBTPHEM MSF',
replyTo: 'dr_nick#doctors.org.uk',
attachments: [file.getAs(MimeType.PDF)]
});
sheet.getRange(startRow + i, 8).setValue(EMAIL_SENT);
SpreadsheetApp.flush();
}
}
catch(e){
Logger.log('responseNo: %s\nsuperMail: %s\nuser: %s\npdfLink:%s\npdfID: %s',responseNo,superMail,user,pdfLink,pdfID);
Logger.log(e);
}
}
}
Try setting up another spreadsheet and adjust the data so that it doesn't send data to your clients and see if it will generate any errors. Also if you could share a copy of the new spreadsheet as a markdown table that would enable us to test it a little. But be careful about sharing private information
New to Apps Script and want to write a simple function to test the waters. Unfortunately, I am having some difficulties. I want the function to check column E and see if there is existing data. If yes, I want it to add a formula to the column next to it. Else do nothing and check the next row. When running the code listed below I get a Error:
Exception: The starting row of the range is too small.
Could somebody please point out what exactly I am doing wrong?
function dateToColumn() {
var ss = SpreadsheetApp.openById(dbGoogleSheet);
Logger.log('Google Sheet database used' + ' ' + ss.getName());
var dataSheet = ss.getSheetByName('Form Responses 1')
Logger.log(dataSheet.getName());
var rangeData = dataSheet.getDataRange();
var lastColumn = rangeData.getLastColumn();
var lastRow = rangeData.getLastRow();
var searchRange = dataSheet.getRange(2, 5, lastRow - 1, lastColumn - 1);
if (dataSheet.getName() === "Form Responses 1") {
var rangeValues = searchRange.getValues();
//Logger.log(rangeValues)
for (i = 0; i < lastColumn - 1; i++) {
for (j = 0; j < lastRow - 1; j++) {
// Logger.log(dataSheet.getRange(j,i));
if (rangeValues[j][i] !== null) {
dataSheet.getRange(j, i++).setFormula(`=YEAR(` + j, i + `)`);
}
}
}
} else {
return;
}
};
The problem is that j is been initialized as 0 and it's being used in a getRange. The minimal value is 1.
Please bear in mind that Arrays uses 0 based indexes while getRange and other SpreadsheetApp methods use 1 based "indexes".
Apart from the point mentioned in the other answer, you should also be aware of the i index.
Moreover, you are passing a wrong parameter to the setFormula method. So depending on how exactly you want to use the YEAR formula, you should reformat it accordingly.
Therefore, you should be changing this line:
dataSheet.getRange(j, i++).setFormula(`=YEAR(` + j, i + `)`);
To:
dataSheet.getRange(j+1, i+2).setFormula('=YEAR(' + (j, i) + ')');
Reference
Apps Script Sheet Class - getRange();
YEAR formula.
Forgive the basic question, but after 15 attempts at different variations, I come here with this.. Full code below, but the following statement
if (data[i][11] <> "YES")
does not seem to be executing properly in any of the various methods I've tried, I am sure I am doing something wrong somewhere else in this script but for the life of me cannot see it. Hoping a new set of eyes can help..
I am trying to collect data on Sheet A, process it and place it on Sheet B, and update a key in Sheet A. If the script is run again, it should not pick up Sheet A's already processed items (via the Key - currently in the 12th column and indicated as "YES"). In each instance the script continued to process all rows regardless of if it - leading me to think it isn't actually the conditions I am providing..
Hope this is clear. Appreciate any push in the right direction.
Another of the attempts:
var jiraupdated = data[i][11];
if (jiraupdated !== UPDATED)
//and various similar replacing with different types, methods, etc.
Full script:
var UPDATED = "YES";
function formatJIRASheet() {
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = sheet.getLastRow();
var startRow = 2; // First row of data to process
var numRows = lastRow-1; // Number of rows to process
// Fetch the range of cells
var dataRange = sheet.getRange(startRow, 1, numRows, lastRow); //rowCount for data
// Fetch values for each row in the Range.
var data = dataRange.getValues();
var ss=SpreadsheetApp.getActive();
var sh1=ss.getSheetByName('JIRA Sheet');
for (var i = 0; i < data.length; ++i) {
// Fetch values on initial data
var row = data[i];
var date = row[1]; // 2nd col
var customername = row[2]; //3rd col
var test = row[3];
var testt = row[4];
var summary = row[5];
var actualoutcome = row[6];
var exptoutcome = row[7];
var customeremail = row[8];
// Form new description (merge of other fields)
var description = (date + " " + dftdescription + " " + test + " " + testt + " " + actualoutcome + " " + exptoutcome); // target col 2
// This is the failing check, continuing to write records to next sheet even though they've already been covered in previous runs. I've tried maybe 15 different methods to fix this and have came up short.
if (data[i][11] <> "YES") {
sh1.appendRow([null, "Bug", null, summary, description, customeremail, customername, null, null, null, null, null, "Low", "Low", null, null, null, null, null]);
sheet.activate();
sheet.getRange(startRow + i, 12).setValue(UPDATED);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
Try this:
function formatJIRASheet() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet1');
const sr=2;
const rg=sh.getRange(sr,1,sh.getLastRow()-sr+1,sh.getLastColumn());
const v=rg.getValues();
const sh1=ss.getSheetByName('Sheet2');
v.forEach(function(row,i){
var date=row[1];
var customername=row[2];
var test=row[3];
var testt=row[4];
var summary=row[5];
var actualoutcome=row[6];
var exptoutcome=row[7];
var customeremail=row[8];
var description=(date + " " + "undefined" + " " + test + " " + testt + " " + actualoutcome + " " + exptoutcome);
if(row[11]!="YES") {
sh1.appendRow(['',"Bug",'',summary,description,customeremail,customername,'','','','','',"Low","Low",'','','','','']);
sh.getRange(sr + i, 12).setValue("YES");
}
});
SpreadsheetApp.flush();
}
I'm trying to set dynamic getRange function, so I use getRange(row, column, numRows, numColumns) function and my example looks like:
var range = sheet.getRange(7,11,sheet.getLastRow(),sheet.getLastColumn());
And the result is ex. sheet.getRange(7,11,200,30);
But when I want to use this range, for example, to put some data to the sheet, function doesn't use starting point (startRow - 7, startColumn - 11). So I tried subtract it from getLastRow() and getLastColumn() and it works but gives me decimal number (example lastRow = 193.0) and the function crushed
function myFunction() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName('Arkusz1');
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn() - 2;
var lastColumnParse = parseInt(lastColumn, 10);
var range = sheet.getRange(1,1,lastRow, lastColumn);
var formatting = range.getBackgrounds();
var data = range.getValues();
for(var y = 1; y < data.length; ++y){
var message = '';
for(var x = 0; x < data[y].length; x++){
if(formatting[y][x] == '#ffff00'){
var header = data[0][x];
message += ' ' + header + ' - ' + data[y][x] + ' zł, ' + lastRow + ' ' + lastColumn;
};
data[y][lastColumn] = message
}
}
range.setValues(data);
}
And the error message is:
The message said that wide range is not correct. Inputted 7 but it should be 6.
In the console, we can see, that x = 7.0, not 6.
I cannot find the mistake. Please help me.
The problem is that in JavaScript/Google Apps Script the array index is 0 (zero) based, and row/columns indexes are 1 (one) based. In other words, the length for an array with seven elements is seven but the index of the last element is six.
I've created a spreadsheet to pull in data from two river gauges near my house to try and follow their relationship to the water level as it passes us, (it's an old mill) since more and more the country seems to be flooding!
Basically the sheet works perfectly but not when the spreadsheet isn't open/when I close the laptop. I thought openById and getSheetByName would solve this but I'm having no luck.
The ImportXML commands that I construct just return N/A when the sheet is not open. The script is on a timed trigger every 15mins. I have another basic script that rewrites the contents of the cells as values so that there is only one row of ImportXML commands at a time.This script is also on a timed trigger.
I've pasted the scripts below - apologies if they're not very eloquent, these are my first attempts!
function fetchData() {
var sheet = SpreadsheetApp.openById("0AgG7jQSg2ljFdGNpbFRjUTA1LXJwdmtPcmxkQnZpUHc").getSheetByName("River Levels");
var bredURL = "http://www.environment-agency.gov.uk/homeandleisure/floods/riverlevels/120743.aspx?stationId=4004";
var belURL = "http://www.environment-agency.gov.uk/homeandleisure/floods/riverlevels/120743.aspx?stationId=4002";
var ssBredLevel = "substring((//div[#class='plain_text']/p)[2],35,4)";
var ssBelLevel = "substring((//div[#class='plain_text']/p)[2],31,4)";
var ssTime = "substring(//div[#class='plain_text']/p[2],34,5)";
var ssDate = "substring(//div[#class='plain_text']/p[2],43,10)";
var commandBredLevel = "ImportXML(\"" + bredURL + "\",\"" + ssBredLevel + "\")"; // build ImportXML() command
var commandBredTime = "ImportXML(\"" + bredURL + "\",\"" + ssTime + "\")"; // build ImportXML() command
var commandBredDate = "ImportXML(\"" + bredURL + "\",\"" + ssDate + "\")"; // build ImportXML() command
var commandBelLevel = "ImportXML(\"" + belURL + "\",\"" + ssBelLevel + "\")"; // build ImportXML() command
var commandBelTime = "ImportXML(\"" + belURL + "\",\"" + ssTime + "\")"; // build ImportXML() command
var commandBelDate = "ImportXML(\"" + belURL + "\",\"" + ssDate + "\")"; // build ImportXML() command
sheet.appendRow(['Bredwardine',' ',' ',' ',' ','Belmont',' ',' ',' ',' ','=now()']); // append row
var lastrow = sheet.getLastRow(); // define last row
var bredLevel = sheet.getRange(lastrow, 2); // define ImportXML cell
var bredTime = sheet.getRange(lastrow, 3); // define ImportXML cell
var bredDate = sheet.getRange(lastrow, 4); // define ImportXML cell
var belLevel = sheet.getRange(lastrow, 7); // define ImportXML cell
var belTime = sheet.getRange(lastrow, 8); // define ImportXML cell
var belDate = sheet.getRange(lastrow, 9); // define ImportXML cell
bredLevel.setFormula(commandBredLevel);
bredTime.setFormula(commandBredTime);
bredDate.setFormula(commandBredDate);
belLevel.setFormula(commandBelLevel);
belTime.setFormula(commandBelTime);
belDate.setFormula(commandBelDate);
writeFormats();
}
function writeRows() {
var sheet = SpreadsheetApp.openById("0AgG7jQSg2ljFdGNpbFRjUTA1LXJwdmtPcmxkQnZpUHc").getSheetByName("River Levels");
var range = sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn());
range.setValues(range.getValues());
};
function writeFormats() {
var sheet = SpreadsheetApp.openById("0AgG7jQSg2ljFdGNpbFRjUTA1LXJwdmtPcmxkQnZpUHc").getSheetByName("River Levels");
var lastcol = sheet.getLastColumn(); // define width of sheet
var lastrow = sheet.getLastRow(); // define last row
var penrow = lastrow-1; // define penultimate row
var formatting = sheet.getRange(penrow,1,1,lastcol); // fetch formatting from penultimate row
formatting.copyFormatToRange(sheet,1,lastcol,lastrow,lastrow); // paste formatting to last row
};