I am trying to apply for loop in the xpages application.
In the computed field, I put the following code and it shows the result as expected.
var msg = "";
for(var j = 1; j <5;j++)
{
msg += "* This message is from " +j +" " ;
}
return msg;
//Result will show something like this
//"* This message is from 1 * This message is from 2 * This message is from 3 * This message is from 4 * This message is from 5 "
Assume in page A there is a multiline edit box, it uses sessionScope variable (ssvTopic). In pages B there is a computed field, I can show the values from the multiline edit box by use this code
sessionScope.ssvTopic
This works fine. Now I try to apply the sessionScope variable in the for loop.
var msg ="";
var value = sessionScope.ssvTopic
for(var i =0; i< value.length; i++)
{
msg += "* This message is from " + value+" " ;
}
return msg;
When I run the application, I notice the value.length means the number of characters in value. I mean if the sessionScope.ssvTopic values are life style, news, sports, the characters are 24, so the in the for loop, the message will display 24 times.
So I change the code value.length to #Count(value). When I run the application, the message only display one time.
var msg ="";
var value = sessionScope.ssvTopic
for(var i =0; i< #Count(value); i++)
{
msg += "* This message is from " + value+" " ;
}
return msg;
//The result display like this, it only display one time
//* This message is from life style, news, sports
I think #Count(value) is close to the result (compare with value.length), but I don't understand why it shows the message one time only.
I also try to put the sessionScope value in a array, but the result is the same, it just shows one message.
var msg ="";
var value = sessionScope.ssvTopic
var valueArray = new Array();
viewScope.put("valueArray", #Implode(valueArray, ",")) ;
valueArray.push(value);
//no matter if I use #Count(valueArray) or valueArray.length, the result does not have difference
for(var i =0; i< #Count(valueArray); i++)
{
msg += "* This message is from " + valueArray+" " ; //no matter if I use valueArray or valueArray[i], the result does not have difference too
}
return msg;
I am not sure which part I make mistake. What I intend to do is to show the number of messages depends on the number of the sessionScope variable values. In my case if the sessionScope variable contains life style, news, sports, the result will be someting like this
* This message is from life style * This message is from news * This messages is from sports
If I run this code again, it works fine.
var msg = "";
for(var j = 1; j <5;j++)
{
msg += "* This message is from " +j +" " ;
}
return msg;
So I just change the "5" to sessionScope variable, it will not show the number of messages depends on the number of the sessionScope variable values.
Would someone let me know how to solve this issue. Thanks a lot.
(A quick update)
I try the following the code but it does not return anything.
for(var i =0; i< sessionScope.ssvTopic; i++)
{
msg += "* This message is from " + ssvTopic[i]+" " ; // with [i] or without [i], the result is the same, it does not return anything
}
return msg;
Instead of return the message, I try to return other things such #Count(value), #Count(valuArray), valueArray.length.
#Count(value) //this returns 1.0
#Count(valueArray) //this returns 1.0
valueArray.length //this returns 1.0
value.length //this return 24.0 as mentioned above, this returns the number of characters of the value
Therefore I notice this a mistake in the code, but I don't understand the The mistake only return 1.0 for the result.
You missed only a little thing to get it to work:
var msg = "";
var value = sessionScope.ssvTopic.split('\n');
for(var i = 0; i < value.length; i++) {
msg += "* This message is from " + value[i] + " " ;
}
return msg;
Multiline edit box returns a multi-line string, not an array of strings. So, you need to split the string by newline first. Then you can work with the resulting array.
(#Count always returned 1 as multiline edit box's value was only one string)
Related
In apps script I want to obtain formatted 'number' strings. The input is an unformatted number. With an earlier answer posted by #slandau, I thought I had found a solution by modifying his code (see code snippet). It works in codepen, but not when I am using apps script.
1. Does anyone know what went wrong here?
2. I noticed this code works except when entering a number ending in .0, in that case the return value is also .0 but should be .00. I would like some help fixing that too.
Thanks!
I have tried to look for type coercion issues, but wasn't able to get it down. I am fairly new to coding.
function commaFormatted(amount)
{
var delimiter = ","; // replace comma if desired
var a = amount.split('.', 2);
var preD = a[1]/(Math.pow(10,a[1].length-2));
var d = Math.round(preD);
var i = parseInt(a[0]);
if(isNaN(i)) { return ''; }
var minus = '';
if(i < 0) { minus = '-'; }
i = Math.abs(i);
var n = new String(i);
var a = [];
while(n.length > 3)
{
var nn = n.substr(n.length-3);
a.unshift(nn);
n = n.substr(0,n.length-3);
}
if(n.length > 0) { a.unshift(n); }
n = a.join(delimiter);
if(d.length < 1) { amount = n; }
else { amount = n + '.' + d; }
amount = minus + amount;
return amount;
}
console.log(commaFormatted('100000.3532'))
The expected result would be 100,000.35.
I am getting this in the IDE of codepen, but in GAS IDE is stops at the .split() method => not a function. When converting var a to a string = I am not getting ["100000", "3532"] when logging var a. Instead I am getting 100000 and was expecting 3532.
Based on this answer, your function can be rewritten to
function commaFormatted(amount)
{
var inputAmount;
if (typeof(amount) == 'string') {
inputAmount = amount;
} else if (typeof(amount) == 'float') {
inputAmount = amount.toString();
}
//--- we expect the input amount is a String
// to make is easier, round the decimal part first
var roundedAmount = parseFloat(amount).toFixed(2);
//--- now split it and add the commas
var parts = roundedAmount.split(".");
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ",");
return parts.join(".");
}
console.log(commaFormatted(100000.3532));
console.log(commaFormatted('1234567.3532'));
I want to print out all number from 1 to 1,000,000 with 1,000 numbers per line. and return the response without having a long delay.
Thanks in advance for any type of help!!!
Well, first you can create a function to print numbers from 1 to 1000.
function getThousand(index) {
var result = '';
for (var i = index; i < index + 1000; i++) {
result += i + ' ';
}
return result;
}
Then, you need a function to call this for 1 to 1000000.
function getAll() {
var result = '';
for (var i = 0; i < 1000; i++) {
result = getThousand((i * 1000) + 1) + " \n";
fs.appendFileSync('foo.txt', result);
}
}
Then call it all:
getAll();
This will save your lines into a file. At the end of getAll() you can print what you need.
I want to split up a document by quotation it's marks. I see (here) that they're able to fake this answer by adding a '\' at the beginning of the quotation mark, however in my document there are hundreds of these strings I'm trying to cut string out of, so changing that manually would be a real pain and time taker.
Here's an example of the string I'm trying to cut from:
D
And here's an example of my current code:
private function onShopTextLoaded(e:Event):void
{
shopArrayOfWebsites = e.target.data.split(/\n/);
for (var i:String in shopArrayOfWebsites)
{
trace("shopArrayOriginal: " + shopArrayOfWebsites[i]);
var arrayString:String = shopArrayOfWebsites[i].split('"' /* << that won't work */ );
trace(arrayString[1]);
//shopArrayOfWebsites[i] = arrayString[1];
}
}
private function postInShopView():void
{
var iLevel:Number = 1;
var iSection:Number = 1;
var iShop:Number = 0;
for (var i:String in shopArrayOfWebsites)
{
iShop++;
if(iShop >= 5)
{
iSection++;
iShop = 0;
}
if(iSection >= 5)
{
iLevel++;
iSection = 1;
}
var shopStringEquiv:String = "L" + iLevel.toString() + "S" + iSection.toString() + "Shop" + iShop.toString();
if(global.shopTarget == shopStringEquiv)
{
var result:uint = ExternalInterface.call("showShopFrame", shopArrayOfWebsites[i]);
}
//trace(shopStringEquiv);
//trace(shopArrayOfWebsites[i]);
}
}
I get an error of:
ReferenceError: Error #1069: Property 1 not found on String and there is no default value.
So from here I'm not quite sure how I'm able to split up this document. Any ideas? Thanks!
I've been given the following exercise but can't seem to get it working.
//Remove duplicate characters in a
// given string keeping only the first occurrences.
// For example, if the input is ‘tree traversal’
// the output will be "tre avsl".
// ---------------------
var params = 'tree traversal word';
var removeDuplicates = function (string) {
return string;
};
// This function runs the application
// ---------------------
var run = function() {
// We execute the function returned here,
// passing params as arguments
return removeDuplicates;
};
What I've done -
var removeDuplicates = function (string) {
var word ='';
for(var i=0; i < string.length; i++){
if(string[i] == " "){
word += string[i] + " ";
}
else if(string.lastIndexOf(string[i]) == string.indexOf(string[i]))
{
word += string[i];
}
}
return word;
};
I'm not allowed to use replaceAll and when I create an inner for loop it doesn't work.
<script>
function removeDuplicates(string)
{
var result = [];
var i = null;
var length = string.length;
for (i = 0; i < length; i += 1)
{
var current = string.charAt(i);
if (result.indexOf(current) === -1)
{
result.push(current);
}
}
return result.join("");
}
function removeDuplicatesRegex(string)
{
return string.replace(/(.)(?=\1)/g, "");
}
var str = "tree traversal";
alert(removeDuplicates(str));
</script>
First of all, the run function should be returning removeDuplicates(params), right?
You're on the right lines, but need to think about this condition again:
else if(string.lastIndexOf(string[i]) == string.indexOf(string[i]))
With i = 0 and taking 'tree traversal word' as the example, lastIndexOf() is going to be returning 5 (the index of the 2nd 't'), whereas indexOf() will be returning 0.
Obviously this isn't what you want, because 't' hasn't yet been appended to word yet (but it is a repeated character, which is what your condition does actually test for).
Because you're gradually building up word, think about testing to see if the character string[i] exists in word already for each iteration of your for loop. If it doesn't, append it.
(maybe this will come in handy: http://www.w3schools.com/jsref/jsref_search.asp)
Good luck!
I have a multivalue field on my document that I would like to remove a value based on the value.
I came up with this:
var doc:NotesDocument = rowData.getDocument();
var item:NotesItem = doc.getFirstItem("ValidProjects");
var a:Array = item.getValues()
for (var v in a)
dBar.info("Before removed V=" + v );
removeFromArray(a,compositeData.ProjectID);
doc.replaceItemValue("ValidProjects",a );
for (var v in a)
dBar.info("After removed V=" + v);
doc.save();
function removeFromArray(arr, val) {
for(var i=0; i<arr.length; i++) {
dBar.info("Value = " + arr[i] + " Remove = " + val);
if(arr[i] == val) {
dBar.info("Removing " + i)
arr.splice(i, 1);
break;
}
}
}
The removeFromArray is being called successfully and I can see the "Removing 0" message displayed in the debugbar as expected but the array does not change at all and the value is not removed. Any ideas?
Treat the ItemValues as Vector.
function removeFromItemValues(java.util.Vector vector, val) {
// see http://docs.oracle.com/javase/6/docs/api/java
vector.remove(val);
return vector; //Optional
}
Hope that helps
Just a quick shot... I am not sure that arguments are passed "by reference"...?
If not, then that is the reason. I would normally prefer to use a function to return a value instead. From a programming point of view I find it more clear to read what the code does. In this particular example you would change your code to something like:
function removeFromArray(arr, val) {
for(var i=0; i<arr.length; i++) {
dBar.info("Value = " + arr[i] + " Remove = " + val);
if(arr[i] == val) {
dBar.info("Removing " + i)
arr.splice(i, 1);
break;
}
}
return arr;
}
and then you would call it like:
a = removeFromArray(a,compositeData.ProjectID);
You do not write whether you can see a change in your "After..." message? - or you just can see in the document that the value did not change?
Best regards
/John