Google Scripts - Using a drop-down menu to show a balance - javascript

So I have used data validation to create a drop-down menu that will then update some cells to show the budget amount that is remaining from another sheet. Nothing is occurring when I try to update the field.
The first check for if a checkbox is marked true all works, so I know it is entering the first if. I just can't seem to get it to enter the second if.
function onEdit(e) {
var sheet=e.range.getSheet();
var rgA1=e.range.getA1Notation();
if (sheet.getName()=="Entry") {
console.log("Entry")
if (e.value == "TRUE") {
submit();
Today();
e.range.setValue("FALSE");
}
if (rgA1=="A8" || rgA1 == "B8") {
var entry = e.source.getSheetByName("Entry");
var summary = e.source.getSheetByName("Summary");
var day = entry.getRange("B9").getValue();
var month = entry.getRange("B10").getValue();
var total = entry.getRange("B11").getValue();
var today = Utilities.formatDate(new Date(), "GMT+1", "MM/dd/yy");
//var daysRemaining = DATEIF(today, summary.getRange("D4"), "D");cell functions not allow
//var monthsRemaining = DATEIF(today, summary.getRange("D4"), "M");cell functions not allowed
console.log("Entered 2nd if")
if (e.value == summary.getRange("B59").getValue) {
var balance = summary.getRange("E59").getValue
console.log("Entered 3rd if")
}
else if (e.value == summary.getRange("B60").getValue()) {
var balance = summary.getRange("E60").getValue()
}
else if (e.value == summary.getRange("B61").getValue()) {
var balance = summary.getRange("E61").getValue()
}
else if (e.value == summary.getRange("B62").getValue()) {
var balance = summary.getRange("E62").getValue()
}
else if (e.value == summary.getRange("B63").getValue()) {
var balance = summary.getRange("E63").getValue()
}
else if (e.value == summary.getRange("B64").getValue()) {
var balance = summary.getRange("E64").getValue()
}
else if (e.value == summary.getRange("B65").getValue()) {
var balance = summary.getRange("E65").getValue()
}
else if (e.value == summary.getRange("B66").getValue()) {
var balance = summary.getRange("E66").getValue()
}
else if (e.value == summary.getRange("B67").getValue()) {
var balance = summary.getRange("E67").getValue()
}
else if (e.value == summary.getRange("B68").getValue()) {
var balance = summary.getRange("E68").getValue()
}
else if (e.value == summary.getRange("B69").getValue()) {
var balance = summary.getRange("E69").getValue()
}
else if (e.value == summary.getRange("B70").getValue()) {
var balance = summary.getRange("E70").getValue()
}
else if (e.value == summary.getRange("B71").getValue()) {
var balance = summary.getRange("E71").getValue()
}
day.setValue(balance / 56);
month.setValue(balance / 2);
total.setValue(balance);
}
}
}
Any thanks would be hugely appreciated!
EDIT 5/8/20
Fixed using Cooper's suggestions
Also here is a copy of the sheet this script is for.

That's better but you still have some problems at the end.
function onEdit(e) {
var sheet=e.range.getSheet();
var rgA1=e.range.getA1Notation();
if (sheet.getName()=="Entry") {
console.log("Entry")
if (e.value == "TRUE") {
submit();
Today();
e.range.setValue("FALSE");
}
if (rgA1=="A8" || rgA1 == "B8") {
var entry = e.source.getSheetByName("Entry");
var summary = e.source.getSheetByName("Summary");
var dA=entry.getRange('B9:B11').getValues();
var day = dA[0][0];
var month = dA[0][1];
var total = dA[0][2];
var today = Utilities.formatDate(new Date(), "GMT+1", "MM/dd/yy");
var bvs=summary.getRange('B59:B71').getValues();
var erg=summary.getRange('E59:E71');
var evs=erg.getValues();
for(var i=0;i<bvs.length;i++) {
if(e.value==bvs[i][0]) {
var balance=evs[i][0];
break;
}
}
entry.getRange('B9').setValue(balance/56);
entry.getRange('B10').setValue(balance/2);
entry.getRange('B11').setValue(balance);
//day.setValue(balance / 56);//day is not a range so there is no setValue Method
//month.setValue(balance / 2);//day is not a range so there is no setValue Method
//total.setValue(balance);//day is not a range so there is no setValue Method
}
}
}

