Trying to use IF STATEMENTS to automatically fill cells - javascript

As shown in the image, on column C they are supposed write down the homework they have for each class. I want columns D, E, and F to be automatically filled with "N/A" if the student puts "None" on column C (as in they didn't receive homework for a class). But, the columns automatically fill with N/A, even if column C doesn't say None! I don't understand this.
This is what I have so far
function myFunction() {
var app = SpreadsheetApp;
var activeSheet = app.getActiveSpreadsheet().getActiveSheet();
for(var i = 2;i<=183; i++) {
var homework = activeSheet.getRange(i,3).getValue();
if(homework = "None"){
activeSheet.getRange(i,4).setValue("N/A");
activeSheet.getRange(i,5).setValue("N/A");
} else{
activeSheet.getRange(i,4).setValue("");
activeSheet.getRange(i,5).setValue("");
}
}
}

That looks like JS.
if that is JS, you are using an assignment in the place of what you mean to be an equality check between the homework variable and the value "None"
Try if(homework === "None"){
and see if your results change towards your liking.
Disregarding language, your behavior is manifesting as if your predicate is evaluating the truthiness of an assignment to "None" and tripping your conditional. You likely want to investigate your equality operators to verify that the single equals sign is appropriate for equality comparisons. In most languages, it is not.

Related

Script to automatically capitalize contents of a cell in Google Sheets?

I have a spreadsheet that takes input of stock symbols. I would like them to always be in ALL CAPS regardless of how they are typed in. This appears to require some scripting as there is no way to do this with a function unless a second copy of the column exists, which is not acceptable.
I have a solution which works, with one critical problem. The code is as follows:
function OnEdit(e) {
var ss = e.source.getActiveSheet(),
sheets = ['Trades', ''],
ind = sheets.indexOf(ss.getName());
if (ind === 0 && e.range.rowStart > 1 && e.range.columnStart >= 1 ) {
e.range.setValue(e.value.toUpperCase());
}
}
It works great, and allows me to add as many tabs and columns to format as I wish. Unfortunately it also capitalizes the FORMULAS inside the cells, which is breaking formulas that use the importhtml() function, because it capitalizes the URL being requested.
So, anyone know a way to do exactly what the above code does, but not touch the actual formulas inside the cells, only the text that they output?
EDIT: Thanks to #ocordova's comment, I thought I had something that would do the job well enough. Unfortunately it's behaving strangely... it works partly o some columns, and not at all on others. Here is my current code (slightly altered from earlier for clarity):
function onEdit(e){
var activeSheet = e.source.getActiveSheet(),
sheets = ['NEW Trades', ''],
sheetIndex = sheets.indexOf(activeSheet.getName());
if (sheetIndex === 0 && e.range.rowStart > 1 && e.range.columnStart >0 && e.range.getFormula() == '') {
e.range.setValue(e.value.toUpperCase());
}
}
Anyone have any ideas why some cells in some columns will capitalize as expected, and other cells in those same columns won't, and yet other columns won't capitalize at all, anywhere?
EDIT 2: My trouble appears to be related to, or a conflict with, Data Validation. The columns I'm trying to capitalize are fed by lists of values on another sheet. If the value was present previously in lower case, and then I applied the data validation to the column, the script will not capitalize the value. However if I select the appropriate, capitalized selection from the data validation list, and then re-type the same value in lower case, the script DOES kick in and capitalize. Very strange and confusing. I could be wrong about the conflict, but that's what it seems like to me.
EDIT 3: It's not related to data validation, because it's behaving the same way on a simple column that has no validation at all. If the value I had previously entered was already in lowercase, then typing it again in lowercase will not activate the script. BUT if I type the value in CAPS, then re-type it in lowercase, the script capitalizes it. Maybe some strange condition relating to when the script is triggered...?
If you don't want to capitalize if the cell contains a formula, you can use the method getFormula() and check if the cell contains a formula.
Returns the formula (A1 notation) for the top-left cell of the range, or an empty string if the cell is empty or doesn't contain a formula.
The code should look like this:
if (ind === 0 && e.range.rowStart > 1 && e.range.columnStart >= 1 && e.range.getFormula() == '') {
e.range.setValue(e.value.toUpperCase());
}
EDIT:
If I've understood you correctly, you're typing exactly the same value, example: if the value in the cell is México, and you delete all or some characters and inmediately type México again, in that scenario the old value and the new value are the same and the OnEdit() won't be fired. Another example is if you change the format of the value, that's another type of event.
If you want know how the event is considered, you can use an installable on change trigger:
function triggerOnChange(e) {
MailApp.sendEmail('john.doe#gmail.com', 'Testing triggerOnChange', JSON.stringify(e));
}
Then in the Script Editor menu: Resources -> Current Project Triggers -> Add a new trigger -> ['triggerOnChange', 'From spreadsheet', 'On change']
On how to change the case of the formula's result, I think #Rubén has the right idea, but it will only work if the formula contains UPPER() in the first characters, and also since you're using the formula IMPORTHTML() using UPPER() will break it and maybe some other functions like array formulas, unless you use INDEX():
=INDEX(UPPER(IMPORTHTML(url, query, index)))
Another option could be Regular expressions, but I think it's a little risky considering all the combinations.
So, anyone know a way to do exactly what the above code does, but not touch the actual formulas inside the cells, only the text that they output?
Consider to make a slight change in the OP approach: rather than capitalize all the cells content for any case, capitalize according the following conditions:
If the cell value, including the values of cells that holds constants or formulas, is not a string then do nothing .
If the cell value is a string
and the cell content is a constant, then change the case directly from the script.
and the cell content is a formula, then nest the original formula inside the built-in function UPPER.
Example:
function onEdit(e) {
var range = e.range;
var value = range.getValue();
var sheet = range.getSheet();
var sheetName = sheet.getName();
if (sheetName === 'Sheet1' &&
range.getRow() > 1 &&
range.getColumn() > 1 &&
typeof value === 'string') {
if(!range.getFormula()) {
range.setValue(value.toUpperCase());
} else {
if(range.getFormula().substring(0,6).toUpperCase() == '=UPPER') {
return;
} else {
range.setFormula('=UPPER(' + range.getFormula().substring(1) + ')');
}
}
}
}
Notes:
For simplicity the ind array was not included.
typeof e.value always returns 'string', so instead range.getValue(); is used.

Understanding and correcting the structure of Javascript code

so I've been on here for awhile, and I'm still considered an entry level programmer based on my general knowledge of structure and basic concepts. I have a function below that was given to me in an answer for a different question I asked. I can understand most of what it is doing, but I need help understanding the rest of what it does. I'm asking this because I would really like to understand further advanced concepts of javascript, and jQuery.
So what I've done below is placed the function, and I'll comment in what I know about what the function is doing at where, and then I'll place question marks where I"m confused.
function validate(){
//array of objeccts used to defined the class selector for each element iterated
//with what validation function is be assigned to that specific selector
var fields = [
{
selector: $('.not-empty'),
validations: [ isNotEmpty]
},
{
selector: $('.email'),
validations: [ isNotEmpty, isEmail]
},
{
selector: $('.number'),
validations: [ isNotEmpty, isNumber]
},
{
selector: $('.number-noreq'),
validations: [isNumberNotRequired]
},
{
selector: $('.checked'),
validations: [isChecked]
}
];
//remove any classes of 'has-error' from each element traversed before validation begins
$('.form-control').closest('.form-group').removeClass('has-error');
//defining variables
var i = 0, k = 0, z = 0, j = fields.length, item, selector, fn, info;
//for loop to traverse the fields array of objects
for(; i < j; i++){
item = fields[i];
//traversing each field.validation
for(k = 0; k < item.validations.length; k++){
fn = item.validations[k]; //setting fn as a function found in validation
//traversing each selector in item
for( z = 0; z < item.selector.length; z++){
selector = $(item.selector[z]); //setting the selector
//attempting to set info to the closest form or input group found by the selector
info = selector.closest('.form-group, .input-group');
if(info) //if info contains data
//?????????????????????????????????????? no idea what's going on below other
//other than it's running the validation function that was passed, but why
//is it written like this and what is it doing?
info[fn(selector.val()) ? 'removeClass' : 'addClass']('has-error');
}
}
}
}
So that is the basic question I have for this code (where all the question marks are). If someone can clearly answer what is going on, why you write the code like that, what the purpose of it is, and is it benefcial or not, would be fantastic. if you need more clarification I would be happy to provide it. I just want to be able to explain the code to somebody and know what I am talking about instead of trying to have to bs my through it. I think it was Einstein who said, "If you can't explain something accurately and to the point, then you truly do not understand it" or something like that!
Thank you in advance!
EDIT: here are the functions that 'validations' traverse through
//validation functions
function isNotEmpty(value){
return value && $.trim(value).length > 0;
}
function isEmail(value){
return /^([^#\s\t\n]+\#[\w\d]+\.[\w]{2,3}(\.[\w]{2})?)$/.test(value);
}
function isNumber(value){
return /^\d+$/.test(value);
}
function isNumberNotRequired(value){
return /^\d+$/.test(value) || value.length < 1;
}
function isChecked(value){
var r = false;
var name = $(value).attr('name');
$('input[name="'+name+'"').each(function(){
if($(this).is(':checked')){
r = true;
}
});
return r;
}
SECOND EDIT/UPDATE: We have determined that there is a severe error in the code that allows it not to keep track of the validation and take into account previous validations for input groups, and other related sections. How does this corrected. I'm testing items on jsfiddle at the moment I will return when I have restuls!
This line:
info[fn(selector.val()) ? 'removeClass' : 'addClass']('has-error');
is equivalent to this:
var result = fn(selector.val());
if (result)
info.removeClass("has-error");
else
info.addClass("has-error");
How is that? Well, your code calls the function plucked from the list of validation routines stored in that data structure, passing the value of the field to be tested. The result of that function call is used as a true/false test in the ? : expression. If the result is true, the ? : resolves to the string "removeClass"; if false, to "addClass".
Now, what is info? It's a jQuery object that refers to the closest piece of the DOM that (presumably) is where an error message would be displayed, or where some other indicator would be shown based on some CSS rule. The [ ] operator will take whichever of those two strings the ? : resolves to and use that as a property accessor. The net effect, therefore, is to reference either info.removeClass or info.addClass. Those are both references to jQuery methods, so one or the other will be called. In either case, the code wants to operate on the class name "has-error", because it wants to either add it (when the validation fails) or remove it (when the validation succeeds).
That said, the code has a serious defect: if, for a given field, there is in fact a list of validation functions, the code will run all of them (which is fine). However, for each validation function, it sets or clears that "has-error" class without regard to prior validation results. That might work, if you're really careful with the ordering of the validation functions, but that's an awfully fragile way of doing things. I think it would be much more robust if it made each test and kept track of whether any test failed, and then after that process is complete for a given field it'd only then set or clear the "has-error" class.
Fixing the code isn't too hard. Currently it iterates the the validation functions outside the iteration over the selected fields, which (I think) is backwards. However, as long as it checks the state of the error indicator element(s), it should be OK.
First, at the top, the code removes "has-error" from .form-group elements but not from .input-group elements. That's clearly incorrect, so:
$('.form-control').closest('.form-group, .input-group').removeClass('has-error');
Then, in the loop:
for( z = 0; z < item.selector.length; z++){
selector = $(item.selector[z]); //setting the selector
//attempting to set info to the closest form or input group found by the selector
info = selector.closest('.form-group, .input-group');
if (info.length && !fn(selector.val())) // if info contains data and field is invalid
info.addClass('has-error');
}
Since all the "has-error" flags are cleared at the outset, all we need to do is add the class to classes that are invalid. If you wanted to have a positive "is-ok" class, then you'd add that to everything at the top and remove it when you find an error.
As you should have known, foo.bar are foo["bar"] are identical in JavaScript (if you did not know, learn it, now).
This line
info[fn(selector.val()) ? 'removeClass' : 'addClass']('has-error');
means
var methodName;
if (fn(selector.val())) { methodName = 'removeClass'; } else { methodName = 'addClass'; }
info[methodName]('has-error')
so, in yet another words,
if (fn(selector.val())) {
info.removeClass('has-error');
} else {
info.addClass('has-error');
}
So it is actually switching class has-error on/off. Just it's pretty densely written.

JavaScript logic - Parsing a textarea

I need to take a textbox that is full of formatted info about accounts and then sort it somehow. I would like to know if it would be ideal (I'm trying to make this as efficient as possible) to parse the info into a two dimensional array, or if I should make account objects that will hold info in fields.
The program is simply meant to format the data so that it can be printed out without having to copy/paste.
So far I have...
function generateOutputfvoc()
{
var accountLines = document.getElementById('accountLines').value;
var accountLinesTemp = accountLines.split(/[\s]/);
for(var i = 0; i < accountLinesTemp.length; i++)
{
if(accountLinesTemp[i].match(/
Edit (1-18-13): Here is an example input. It is basically text copied from a web CRM tool. Note, this example input is something I typed up randomly.
P8B000001234567 stackoverflow Thing 12522225555 444 Active 2005-02-26 CO1000123456
P8B000001234568 stackoverflow Another Thing 444 Active 2005-02-26 CO1000123456
P8B000001234569 stackoverflow Another Thing 556 Active 2005-02-26 CO1000123456
I would like my program to take the text and simply output the text like this:
P8B000001234567 stackoverflow Thing 12522225555 444 Active 2005-02-26 CO1000123456
P8B000001234568 stackoverflow Another Thing 444 Active 2005-02-26 CO1000123456
P8B000001234569 stackoverflow Another Thing 556 Active 2005-02-26 CO1000123456
Also, I would like to know if I should use jQuery variables. I asked this because I have been looking online a lot and I found examples that use code that looks like this:
$check=fcompcheck();
if($check)
{
$output=document.frm1.type.value+" / ";
$output=$output+"Something - "+document.frm1.disco.value+" / ";
Note the: $output variable. The dollar sign indicates a jQuery variable, right?
Thank you for any help you might be able to offer me.
Update (1-19-13): I've taken a shot at it, but I'm making slow progress. I'm used to programming Java and my JavaScript looks too similar, I can tell I'm makings errors.
I'm taking it one step at a time. Here is the logic I'm using now.
Person pastes text into text box and pushes the generate button
Program takes the contents of the text box and parses it into a large array, removing only whitespace
Program then searches for patterns in the text and begins passing values into variables
I am trying to get the program to simply identify the pattern "Summary section collapse Name" because these four words should always be in this sequence. Once it identifies this it will pass the next two array values into first and last name variables. Here's some of the code:
var contactNameFirst, contactNameLast;
// Parse the input box into an array
var inputArr = document.getElementById('inputBox').value.split(/[\s]/);
for(var i = 0; i < inputArr.length; i++)
{
if(inputArr[i] == "Summary" && inputArr[i - 1] == "section" && inputArr[i - 2] == "Collapse" && inputArr[i + 1] == "Name")
{
if(inputArr[i + 2] != "Details")
{
contactNameFirst = inputArr[i + 2];
}
else
{
contactNameFirst = "";
}
if(inputArr[i + 3] != "Details")
{
contactNameLast = inputArr[i + 3];
}
else
{
contactNameLast = "";
}
}
}
document.getElementById('contactNameOutput').innerHTML = contactNameFirst + " " + contactNameLast;
Also, should I create a new post for this now, or keep editing this one?
Your accountLinesTemp is an Array of String, you could use the Array.sort function to sort your array as expected, and then use Array.join to get the full String if necessary.
See https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort on MDN for more information.

what is the logic for paragraph validation in multiline Textbox using javascript?

i am trying to validate text(Paragraph) in javascript for multiline Textbox.
After giving the text in textbox, the very first Letter should be changed to Capital letter, remaining have to remain as small letters.After full stop the first letter should be in Capital. I need to use textchange event also.
I am new to javascript, and i feel this Proper Case validation is very complex, i am not even getting any logic to start with.. Plz give some idea.
Thanks in advance.
Here's a possible answer, though to reiterate my comment, I don't actually think this is a very useful validation approach. You can see a working version here: http://jsfiddle.net/nrabinowitz/5TSK5/
// regex for a single sentence
var testRE = /^[A-Z][^A-Z]+$/;
var paragraphs = text.split('\n');
var pass, paragraph, sentences, sentence;
for (var x=0; x < paragraphs.length; x++) {
paragraph = paragraphs[x];
pass = true;
if (paragraph) {
sentences = paragraph.split(/\. +/);
for (var y=0; y < sentences.length; y++) {
sentence = sentences[y];
// test sentence for validity
if (sentence && !testRE.exec(sentence)) {
pass = false;
}
}
// pass is now either true or false for paragraph x
}
}
You might want to look for a plugin that already does grammar checking like After The Deadline.
#nrabinowitz is right, I wouldn't try to write a natural language grammar checker in javascript unless your stated goal of "capitalization should only occur after a full stop" is the full extent of what you want to do, you'd be attempting to parse a potentially non-context-free language.

javascript IF nested in a FOR loop not filtering results

I have a for loop that I am using to draw stuff from an array on to a canvas. The array holds a bunch of variables.
These variables contain qualitative values like firstName, lastName, team, etc.
I know the variables are set up correctly because my other functions using them work fine. However, I have a for loop that is suppose to be drawing circles on the canvas only if team = 'blue' .
The problem is that it is recognizing them all as being 'blue' and drawing them all, when in fact only a few are 'blue' and other are 'red', 'green', etc.
here is the code:
ctx.fillGroups = function(g){
for ( var i=0; i<allSeating.length; ++i ){
if (allSeating[i.team]=g){
ctx.beginPath();
ctx.fillPerson(allSeating[i]);
//alert(allSeating[i.team]);
}
}
}
With the alert() active i can see that it thinks they are all blue.
I am guessing the issue lies with the line: if (allSeating[i.team]=g) but I cant seem to get it to work. Does the check for allSeating[i.team]=g need to happen elsewhere? But then why does it think that they are all blue team anyway?
UPDATE: still not working here is a demo http://jsfiddle.net/8ryvH/1/
The issue is that = sets a variable ... use allSeating[i.team]===g
What's going on is that you are assigning g to allSeating[i.team] for every element in allSeating. The = operator does not do the same thing in JavaScript as it does in VB or SQL -- in either of those languages x = y is an equivalency test or an assignment, depending on the context. In JavaScript (and most other languages that I can think of), = is used only for assignment and == (and === in JavaScript) are used to test for equality.
== does type-casting to check equality while === does not. ("1" == 1 // true but "1" === 1 // false)
allSeating[i.team]=g is not a check: it is an assignment statement.
What about allSeating[i.team]==g instead? (Am I missing something?)
The Mozilla Developer's Network JavaScript Documentation is a great resource for this sort of thing.
Update:
As said elsewhere, there's more here than = or ===.
We noted in chat that allSeating[i].team === g is probably what you want to evaluate, but things still didn't add up.
I think the seat object is the problem, or rather the instantiation of it.
The definition has eight properties, but your instantiations have only seven.
Adding a value for the fillStyle property, as shown below, corrected the problem for me, and allSeating[i].team === g now evaluates true.
var markTwain = new Seat(758, 180, 9,fillStyle,"Mark", "Twain", 6207, "red");
Please let me know if you've got any more trouble.

Categories

Resources