Google Script: Adding 1 to a value - google-apps-script

I'm trying to add 1 to the value of a cell in a Google Spreadsheet when a certain event happens. But instead of...say changing -6 to -5, it changes it to -61. What's wrong with my code?
var Spending = sheet.getRange("B2");
var SPEND = [Spending.getCell(1, 1).getValue()];
**EVENT TRIGGERED**
SPEND = SPEND+1;
Spending.setValue(SPEND);

It appears that was reading the value as a string and simply concatenate it. Try to parse the the var SPEND to Integer.
example:
SPEND = parseInt(SPEND)+1 or SPEND = Number(SPEND)+1

for some reason i have yet to fully discover (mainly through lack on needing to know the deeper answer), + is treated as a concatenation for anything but an integer value. so unless the var is declared as an intiger, it's treated as a string. if it's a string, the "+" means to concat, not perform a mathematical operation. "-" doesn't seem to have the same dual usage, only being used for mathematical operations.
Hope that helps!

Related

A function to format numbers as written in Germany

I am writing my first script for an invoice template based on a Google Doc.
It works fine. I need to use it in Germany so I need to be able to format the prices in the way they are shown in Germany.
I have written a short function to do this but am interested in whether there is a better or more obvious way of achieving this.
// this formats numbers as used in Germany
function numberToGerman(number){
number = Utilities.formatString("%d.%d,%02d", number/1000, number%1000, number%1*100);
return number;
}
It has a problem above 999.999,99 or below 1.000,00 at the moment but I hope there is a better solution out there.
Here is a slight modification of the answer by Elias Zamaria, replacing separators and ensuring exactly two decimals:
function numberToGerman(number){
var parts = number.toString().split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
parts[1] = ((parts[1] || "") + "00").slice(0,2);
return parts.join(",");
}
The parts are the integer and fractional parts. Groups of three digits are processed by the regex, which places dots accordingly. The fractional parts is expanded/truncated to two places.
Remarks
Unfortunately, number.toLocaleString("de-DE") is not yet supported by Google Apps Script. One can use number.toLocaleString() but then the performance depends on someone having set the correct locale. Also, options concerning decimal places aren't supported either, so this doesn't help that much.
If this was to be used in a spreadsheet, you can apply appropriate formatting to cells either manually from the menu, or from a script: for example cell.setNumberFormat("#,###.00"). This looks like U.S.-style formatting, but once the locale of the spreadsheet is changed to Germany, it changes accordingly, e.g. 1.234.567,89.

Restrict text field to mathematical expressions - Convert String to mathematical expression

How can I restrict the input of a TextFieldsuch that it can only contain mathematical expressions?
Accepted inputs would be:
"3+5"
"-5 + 6"
"3/2(6*4)"
"6--5"
"+5-3"
etc..
And rejected inputs would be:
"5+++3"
"6(7)"
"6-6-+-7"
and so on.
Basically; the syntax I want it to be restricted to is the kind of syntax that programming languages normally use for evaluating mathematical expressions, kinda like the syntax input you'd expect from your everyday calculator.
I'm making a program in which I want the user to be able to input numbers and/or calculations into a text box, instead of having to use a calculator to do it and then arduously type out a number with 7 decimal places.
I've done a little look around and I've seen a lot of stuff involving Regex, postfix, BNF, and the like. A lot of it looked very complicated, too complex for my understanding, and none of it had anything to do with AS3.
However, I've had a thought about making this problem a whole lot simpler by just converting the string into a mathematical expression that AS3 can understand, and let Flash handle the errors using try catch, but I don't know how to do that either (Number("3+5")resulted to NaN).
I'm currently restricting text input to just numbers using Event.CHANGE, like this:
function Restrict(event:Event):void
{
if (event.currentTarget.text.indexOf(".") == -1)
{
event.currentTarget.restrict = "0-9.";
}
else
{
event.currentTarget.restrict = "0-9";
}
}
and it's seemed to work well so far.
I intend to implement this new restriction in this manner, but if there is a much more efficient way of restricting text input, please feel free to include it in a response.
Just to reiterate for clarity, I am asking how to implement functionality that will enable someone to input a mathematical expression into a TextField, and the program will register that input as an expression and calculate it.
Thanks for reading.
EDIT: I've done a bit more research and I've stumbled upon a Reverse Polish Notation calculator/parser/utility class/library/thingy that looks very useful. Seems kinda similar to the Executer class that fsbmain mentioned, but it looks a lot simpler to use and easier for me to understand.
However the problem still remains that I'd have to find an efficient way to restrict the syntax of user input to mathematical expressions, but at least now I have at least two ways of converting the string into a number for calculations.
That's quite a tough question actually, even definition for valid mathematical expressions which you mentioned is very complicated itself, i.e. expression 6-6-+-7 is a valid from as3 syntax point of view and gives result 7.
Regarding second part of your question:
converting the string into a mathematical expression that AS3 can understand
That's not possible to do with only native as3 means since eval-like functions are gone since as2 time, but you can try to use some as3-written syntax translator, i.e. Executer from flash-console project:
var exec:Executer = new Executer();
var res:* = exec.exec(this, "6-7");
trace("exec = " + res); //output "-1"
Although it's failed with some complex expressions from your question:
var exec:Executer = new Executer();
var res:* = exec.exec(this, "6-6-+-7");
trace("exec = " + res); //output "- 7"