Related

Javascript field validation inside forEach loop

I am building a complex registration form with javascript validation.
There are text fields inserted dynamically if the user states that they have children, the number of fields depends on how many children they say they have.
I get the nodes using const kidDobFields = agesRow.querySelectorAll('input[name^="age"]');
In my loop, I am first trying to ensure that the field is no empty, and then secondly ensure the date entered is not more than 16 years ago, if all fields are populated and valid then the form can go on to the next tab of questions.
if(document.getElementById('hasChildren').checked && numberKids.value != '') {
kidDobFields.forEach(field => {
if(field.value == '') {
error.style.display = "block";
error.innerHTML = 'Please enter all dates of birth.';
field.classList.add("is-invalid");
return;
} else {
var today = new Date();
var todayYear = today.getFullYear();
var todayMonth = today.getMonth()+1;
var todayDate = today.getDate();
var dobParts = field.value.split("/");
var dtDOB = new Date(dobParts[1] + "/" + dobParts[0] + "/" + dobParts[2]);
var dobYear = dtDOB.getFullYear();
var dobMonth = dtDOB.getMonth()+1;
var dobDate = dtDOB.getDate();
var age = 'valid';
if(todayYear - dobYear > 16) {
var age = 'invalid';
}
if(todayYear - dobYear == 16) {
if(todayMonth > dobMonth) {
var age = 'invalid';
}
if(todayMonth == dobMonth) {
if(todayDate > dobDate) {
var age = 'invalid';
}
}
}
if(age == 'invalid') {
error.style.display = "block";
error.innerHTML = 'Please don\'t include children who are aged 16 or over.';
field.classList.add("is-invalid");
return;
}
}
});
} else {
document.getElementById('tab3').style.display = "none";
document.getElementById('tab4').style.display = "block";
document.getElementById('formHeading').innerHTML = 'Availability';
document.getElementById('step3').classList.add("complete");
}
Using the code above, if I use 3 date fields and leave the first empty, the 2nd and 3rd are still validated.
If I put a date over 16 years ago in the first and leave the others empty, the error shows Please enter all dates of birth. because the loop continues, rather than stopping after the first and saying that the date is too old.
I know a forEach cannot be broken out of, but I am not sure how best to improve this validation process.
you need to use every() instead of forEach() https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every?retiredLocale=uk
I found answer here: https://masteringjs.io/tutorials/fundamentals/foreach-break
your code will look like this:
if(document.getElementById('hasChildren').checked && numberKids.value != '') {
kidDobFields.every(field => {
if(field.value == '') {
error.style.display = "block";
error.innerHTML = 'Please enter all dates of birth.';
field.classList.add("is-invalid");
return false;
} else {
var today = new Date();
var todayYear = today.getFullYear();
var todayMonth = today.getMonth()+1;
var todayDate = today.getDate();
var dobParts = field.value.split("/");
var dtDOB = new Date(dobParts[1] + "/" + dobParts[0] + "/" + dobParts[2]);
var dobYear = dtDOB.getFullYear();
var dobMonth = dtDOB.getMonth()+1;
var dobDate = dtDOB.getDate();
var age = 'valid';
if(todayYear - dobYear > 16) {
var age = 'invalid';
}
if(todayYear - dobYear == 16) {
if(todayMonth > dobMonth) {
var age = 'invalid';
}
if(todayMonth == dobMonth) {
if(todayDate > dobDate) {
var age = 'invalid';
}
}
}
if(age == 'invalid') {
error.style.display = "block";
error.innerHTML = 'Please don\'t include children who are aged 16 or over.';
field.classList.add("is-invalid");
return false;
}
}
return true;
});
} else {
document.getElementById('tab3').style.display = "none";
document.getElementById('tab4').style.display = "block";
document.getElementById('formHeading').innerHTML = 'Availability';
document.getElementById('step3').classList.add("complete");
}

