Problem with the order of IF statements Google Script - google-apps-script

I am struggling to set up my IF statements properly, basically I want to check if there is data in column J, if empty continue on with the rest of the script, if there is data ask if the user wants to continue, and then either continue or terminate depending on their response.
Here is the start of my code:
function exportSg() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Subgrade'); //source sheet
var testrange = sheet.getRange('J18:J'); //range to check
var testvalue = (testrange.getValues());
var ui = SpreadsheetApp.getUi();
for (i=0; i<testvalue.length;i++) {
if ( testvalue[i] != "") {
var response = ui.alert("Gaps greater than 50 meters identified in report, unhide column J to identify. \n\n Do you want to cancel the export?",ui.ButtonSet.YES_NO);
Logger.log(response);
if (response == ui.Button.YES) {
SpreadsheetApp.getActive().toast("Export Cancelled...")}else {
SpreadsheetApp.getActive().toast("Exporting Subgrade Report...");
The problem seems to be when there is no data in column J it does not continue with the export.
Anyone fancy shedding some light??

As mentioned in a previous answer to you, you can use a break to stop a loop.
In your case, that means to have a break when the user clicks the YES button:
if (response == ui.Button.YES) {
SpreadsheetApp.getActive().toast("Export Cancelled...");
break;
}
If you want to export even if there is no data to be used by the for statement, you need to move the export part to outside of it:
function exportSg() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Subgrade'); //source sheet
var testrange = sheet.getRange('J18:J'); //range to check
var testvalue = (testrange.getValues());
var ui = SpreadsheetApp.getUi();
var shouldExport = true;
for (i=0; i<testvalue.length;i++) {
if ( testvalue[i] != "") {
var response = ui.alert("Gaps greater than 50 meters identified in report, unhide column J to identify. \n\n Do you want to cancel the export?",ui.ButtonSet.YES_NO);
Logger.log(response);
if (response == ui.Button.YES) {
SpreadsheetApp.getActive().toast("Export Cancelled...");
shouldExport = false;
break;
}
}
}
if (shouldExport) {
myExportFunction();
}
}

Related

Searching a sheet for value stored in a cell fails

I'm an extreme novice in programming and am trying to work an assignment that keeps failing. My code searches a sheet(tab1) in Google sheets for a value that is in a cell in another sheet(tab2). For some reason, the search never finds the value. For simplicity I tested by changing the value that I'm looking for to a whole number, not a ".GetValue". I then had an if statement that would alert with message "Found" and "Not Found" if it wasnt found. The data is never found.
function editRecord(){
var myGoogleSheet=SpreadsheetApp.getActiveSpreadsheet();
var shUserForm=myGoogleSheet.getSheetByName("Form");
var datasheet=myGoogleSheet.getSheetByName("Records");
var ui=SpreadsheetApp.getUi();
var response=ui.alert("Submit", 'Do you want to submit your data?', ui.ButtonSet.YES_NO);
var str=shUserForm.getRange("F7").getValue();
var values=datasheet.getDataRange().getValues();
var valuesFound=false;
if(response==ui.Button.NO){
return;
}
for (var i=0;i<values.length;i++){
if (values[i][1]==str){
var iRow=i+1;
datasheet.getDataRange(iRow,5).setValue(shUserForm.getDataRange("F15").getValue());
datasheet.getDataRange(iRow,6).setValue(shUserForm.getDataRange("F17").getValue());
datasheet.getDataRange(iRow,7).setValue(shUserForm.getDataRange("F19").getValue());
ui.alert("Data updated.");
shUserForm.getDataRange("F15").clearContent;
shUserForm.getDataRange("F17").clearContent;
shUserForm.getDataRange("F19").clearContent;
shUserForm.getDataRange("F21").clearContent;
shUserForm.getDataRange("F23").clearContent;
shUserForm.getDataRange("F25").clearContent;
valuesFound=true;
return;
}
if (valuesFound==false){
ui.alert("Your ID was not found.");
return;
}
}
}
Modification points:
I think that in your script, by return of if (valuesFound==false){}, when values[i][1]==str is false, the for loop is finished. By this, for example, when values[i][1]==str is false at the 1st row of values, the for loop is finished. I thought that this might be the reason of your issue.
About getDataRange(iRow, 5) of datasheet.getDataRange(iRow, 5), unfortunately, getDataRange has no arguments. I think that an error also occurs at this part.
About clearContent of shUserForm.getDataRange("F15").clearContent, in this case, the method of clearContent is not run.
If you want to search the value, how about the following modification?
Modified script 1:
When your script is modified, it becomes as follows.
function editRecord() {
var myGoogleSheet = SpreadsheetApp.getActiveSpreadsheet();
var shUserForm = myGoogleSheet.getSheetByName("Form");
var datasheet = myGoogleSheet.getSheetByName("Records");
var ui = SpreadsheetApp.getUi();
var response = ui.alert("Submit", 'Do you want to submit your data?', ui.ButtonSet.YES_NO);
var str = shUserForm.getRange("F7").getValue();
var values = datasheet.getDataRange().getValues();
var valuesFound = false;
if (response == ui.Button.NO) {
return;
}
for (var i = 0; i < values.length; i++) {
if (values[i][1] == str) {
var iRow = i + 1;
datasheet.getRange(iRow, 5).setValue(shUserForm.getRange("F15").getValue());
datasheet.getRange(iRow, 6).setValue(shUserForm.getRange("F17").getValue());
datasheet.getRange(iRow, 7).setValue(shUserForm.getRange("F19").getValue());
ui.alert("Data updated.");
shUserForm.getRange("F15").clearContent();
shUserForm.getRange("F17").clearContent();
shUserForm.getRange("F19").clearContent();
shUserForm.getRange("F21").clearContent();
shUserForm.getRange("F23").clearContent();
shUserForm.getRange("F25").clearContent();
valuesFound = true;
return;
}
}
if (valuesFound == false) {
ui.alert("Your ID was not found.");
return;
}
}
Modified script 2:
I thought that in your script, getValue and setValue are used in the loop. In this case, the process cost will become high. So, as another modified script, how about the following modification?
unction editRecord() {
var myGoogleSheet = SpreadsheetApp.getActiveSpreadsheet();
var shUserForm = myGoogleSheet.getSheetByName("Form");
var datasheet = myGoogleSheet.getSheetByName("Records");
var ui = SpreadsheetApp.getUi();
var response = ui.alert("Submit", 'Do you want to submit your data?', ui.ButtonSet.YES_NO);
var str = shUserForm.getRange("F7").getValue();
if (response == ui.Button.NO) {
return;
}
var res = datasheet.getRange("B1:B" + datasheet.getLastRow()).createTextFinder(str).matchEntireCell(true).findNext();
if (!res) {
ui.alert("Your ID was not found.");
return;
}
var [[v1],,[v2],,[v3]] = shUserForm.getRange("F15:F19").getValues();
datasheet.getRange(res.getRow(), 5, 1, 3).setValues([[v1, v2, v3]]);
shUserForm.getRangeList(["F15","F17","F19","F21","F23","F25"]).clearContent();
SpreadsheetApp.flush();
ui.alert("Data updated.");
}
In this sample, the value is searched using TextFinder. And, the cells are cleared using the RangeList.
References:
getRange(row, column)
clearContent()
createTextFinder(findText)

Script keeps looping Google Script

I have a simple script that I would like to check if there is data in column J, but it seems to keep looping and bringing up the notification...
function checkGaps() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Subgrade'); //source sheet
var testrange = sheet.getRange('J18:J'); //range to check
var testvalue = (testrange.getValues());
//Condition check in J18:J
for (i=0; i<testvalue.length;i++) {
if ( testvalue[i] != "") {
Browser.msgBox('Possible duplicates found marked in RED.');
}
}
}
Anyone can help?
If you want to stop the loop after the first time it finds a value you can add a break inside the if:
for (i=0; i<testvalue.length;i++) {
if ( testvalue[i] != "") {
Browser.msgBox('Possible duplicates found marked in RED.');
break;
}
}

Deleting Row - Google Apps Script "Cannot find method deleteRow((class))"

Here is my function:
function deleteContact(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var wsname = ss.getRangeByName("contactName").getValue();
var wscl = ss.getSheetByName('Connection List');
var wsRange = wscl.getRange("A1:A").getValues();
for(var i = 0; i<wsRange.length;i++){
if(wsRange[i][0] == wsname){
var row = i+1; //This gets the row number
}
var ui = SpreadsheetApp.getUi();
var response = ui.alert("Are You Sure You Want To Delete " + wsname, ui.ButtonSet.YES_NO);
if (response == ui.Button.YES) {
var delr = wscl.deleteRow(row);
}
}
}
I am able to get the row number, but once I click the 'YES' button, I am getting this error:
Cannot find method deleteRow((class)).
Any suggestions? I want the function to delete the row it found.
Try this:
function deleteContact(){
var ss=SpreadsheetApp.getActive();
var wsname=ss.getRangeByName("contactName").getValue();
var wscl=ss.getSheetByName('Connection List');
var wsValues=wscl.getRange(1,1,wscl.getLastRow(),1).getValues();
var d=0;
for(var i=0;i<wsValues.length;i++){
if(wsValues[i][0]==wsname){
var row=i+1-d; //This gets the row number
var ui=SpreadsheetApp.getUi();
var response=ui.alert("Are You Sure You Want To Delete " + wsname, ui.ButtonSet.YES_NO);
if (response == ui.Button.YES) {
wscl.deleteRow(row);
d++;
}
}
}
}
As you delete the rows the ones that are left move up a row each time but the data was taken before the rows were deleted so the indices for calculating the address from the data array have to be compensated by the number of rows that have been deleted.
You also had some lines that should have been within the scope of if(wsValues[i][0]==wsname){ and were not so I moved them in and now it only deletes lines with the correct name.

How do I call a mailApp function within an onEdit function?

I have an onEdit function where if executed should send an email. However, some research has turned up that the mailApp functions don't work with onEdit. I'm currently toying around with workarounds but wondering if others have solutions they've come up with.
function onEdit(e) {
var sheet = e.source.getActiveSheet();
var sheetName = sheet.getName();
//if editing specific sheet
if (sheetName == "draft_test" ) {
//if editing 6th column
var r = e.source.getActiveRange();
if (r.getColumn() == 6 ) {
var player = sheet.getActiveCell().getValue();
// Display a dialog box with a message and "Yes" and "No" buttons.
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Do you want to draft '+player+'?', ui.ButtonSet.YES_NO);
// Process the user's response.
if (response == ui.Button.YES) {
//***********FOR SOME REASON EXECUTING THIS FUNCTION ISNT WORKING******************
emailLeague();
//sortAutoRoster();
} else {
}
}
}
}
function emailLeague() {
var draftSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("draft_test");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("test_email");
var emailSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Manager Info");
//actual email address omitted
var recipient = 'emailaddress#gmail.com';
//get array of all picks on "draft test" tab, and find latest one
var picks = draftSheet.getRange(3,6,146,1).getValues();
for (var i=0; i<picks.length; i++){
if (picks[i] == ""){
var latestPick = i;
break;
}
}
var subject = sheet.getRange(i+1, 2).getValue();
var body = sheet.getRange(i+1, 1).getValue();
MailApp.sendEmail(recipient, subject, body);
}

Why is my .appendRow from Array adding an extra row?

I pretty much have the Apps Script file working as intended. However, each time it is triggered, it also adds a second line where the sessionEmail is not captured and is blank.
function onEdit() {
var sessionEmail = Session.getActiveUser().getEmail();
var spreadsheetTimeZone = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
var lastUpdatedString = Utilities.formatDate(new Date(), spreadsheetTimeZone, "MM/dd/yyyy' 'HH:mm:ss");
var s = SpreadsheetApp.getActiveSheet();
if (s.getName() == "Workload") { //checks that we're on the correct sheet
var r = s.getActiveCell();
if (r.getColumn() == 14) { //checks the column
var status = r.getValue();
var note = r.offset(0, -1);
var noteValue = note.getValue()
var delivery = r.offset(0, -5);
var deliveryValue = delivery.getValue()
}
// Validating fields are filled in
if (status == "Complete") {
var ui = SpreadsheetApp.getUi();
if (noteValue == '') { // if no note is entered, stop script with message box
var noStatus = ui.alert(
'Warning!',
'Please enter notation before choosing Complete.',
ui.ButtonSet.OK);
r.setValue('')
return;
}
// get destination range
var array = [lastUpdatedString, sessionEmail, deliveryValue, noteValue]
var ss = SpreadsheetApp.getActiveSpreadsheet();
var pasteSheet = ss.getSheetByName("Historical Notes Sheet");
pasteSheet.appendRow(array)
// clear response row
note.setValue('')
r.setValue('')
}
}
}
Image of what the results look like:
If any of you have any ideas on how to resolve this, and only append 1 line that has all the values, I would really appreciate it.
Thanks!
Update:
Logging the variable produces the following (expected) results, where the e-mail address appeared in the string.
Results still populating 2 rows:
Thanks for helping me troubleshoot.
I went into View>Executions, and noticed that the script was running twice each time at about 2 milliseconds apart. I think the function name onEdit() was acting like an On Edit trigger, and causing the script to run with another On Edit trigger that I had set up for it.
I tried removing the trigger, and leaving it with the onEdit()name, but that was causing it to not grab the sessionEmail. Changing the code to the below, and adding the trigger back causes the code to run as expected.
function appendLine() {
var sessionEmail = Session.getActiveUser().getEmail().toString();
var spreadsheetTimeZone = SpreadsheetApp.getActive().getSpreadsheetTimeZone();
var lastUpdatedString = Utilities.formatDate(new Date(), spreadsheetTimeZone, "MM/dd/yyyy' 'HH:mm:ss");
var s = SpreadsheetApp.getActiveSheet();
if (s.getName() == "Workload") { //checks that we're on the correct sheet
var r = s.getActiveCell();
if (r.getColumn() == 14) { //checks the column
var status = r.getValue();
var note = r.offset(0, -1);
var noteValue = note.getValue()
var delivery = r.offset(0, -5);
var deliveryValue = delivery.getValue().toString();
}
// Validating fields are filled in
if (status == "Complete") {
var ui = SpreadsheetApp.getUi();
if (noteValue == '') { // if no note is entered, stop script with message box
var noStatus = ui.alert(
'Warning!',
'Please enter notation before choosing Complete.',
ui.ButtonSet.OK);
r.setValue('')
return;
}
// get destination range
var array = [lastUpdatedString, sessionEmail, deliveryValue, noteValue]
var ss = SpreadsheetApp.getActiveSpreadsheet();
var pasteSheet = ss.getSheetByName("Historical Notes Sheet");
pasteSheet.appendRow(array)
// clear response row
note.setValue('')
r.setValue('')
}
}
}
Thanks again to everyone for your help!