Formatting String Value as Monetary Value in Google Apps Script

I have created a Google Form that has a field where a numeric value is entered by the user (with numeric validation on the form) and is then submitted. When the number (e.g., 34.00) gets submitted, it appears as 34 in the Google spreadsheet, which is annoying but understandable. I already have a script that runs when the form is submitted to generate a nicely-formatted version of the information that was submitted on the form, but I'm having trouble formatting that value as a monetary value (i.e., 34 --> $34.00) using the Utilities.formatString function. Can anyone help? Thanks in advance.
The values property of a form submission event as documented in Event Objects is an array of Strings, like this:
['2015/05/04 15:00', 'amin#example.com', 'Bob', '27', 'Bill', '28', 'Susan', '25']
As a result, a script that wishes to use any of these values as anything but a String will need to do explicit type conversion, or coerce the string to number using the unary operator (+).
var numericSalary = +e.values[9];
Alternatively, you could take advantage of the built-in type determination of Sheets, by reading the submitted value from the range property also included in the event. Just as it does when you type in values at the keyboard, Sheets does its best to interpret the form values - in this case, the value in column J will have been interpreted as a Number, so you could get it like this:
var numericSalary = e.range.getValues()[9];
That will be slower than using the values array, and it will still provide an unformatted value.
Formatting
Utilities.formatString uses "sprintf-like" formatting values. If you search the interwebs, you'll find lots of references for sprint variables, some of which are helpful. Here's a format that will turn a floating-point number into a dollar-formatted string:
'$%.2f'
$ - nothing magic, just a dollar sign
% - magic begins here, the start of a format
.2 - defines a number with two decimal places, but unspecified digits before the radix
f - expect a floating point number
So this is your simplest line of code that will do the conversion you're looking for:
var currentSalary = Utilities.formatString( '$%.2f', +e.values[9] );
The correct format to get your string into a proper numeric format is as follows:
var myString = myString.toLocaleString('en-US', { style: 'currency', currency: 'USD' });
If you only care about the $ sign and don't need commas the code below (also shown in one of the answers above will suffice.
var myString = Utilities.formatString( '$%.2f', myString );
In my experience toLocaleString performs sometimes performs strangely in Apps Script as opposed to JavaScript
I know this was years ago but might help someone else.
You should be able to add the commas in between with this
.toLocaleString(); after you format the string decimal then add the '$' sign in the beginning by just concating them together.
Ex:
myString = Utilities.formatString( '%.2f', myNumber );
myString = '$' + myString.toLocaleString();

Replace multiple characters in As3