Disable/Enable HTML Button based on Existing Functions

I have a function running onclick from HTML button and need to add disabling the button on success but NOT on return = false.
I've tried toggling, disabling directly in the HTML and inserting changing the HTML attribute within my current function.
var amtCount = 0;
function addToLineItem()
{
var totalAmount = 0.0;
var valid = true;
var difference = [];
$.each($(".tbodys tr"),function(index,vs)
{
for(var tdcnt = 0; tdcnt < vs.children.length - 1; tdcnt++)
{
if(tdcnt != 5)
if(vs.children[tdcnt].firstElementChild.value == "" || vs.children[tdcnt].firstElementChild.value == undefined)
valid = false;
}
if(vs.children[9].firstChild.value != "" && vs.children[9].firstChild.value != undefined)
{
RMID.push(vs.children[9].firstChild.value);
}
});
if(CodingListItem.length > 0)
{
difference = arr_diff(CodingListItem,RMID);
}
if(valid == false)
{
alert("Message");
return false;
}
if($("#aprDate").val() == "")
{
alert("Please date.");
return false;
}
$.each($(".tbodys tr .nine"),function(index,vs){
totalAmount += parseFloat(vs.firstElementChild.value.replace(/,/g, ""));
});
if($("#Total")[0].innerText == "")
{
alert("Please .");
return false;
}
//if(parseFloat($("#invTotal").val().replace(/,/g, "")) != totalAmount)
if(parseFloat($("#invTotal").val().replace(/,/g, "")) != parseFloat($("#Total")[0].innerText.replace(/,/g, "")))
{
alert("total amount does not match.");
return false;
}
SP.SOD.executeFunc("sp.js", 'SP.ClientContext', function()
{
try
{
var clientContext = SP.ClientContext.get_current();
var web = clientContext.get_web();
var oList = clientContext.get_web().get_lists().getByTitle('Invoice');
if(difference.length > 0)
{
$.each(difference, function( index, value )
{
deleteListItem(parseInt(value));
});
}
$.each($(".tbodys tr"),function(i,v)
{
if(v.children[9].firstChild.value != "" && v.children[9].firstChild.value != undefined)
{
var itemType1 = GetItemTypeForListName("InvoiceLineItem");
var item1 = {
"__metadata": { "type": itemType1 },
"Title": v.children[0].firstChild.value,
"InvoiceIDId": parseInt(INV),
"Entity": v.children[1].firstChild.value,
"MS": v.children[2].firstChild.value,
"LocationId": parseInt(v.children[3].firstChild.value),
"DepartmentId": parseInt(v.children[4].firstChild.value),
"Account": v.children[5].children[1].options[v.children[5].children[1].selectedIndex].text,
"SubAccount": v.children[6].firstChild.value,
"GLCode": v.children[7].firstChild.value,
"Amount": v.children[8].firstChild.value
};
updateListItem(parseInt(v.children[9].firstChild.value), "Invoice Approval and Coding", _spPageContextInfo.webAbsoluteUrl, item1, function () {
amtCount = amtCount + 1;
updatePendingInvoice(amtCount);
}, function () { errorMsg = true; });
}
else
{
var itemCreateInfo = new SP.ListItemCreationInformation();
var oListItem = oList.addItem(itemCreateInfo);
oListItem.set_item('Title', v.children[0].firstChild.value); //Line Description
oListItem.set_item('InvoiceID', INV);
oListItem.set_item('Entity', v.children[1].firstChild.value);
oListItem.set_item('MS', v.children[2].firstChild.value);
oListItem.set_item('Location', v.children[3].firstChild.value);
oListItem.set_item('Department', v.children[4].firstChild.value);
oListItem.set_item('Account', v.children[5].children[1].options[v.children[5].children[1].selectedIndex].text);
oListItem.set_item('SubAccount', v.children[6].firstChild.value);
oListItem.set_item('GLCode', v.children[7].firstChild.value);
oListItem.set_item('Amount', v.children[8].firstChild.value);
oListItem.set_item('Date', $("#aprDate").val());
oListItem.set_item('Comment', $("#cmt").val());
oListItem.update();
clientContext.executeQueryAsync(onQuerySucceeded, onQueryFailed);
}
});
}
catch(err)
{
alert(err.message);
}
});
}
function onQuerySucceeded()
{
amtCount = amtCount + 1;
updatePendingInvoice(amtCount);
}
function onQueryFailed(sender, args)
{
alert('not inserted');
}
This runs fine but if the HTML Button is clicked quickly, the function runs and creates duplicate data.
You should disable the button while you are acting on the click. Then the user cannot queue up another update until the first one finishes. Set an internal variable saying that the work is in progress, disable the button, and then clear the flag when you get the result (success or fail).
For instance:
$("#btnSubmit").click(function() {
$("#btnSubmit").prop("disabled", true);
// do your work here, waiting for success or failure
$('#btnSubmit').prop("disabled", false);
})
or:
$("button").click(function(e) {
$(e.currentTarget).prop('disabled', true);
window.setTimeout(function() {
$(e.currentTarget).prop('disabled', false);
}, 5000);
})
I found what I needed and with some experimentation with where to put the "disabled", false lines was able to get to the solution. I got the simple code from Palash
https://stackoverflow.com/users/1823841/palaѕн
All versions of jQuery after 1.6
Disabling and enabling a html input button
Thank you all for helping... New Code....
var amtCount = 0;
function addToLineItem()
{
**$("#IApprove").attr("disabled", true);**
var totalAmount = 0.0;
var valid = true;
var difference = [];
$.each($(".tbodys tr"),function(index,vs)
{
for(var tdcnt = 0; tdcnt < vs.children.length - 1; tdcnt++)
{
if(tdcnt != 5)
if(vs.children[tdcnt].firstElementChild.value == "" || vs.children[tdcnt].firstElementChild.value == undefined)
valid = false;
}
if(vs.children[9].firstChild.value != "" && vs.children[9].firstChild.value != undefined)
{
RMID.push(vs.children[9].firstChild.value);
}
});
if(CodingListItem.length > 0)
{
difference = arr_diff(CodingListItem,RMID);
}
if(valid == false)
{
alert("Please add Line Items with Required Information. GL coding missing.");
**$("#IApprove").attr("disabled", false);**
return false;
}
if($("#aprDate").val() == "")
{
alert("Please add approver date.");
**$("#IApprove").attr("disabled", false);**
return false;
}
$.each($(".tbodys tr .nine"),function(index,vs){
totalAmount += parseFloat(vs.firstElementChild.value.replace(/,/g, ""));
});
if($("#Total")[0].innerText == "")
{
alert("Please add Line items.");
**$("#IApprove").attr("disabled", false);**
return false;
}
//if(parseFloat($("#invTotal").val().replace(/,/g, "")) != totalAmount)
if(parseFloat($("#invTotal").val().replace(/,/g, "")) != parseFloat($("#Total")[0].innerText.replace(/,/g, "")))
{
alert("Line item's total amount does not match with total invoice amount.");
**$("#IApprove").attr("disabled", false);**
return false;
}
SP.SOD.executeFunc("sp.js", 'SP.ClientContext', function()
{
try
{
var clientContext = SP.ClientContext.get_current();
var web = clientContext.get_web();
var oList = clientContext.get_web().get_lists().getByTitle('Invoice Approval and Coding');
///////////// Delete Items //////////////////
if(difference.length > 0)
{
$.each(difference, function( index, value )
{
deleteListItem(parseInt(value));
});
}
$.each($(".tbodys tr"),function(i,v)
{
if(v.children[9].firstChild.value != "" && v.children[9].firstChild.value != undefined)
{
var itemType1 = GetItemTypeForListName("InvoiceLineItem");
var item1 = {
"__metadata": { "type": itemType1 },
"Title": v.children[0].firstChild.value,
"InvoiceIDId": parseInt(INV),
"Entity": v.children[1].firstChild.value,
"MS": v.children[2].firstChild.value,
"LocationId": parseInt(v.children[3].firstChild.value),
"DepartmentId": parseInt(v.children[4].firstChild.value),
"Account": v.children[5].children[1].options[v.children[5].children[1].selectedIndex].text,
"SubAccount": v.children[6].firstChild.value,
"GLCode": v.children[7].firstChild.value,
"Amount": v.children[8].firstChild.value
};
updateListItem(parseInt(v.children[9].firstChild.value), "Invoice Approval and Coding", _spPageContextInfo.webAbsoluteUrl, item1, function () {
amtCount = amtCount + 1;
updatePendingInvoice(amtCount);
}, function () { errorMsg = true; });
}
else
{
var itemCreateInfo = new SP.ListItemCreationInformation();
var oListItem = oList.addItem(itemCreateInfo);
oListItem.set_item('Title', v.children[0].firstChild.value); //Line Description
oListItem.set_item('InvoiceID', INV);
oListItem.set_item('Entity', v.children[1].firstChild.value);
oListItem.set_item('MS', v.children[2].firstChild.value);
oListItem.set_item('Location', v.children[3].firstChild.value);
oListItem.set_item('Department', v.children[4].firstChild.value);
oListItem.set_item('Account', v.children[5].children[1].options[v.children[5].children[1].selectedIndex].text);
oListItem.set_item('SubAccount', v.children[6].firstChild.value);
oListItem.set_item('GLCode', v.children[7].firstChild.value);
oListItem.set_item('Amount', v.children[8].firstChild.value);
oListItem.set_item('Date', $("#aprDate").val());
oListItem.set_item('Comment', $("#cmt").val());
oListItem.update();
clientContext.executeQueryAsync(onQuerySucceeded, onQueryFailed);
}
});
}
catch(err)
{
alert(err.message);
}
});
}

