I'm trying to add the results of a loop to an array.
Here is my code:
<cfset mobNumbers = ArrayNew(1)>
<cfloop query = "staffLoop">
<cfscript>
mobileNo = staffLoop.mobileno;
mobileNo = mobileNo.replaceAll("[^0-9]", "");
ext = staffLoop.extension;
ext = ext.replaceAll("[^0-9]", "");
if (Left(mobileNo, 2) == "07" || Left(mobileNo, 3) == "447") {
recipient = mobileNo;
} else if (Left(ext, 2) == "07" || Left(ext, 3) == "447") {
recipient = ext;
} else {
recipient = "";
}
if (Left(recipient, 2) == "07") {
recipient = "447" & Right(recipient, Len(recipient) - 2);
}
if (Len(recipient) == 12) {
[send text code]
}
</cfscript>
</cfloop>
<cfset ArrayAppend(mobNumbers, "recipient")>
The goal is to get an array of all mobile numbers.
My code isn't working and I'm after some research, I'm not sure what to do. Any ideas?
If possible I'd like to use non-cfscript for my solution but if using cfscript is easier, that's fine.
As Adam points out, the ArrayAppend needs to be inside the loop. You'll also need to remove the quotes around the "recipient" in your call to ArrayAppend, otherwire you'll have an array of the String "recipient".
Your arrayAppend() needs to be inside the loop, otherwise you're just appending the last result after the loop has finished.
Related
say I have Some List inside a List.
List<List> rules = [
[],
[],
[],
];
Beside, I have 3 list.
They will have some widgets inside, base on another process
List<TextSpan> arrayRule1 = [];
List<TextSpan> arrayRule2 = [];
List<TextSpan> arrayRule3 = [];
Say i want to loop through rules, and loop on each array in it.
How can i can make a dynamic call by concatenate the index of the loop with a string, to use the actual existing array ?
int indice = 0;
for (List rule in rules) {
indice++
for (String statement in rule) {
if (statement == "vrai")
arrayRule+indice.add(// code... ) // Throw an error
else if (statement == "faux" || statement == "fausse")
arrayRule+indice.add(// code... ) // Throw an error
else
arrayRule+indice.add(// code... ) // Throw an error
}
}
I do know how to do this in Javascript, but in Dart, I'm lost
I don't want to make a If...else statement just to select my previous arrayRule1 arrayRule2 arrayRule3 based on the indice variable.
Any idea would be welcome, thanks !
Reflection is not easy in dart, look for dart:mirrors package but I think it does not work in flutter. You have to find another way of doing it.
What you can do it create a map like this
List<TextSpan> arrayRule1 = [];
List<TextSpan> arrayRule2 = [];
List<TextSpan> arrayRule3 = [];
Map<int, List<TextSpan>> arrayRuleMap = {
1: arrayRule1,
2: arrayRule2,
3: arrayRule3,
};
then instead of
arrayRule+indice.add(// code... ) // Throw an error
You can use
arryaRuleMap[indice].add(// code... ) // Throw an error
Edit
For more simplification you can directly initialise array in map instead of creating 3 variables.
Map<int, List<TextSpan>> arrayRuleMap = {
1: [],
2: [],
3: [],
};
I have a solution for filtering on this question.
This works perfectly with a column that has string values. When I try to filter a column with numeric values it will not work. I'm assuming it is because .setHiddenValues() will not accept numeric values. I could be wrong.
Let me explain my scenario:
The user inputs a value on an HTML interface, let's say 6634.
The HTML calls my function on .gs and passes the numeric value the user inputted.
google.script.run //Executes an Apps Script JS Function
.withSuccessHandler(updateStatus) //function to be called upon successfull completion of Apps Script function
.withFailureHandler(failStatus)
.withUserObject(button) //To pass the event element object
.projectSearch2(projectID); //Apps Script JS Function
return;
The function (on the linked question above) will take that value and bump it up against the values in a column deleting the value if it is found. What I am left with is an array of values that I do not want filtered.
function projectSearch2(projectID){
var ss = SpreadsheetApp.getActive();
var monthlyDetailSht = ss.getSheetByName('Data Sheet');
var monLastCN = monthlyDetailSht.getLastColumn();
var monLastRN = monthlyDetailSht.getLastRow();
var data = monthlyDetailSht.getRange(1,1,1,monLastCN).getValues();//Get 2D array of all values in row one
var data = data[0];//Get the first and only inner array
var projectIDCN = data.indexOf('Project Id') + 1;
//Pull data from columns before filtering
var projectIDData = monthlyDetailSht.getRange(2,projectIDCN,monLastRN,1).getValues();
//Reset filters if filters exist
if(monthlyDetailSht.getFilter() != null){monthlyDetailSht.getFilter().remove();}
//Start Filtering
var projectIDExclCriteria = getHiddenValueArray(projectTypeData,projectID); //get values except for
var rang = monthlyDetailSht.getDataRange();
var projectIDFilter = SpreadsheetApp.newFilterCriteria().setHiddenValues(projectIDExclCriteria).build();//Create criteria with values you do not want included.
var filter = rang.getFilter() || rang.createFilter();// getFilter already available or create a new one
if(projectID != '' && projectID != null){
filter.setColumnFilterCriteria(projectIDCN, projectIDFilter);
}
};
function getHiddenValueArray(colValueArr,visibleValueArr){
var flatUniqArr = colValueArr.map(function(e){return e[0];})
.filter(function(e,i,a){return (a.indexOf(e.toString())==i && visibleValueArr.indexOf(e.toString()) ==-1); })
return flatUniqArr;
}
That array is used in .setHiddenValues() to filter on the column.
Nothing is filtered however. This works for all columns that contain string values, just not columns with numeric values. At this point I'm lost.
Attempted Solutions:
Convert user variable to string using input = input.toString(). Did not work.
manually inserted .setHiddenValues for projectIDExclCriteria. Like this: var projectIDFilter = SpreadsheetApp.newFilterCriteria().setHiddenValues([1041,1070,1071,1072]).build(); That succeeded so I know the issue is before that.
Step before was calling getHiddenValueArray. I manually inserted like so: var projectIDExclCriteria = getHiddenValueArray(projectIDData,[6634]); It is not working. Is the issue with that getHiddenValueArray function not handling the numbers properly?
Here is a solution. Changing the following:
.filter(function(e,i,a){return (a.indexOf(e.toString())==i && visibleValueArr.indexOf(e.toString()) ==-1); })
To:
.filter(function(e,i,a){return (a.indexOf(e) == i && visibleValueArr.indexOf(e) == -1); })
That works! Thank you Tanaike. The next question is will this impact columns that are not numeric. I have tested that and it works as well.
How about this modification?
From :
.filter(function(e,i,a){return (a.indexOf(e.toString())==i && visibleValueArr.indexOf(e.toString()) ==-1); })
To :
.filter(function(e,i,a){return (a.indexOf(e) == i && visibleValueArr.indexOf(e) == -1); })
Note :
In this modification, the number and string can compared using each value.
If you want to use return (a.indexOf(e.toString())==i && visibleValueArr.indexOf(e.toString()) ==-1), you can achieve it by modifying from colValueArr.map(function(e){return e[0];}) to colValueArr.map(function(e){return e[0].toString();}).
In this modification, colValueArr.map(function(e){return e[0].toString();}) converts the number to string, so the number is used as a string.
Reference :
Array.prototype.indexOf()
I have working code, that delete row from sheet if column corresponds to one of the conditions. It based on arrays and because of it works much more faster than standard google sheet deleteRow function. I call it like this:
deleteRowsBV('SIZ',4,'0','')
where
deleteRowsBV(listName,ColNum,FirstSearch,SecondSearch)
What I want is a call function with more or less and equal signs, like this:
deleteRowsBV('SIZ',4,<='0',=='')
But in case of my main function, it doesn't work, when I specify a variable instead of a sign and a value.
Here is main function:
function deleteRowsBV(listName,ColNum,FirstSearch,SecondSearch) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(listName);
var DataLengBefore = sheet.getLastRow();
var DataColLeng = sheet.getLastColumn();
var data = sheet.getRange(1,1,DataLengBefore,DataColLeng).getValues();
for (var i = data.length-1; i >= 0; i--) {
if (data[i][ColNum] <= FirstSearch||data[i][ColNum] == SecondSearch) {
data.splice(i, 1);
}
}
sheet.getRange(10, 1, DataLengBefore,DataColLeng).clearContent();
sheet.getRange(10, 1,data.length,5).setValues(data);
}
Based from this related post, spreadsheet rows and columns are numbered starting at 1, for all methods in the SpreadsheetApp, while javascript arrays start numbering from 0. You need to adjust between those numeric bases when working with both. When deleting rows, the size of the spreadsheet dataRange will get smaller; you did take that into account, but because you're looping up to the maximum size, the code is complicated by this requirement. You can simplify things by looping down from the maximum.
You may refer with this thread. However, this only looks at the value from a single cell edit now and not the values in the whole sheet.
function onEdit(e) {
//Logger.log(JSON.stringify(e));
//{"source":{},"range":{"rowStart":1,"rowEnd":1,"columnEnd":1,"columnStart":1},"value":"1","user":{"email":"","nickname":""},"authMode":{}}
try {
var ss = e.source; // Just pull the spreadsheet object from the one already being passed to onEdit
var s = ss.getActiveSheet();
// Conditions are by sheet and a single cell in a certain column
if (s.getName() == 'Sheet1' && // change to your own
e.range.columnStart == 3 && e.range.columnEnd == 3 && // only look at edits happening in col C which is 3
e.range.rowStart == e.range.rowEnd ) { // only look at single row edits which will equal a single cell
checkCellValue(e);
}
} catch (error) { Logger.log(error); }
};
function checkCellValue(e) {
if ( !e.value || e.value == 0) { // Delete if value is zero or empty
e.source.getActiveSheet().deleteRow(e.range.rowStart);
}
}
Using google scripts in google sheets.I'm trying to use an arrary that has zip codes in it to look at a certain field and if that field matches one of the values in the array then it will proceed otherwise i'll keep going. I can't seems to figure that out. I'm having issues with the .indexOf function.
for (var i = 0; i < data.length; ++i) {
var tzip = new Array("02703", "02763", "02019", "01504", "02712", "02720");
var dzip = new Array("02721", "02722", "02723", "02724", "02035", "02038");
var row = data[i];
var emailAddress = row[18]; // First column
var message = "Hello"
var emailSent = row[19]; // Third column
var leadsent = row[20];
if (emailAddress == "Oil Sales" && tzip.indexOf(row[9] != 1) && emailSent != LEAD_SENT && leadsent != LEAD_COPIED) {
}
}
You had tzip.indexOf(row[9] != 1) where row[9] != 1 will evaluate to a Boolean value. This means that you will be searching tzip for the index of a Boolean value.
If you change that to
tzip.indexOf(row[9]) != 1
then the value of row[9] can be at any index in tzip except for index 1.
I think what you meant was
tzip.indexOf(row[9]) != -1
since the indexOf function returns the index -1 if the value row[9] is not contained in tzip.
I have a Problem with SwityJson and removing an Element of an Array
For further Datahandling i must remove some Elements.
here my Code
self.jsonObj = JSON(value)
//Filtern
for i in 0 ..< self.jsonObj["customer"].count {
if self.jsonObj["customer"][i]["Group_A"].string == "Mr Abcde"
|| self.jsonObj["customer"][i]["Group_A"].string == "Mr Bcde"
|| self.jsonObj["custome"][i]["Group_B"].string == "Mr Abcde"
|| self.jsonObj["customer"][i]["Group_B"].string == "Mr Bcde"
{
self.jsonObj["customer"].arrayObject?.removeAtIndex(i)
}
}
Now the Problem: If running the Code not all found Element are removed.
I think that looping through all Elements is too fast. There is noch Time for the removing Task?!
How can I handle it. Looping...found something...stop looping...remove Item...start looping..
By making the If-Statement for three Times all is fine an all found Elements are removed, but hey, this is not what i want.
Or is it possible to filter the Array an then say
filterdData = jsonObj
Try
//Filtern
for i in 0 ..< self.jsonObj["customer"].count {
let groupA = self.jsonObj["customer"][i]["Group_A"].string
let groupB = self.jsonObj["customer"][i]["Group_B"].string
if groupA == "Mr Abcde" || groupA == "Mr Bcde" || groupB == "Mr Abcde" || groupB == "Mr Bcde"{
self.jsonObj["customer"].rawArray.removeAtIndex(i)
}
}
Not only does this have less calls to the JSON object(potentially saving speed) but it also uses rawArray instead of arrayObject which writes directly the array instead of going through the arrayObject to the rawArray.
The problem is that you're changing the count that terminates the loop from within the loop. You need to not do that, perhaps using filter or a related approach instead
I would recommend normalizing the data before modifying it. But failing that you could try this:
let filteredJson = self.jsonObj["customer"].filter { elem in
!(["Mr Abcde", "Mr Bcde"].contains(elem.["Group_A"].string) ||
["Mr Abcde", "Mr Bcde"].contains(elem.["Group_B"].string))
}
and then use the filteredJson constant.