I faced difficulties to replace a string.
var expression:String = '2X3';
var inString:String = expression;
inString=inString.replace("÷","/");
inString=inString.replace("X","*");
trace('Result.....',inString);
Output:-
Result.....2*3
Its alright.
But the problem was when i tried to give input as
var expression:String = '2X3X3X4X5X6';
output:-
Result.....2*3X3X4X5X6
But i need it in form of
Result.....2*3*3*4*5*6
and same for division.
Thanks & Regards
I use this for replacing all
var result:String=inString.split("X").join("*");
I know you've already selected a answer, but it lacked an explanation and a proper solution. The reason you see this happening is that String.replace(), when the pattern is a String, only replaces the first result. The solution is to use RegEx:
var expression:String = '2x3X3x4X5X6';
var result:String = expression.replace(/x/ig, "*");
trace(result); // output 2*3*3*4*5*6
The pattern uses two flags, global and case-insensitivity. That will grab all instances of the letter X, regardless of case, and search the entire string. The benefit with RegEx is that is extremely low level. There is little-to-no overhead when using a regular expression meaning they are incredibly fast. String.split and String.join use loops to function, I believe, which are considerably slower. Additionally, you have to store an additional array in memory.
Granted, these are negligible in most cases (difference in the 10's of microseconds, maybe), but not all. I had a project the required files to be scrambled. Unfortunately, the files were too large (200MB minimum) and the doing the replace().join() method was 4-5 slower than the RegEx method. With RegEx, I managed to reduce the lag while scrambling from a few seconds to 2-3 frames.
did you try inString=inString.replaceAll("X","*");? notice the "All" suffix!

Is it possible to prevent death by parentheses?

Occasionally, I will write some code with way more parentheses than I like.
if(!(new Day((((new Date()) / millisecondsPerDay) % 75)) instanceof oldDay))) {
// Bonus points if that condition made any sense to you
}
It is hard to keep track of how many parentheses I need to put, especially when I'm not using an IDE that immediately tells me when something is wrong. In fact, I bet the above example doesn't match the parentheses correctly. I've been pegged with errors from death by parentheses more than I would like to admit.
I was wondering if there was a way to circumvent this. What techniques can I use to avoid having to wrap things with so many parentheses?
Are there any languages with a mechanism that prevent the need for so many parentheses? For example, I thought adding special characters that automaticall close parentheses and one that automatically opens them might help. (< and > in the following example)
if(!(new Day<new Date()) / millisecondsPerDay) % 75> instanceof oldDay>
One viable alternative is to precompute the parenthesized values before the conditional loop. Take your code for example:
if(!(new Day((((new Date()) / millisecondsPerDay) % 75)) instanceof oldDay))) {
// Bonus points if that condition made any sense to you
}
Let's start breaking it up.
Date d1 = new Date();
var factor1 = (d1 / millisecondsPerDay ) % 75;
Day day1 = new Day (factor1);
if (!day1 instanceof oldDay) {
// do something
}
Remember that code is written for humans to read and only afterwards for machines to execute. If you find giant conditionals, then start preprocessing them and break it up. If it takes more than a second to figure out what your condition is checking, then it's probably too long.
Well, first of all i always like to refactor this kind of code. If i can, i extract part of expression to the variable (or function, whichever suites best), then you can make more sense to the code itself, and you would'nt need to make such a mess
bool isOldDay(int someFactor)
{
if(someFactor instanceof oldDay)
{
return true;
}
return false;
}
var today = new Date();
var particularFactor = today/millisecondsPerDay;
var someFactor = particularFactor % 75
var day = new Day(someFactor);
if(!isOldDay(day)) //Do something
EDIT: By the way if you want to do something without parentheses you can try something like this: Reverse Polish Notation
Which you can make 5 + ((1 + 2) * 4) − 3 into this thing : 5 1 2 + 4 * + 3 - .Of course this form may be very close to stack representation of calculations in compilators.
If i follow:
var a = new Date() / millisecondsPerDay) % 75
var newDay = new Day(a);
if (! newDay instanceof oldDay) {
//do something
}
If you can't read an inline logic... just put it on multiple line! ;-)
That many parens is a pretty good indication that
The author doesn't understand the operator precedence of the language. For instance, you've wrapped a constructor invocation new Date() in a completely redundant set of parentheses (new Date()). Unless your language is different than any normal language, that prefix new operator is going to bind tighter than almost any other operator.
The author doesn't care about understandability.
Make it more understandable, testable and maintainable. Somebody down the line (who might well be you, will thank you for it...or curse you for not doing so).
Some hints:
Understand your language's operator precedence. Don't add parentheses without good reason. Somebody who does understand operator precedence has to spend some time figuring out why you put those parens in: are you doing something non-obvious here?
Break the expression up. Use stack space (it's cheap).
Compute each simple subexpression as an independent local variable, building on the previous ones.
make the variable names reflect what they represent.
Then test only the final temporary. In your case, that looks to be a boolean.
Writing code like that makes it easy to under stand (there are no complex expression), it makes it easy to test (simple expressions is much easier to check for correctness). It makes it easier to identify/locate problems.
I would say the answer to this is NO, because the whole point of all those parentheses is to avoid ambiguity in the expression. If you remove them, the expression may not be evaluated in the way that you think it will.
Ergo, if there was such a construct as <> to fix/add your missing parens, if may not add them in the place you were expecting it to.
Simple example (as if it were needed):
(90 / 100 - 1)
...will evaluate to either...
((90 / 100) - 1) // = -0.1
...or...
(90 / (100 - 1)) // = 0.90909090...
... and you have no real way to know which one it will be.
The only alternative is to move some of the parts outside your expression, store the results in variables so you can evaluate less in your expression.