Google script notifies all email adresses everytime the script runs

Is there a way to make it so you do not send a notification to the user's email when using addEditor(email) on Google script. Been looking through the references for Google developers and haven't found anything.
var ss = SpreadsheetApp.openById("1aU3MOdUKHEgGRCtVaSJs3iRqRIRhLSvpCuXzOVT7Ko8")
var sheet = ss.getSheetByName("Ark 1")
var range = sheet.getRange("B:C")
//Column B is the emails, and C is a list of Edit, View, None
var range_length = range.getValues().length + 1
function scriptTesting(row) {
var scriptTesting = DriveApp.getFolderById("0B8FOoqX6_Y84eHZFaFBGTlJzMTQ")
for (var a = 1; range_length > a; a++) {
var email = range.getCell(a, 1).getValue()
var choice = range.getCell(a, 2).getValue()
if (choice == "Edit") {
scriptTesting.addEditor(email)
} else if (choice == "View") {
scriptTesting.addViewer(email)
} else if (email == "") {
break
} else if (choice == "None") {
try {
scriptTesting.removeViewer(email)
} catch(err) {
continue
}
} else {
continue
}
}
}

four repeating letters check javascript, spam detection

Is there a a "smarter" way to do this? This works but I imagine has something to do with for loops, what if I was checking for 20 repeating characters?
What happens if javascript is disabled?
Is there an easier way to check for "sensical" posts instead of say aldjfalkfja;lfjaklfjlkfj how would I filter that out without storing a library of words and comparing the string to those?
function counter(){
this.value = 0;
}
var count = new counter();
function updatecount(fnc){
fnc.value = count.value + 1;
}
function charbank1(){
this.value = "";
}
var cb1 = new charbank1();
function insertchar1(fnc){
fnc.value = cb1.value + String.fromCharCode(keynum);
}
function charbank2(){
this.value = "";
}
var cb2 = new charbank2();
function insertchar2(fnc){
fnc.value = cb2.value + String.fromCharCode(keynum);
}
function charbank3(){
this.value = "";
}
var cb3 = new charbank3();
function insertchar3(fnc){
fnc.value = cb3.value + String.fromCharCode(keynum);
}
function charbank4(){
this.value = "";
}
var cb4 = new charbank4();
function insertchar1(fnc){
fnc.value = cb4.value + String.fromCharCode(keynum);
}
function repeatingcharcheck(){
if(count.value < 4){
if(count.value == 1){
insertchar1(cb1);
}
if(count.value == 2){
insertchar2(cb2);
}
if(count.value == 3){
insertchar3(cb3);
}
if(count.value == 4){
insertchar4(cb4);
}
}else{
if(cb1.value == cb2.value == cb3.value == cb4.value){
alert('four letters in a row is not allowed');
window.location.replace('somewhere.com');
}
}
}

Exit the javascript code when the validation failed

I need help to exit the JavaScript code when the validation failed. At the moment I am having the right error message when the validation failed but the JavaScript code continue running. Please find my code below. Thanks
var CompPlanID=1;
var Component=2;
var TierNo=3;
var StartDate=4;
var EndDate=5;
var TierMin=6;
var TierMax=7;
var Rate=8;
var InvalidFlag = 0;
var BlankTextBox = '';
function DateCheck()
{
var StartDateform= document.getElementById('tblTarget').rows[1].cells[StartDate].getElementsByTagName('input')[0].value;
var EndDateform= document.getElementById('tblTarget').rows[1].cells[EndDate].getElementsByTagName('input')[0].value;
var eDate = new Date(EndDateform);
var sDate = new Date(StartDateform);
if(StartDateform== BlankTextBox || EndDateform == BlankTextBox || sDate> eDate)
{
alert("Please ensure that the End Date is greater than or equal to the Start Date.");
InvalidFlag = 1;
}
}
// Check if the pk row is not empty
function CheckPkRow()
{
var CompPlanIDform= document.getElementById('tblTarget').rows[1].cells[CompPlanID].getElementsByTagName('select')[0].value;
if(CompPlanIDform== BlankTextBox)
{
alert("Please ensure that the primary key is not empty");
InvalidFlag = 1;
}
}
function Submit()
{
InvalidFlag = 0;
CheckPkRow();
DateCheck();
//Call the submit function if the validation is true.
if(InvalidFlag == 0 )
{
$('button_submit').click();
alert('The new rate submitted');
}
}
function CheckPkRow()
{
var CompPlanIDform= document.getElementById('tblTarget').rows[1].cells[CompPlanID].getElementsByTagName('select')[0].value;
if(CompPlanIDform== BlankTextBox)
{
alert("Please ensure that the primary key is not empty");
InvalidFlag = 1;
return false;
}
}
Change your code as
function DateCheck()
{
var StartDateform= document.getElementById('tblTarget').rows[1].cells[StartDate].getElementsByTagName('input')[0].value;
var EndDateform= document.getElementById('tblTarget').rows[1].cells[EndDate].getElementsByTagName('input')[0].value;
var eDate = new Date(EndDateform);
var sDate = new Date(StartDateform);
if(StartDateform== BlankTextBox || EndDateform == BlankTextBox || sDate> eDate)
{
alert("Please ensure that the End Date is greater than or equal to the Start Date.");
return false;
}
return true;
}
function CheckPkRow()
{
var CompPlanIDform= document.getElementById('tblTarget').rows[1].cells[CompPlanID].getElementsByTagName('select')[0].value;
if(CompPlanIDform== BlankTextBox)
{
alert("Please ensure that the primary key is not empty");
return false;
}
return true;
}
function Submit()
{
if(CheckPkRow() && DateCheck())
{
$('button_submit').click();
alert('The new rate submitted');
}
}

Categories

Resources