Filter a sheet based on criteria selected on another sheet and carried as an array - arrays

A Google sheet I've designed for use in analyzing decennial censuses requires that cells be merged and that two rows be used to handle each census record. Because of the merged cells, my users can't use the normal Google Sheets filter process, so I need to create an alternate way to filter records. I'm hitting a snag. I've created a sheet that allows the user to set up the desired filter criteria. But I can't get the choices to translate into a usable GAS script that works. (I won't complicate this with all of the code that extracts the two-line records to another sheet and filters out all but one line per record, which can then be used to filter and rebuild the two-line records in their filtered form.)
The filtering criteria sheet (see below) allows up to nine levels of criteria. To the right, I have displayed columns that will be hidden from the user, but allow me to capture the information I need to create the filter in the script. Column I has the operator text needed in the script, column G is the column where (in the case of the first line) the Census Year is in the sheet being filtered, and column C has the criteria. I've collected the values in an array I'm calling filterArray.
I need to go through each line of the criteria, determining if there was a selection made. If so, I need to filter for the criteria. Here is my For loop:
// Gather filters from Filter Criteria
for (var i = 0; i <= 9; i = i + 1) {
if(filterArray[i][0]!==""){
myFilterText = SpreadsheetApp.newFilterCriteria()+"."+filterArray[i][8]+"("+filterArray[i][2]+")"
myFilter.setColumnFilterCriteria(filterArray[i][6],myFilterText)
}
}
The last line triggers this message:
Exception: The parameters (number,String) don't match the method signature for SpreadsheetApp.Filter.setColumnFilterCriteria.
If I was not using the array as a variable, I'd want it to basically look like this as it goes through the first loop:
for (var i = 0; i <= 9; i = i + 1) {
if('A7'!==""){
myFilterText = SpreadsheetApp.newFilterCriteria().whenNumberLessThan(1850);
myFilter.setColumnFilterCriteria(10,myFilterText)
}
}
In addition to trying the first code, with the array content, I've tried to create the whole string "SpreadsheetApp.newFilterCriteria()."+filterArray[i][8]+"("+filterArray[i][2]+")" as the contents of myFilterText. I get the same error.
How can I turn the criteria the user is selecting into a code that can run to filter records?

I found a solution, which is VERY code-heavy, unfortunately. I'm using a switch-case to evaluate every possible filter condition and to code the variable I need. The section of the code related to the question I posted is now this:
/**
* Activating Filter and pasting records to new sheet called "Filtered Records_Prep"
*/
var filterRange = spreadsheet.getActiveRange().getA1Notation();
var myFilter = spreadsheet.getRange(filterRange).createFilter();
var myFilterText = ""
var sheet = spreadsheet.getActiveSheet();
// Filter selection to row 1 of each set, eliminating 2s and blanks
var Filter_Criteria0 = SpreadsheetApp.newFilterCriteria().whenNumberEqualTo(1);
myFilter.setColumnFilterCriteria(3,Filter_Criteria0);
// Gather filters from Filter Criteria
for (var i = 0; i <= 9; i = i + 1) {
if(filterArray[i][0]!==""){
myCol = filterArray[i][6];
myFilterCondition = filterArray[i][8];
myFilterCriteria = filterArray[i][2];
switch(myFilterCondition)
{
case "whenNumberEqualTo":
myFilterText = SpreadsheetApp.newFilterCriteria().whenNumberEqualTo(myFilterCriteria);
break;
case "whenNumberNotEqualTo":
myFilterText = SpreadsheetApp.newFilterCriteria().whenNumberNotEqualTo(myFilterCriteria);
break;
case "whenNumberContains":
myFilterText = SpreadsheetApp.newFilterCriteria().whenNumberContains(myFilterCriteria);
break;
case "whenNumberDoesNotContain":
myFilterText = SpreadsheetApp.newFilterCriteria().whenNumberDoesNotContain(myFilterCriteria);
break;
case "whenCellEmpty":
myFilterText = SpreadsheetApp.newFilterCriteria().whenCellEmpty();
break;
case "whenCellNotEmpty":
myFilterText = SpreadsheetApp.newFilterCriteria().whenCellNotEmpty();
break;
case "whenNumberGreaterThan":
myFilterText = SpreadsheetApp.newFilterCriteria().whenNumberGreaterThan(myFilterCriteria);
break;
case "whenNumberGreaterThanOrEqualTo":
myFilterText = SpreadsheetApp.newFilterCriteria().whenNumberGreaterThanOrEqualTo(myFilterCriteria);
break;
case "whenNumberLessThan":
myFilterText = SpreadsheetApp.newFilterCriteria().whenNumberLessThan(myFilterCriteria);
break;
case "whenNumberLessThanOrEqualTo":
myFilterText = SpreadsheetApp.newFilterCriteria().whenNumberLessThanOrEqualTo(myFilterCriteria);
break;
case "whenNumberStartsWith":
myFilterText = SpreadsheetApp.newFilterCriteria().whenNumberStartsWith(myFilterCriteria);
break;
case "whenNumberEndsWith":
myFilterText = SpreadsheetApp.newFilterCriteria().whenNumberEndsWith
(myFilterCriteria);
break;
case "whenTextEqualTo":
myFilterText = SpreadsheetApp.newFilterCriteria().whenTextEqualTo(myFilterCriteria);
break;
case "whenTextNotEqualTo":
myFilterText = SpreadsheetApp.newFilterCriteria().whenTextNotEqualTo(myFilterCriteria);
break;
case "whenTextContains":
myFilterText = SpreadsheetApp.newFilterCriteria().whenTextContains(myFilterCriteria);
break;
case "whenTextDoesNotContain":
myFilterText = SpreadsheetApp.newFilterCriteria().whenTextDoesNotContain(myFilterCriteria);
break;
case "whenTextStartsWith":
myFilterText = SpreadsheetApp.newFilterCriteria().whenTextStartsWith(myFilterCriteria);
break;
case "whenTextEndsWith":
myFilterText = SpreadsheetApp.newFilterCriteria().whenTextEndsWith
(myFilterCriteria);
break;
default:
ui.alert("This criteria was not found.")
}
myFilter.setColumnFilterCriteria(myCol,myFilterText);
} else {
return false;
}
}

Related

Programmatically add Aggregate Transform - Count Distinct to SSIS package

I am working on programmatically creating Aggregate transform with aggregation type as count distinct and i am able to create other aggregations like min,max,count.. but when it comes to count distinct i am getting below error
The component has detected potential metadata corruption during
validation. Error at Data Flow Task - Load Count Dist [Aggregate -
All [2]]: The "Aggregate - All.Outputs[Aggregate Output
1].Columns[col1]" is missing the required property
"CountDistinctScale". The object is required to have the specified
custom property.
I am unable to find "CountDistinctScale" custom property as this custom property doesn't exit for other aggregation and magically appears when count distinct is selected,is there a method which i need to call to create new custom property?
I understand there are not a lot of people who know how to programmatically create package, please help me find someone with knowledge or suggest me how i can get some help.
IDTSComponentMetaData100 Aggregate = pipeline.ComponentMetaDataCollection.New();
Aggregate.ComponentClassID = app.PipelineComponentInfos["Aggregate"].CreationName;
// Get the design time instance of the derived column
var DesignAggregate = Aggregate.Instantiate();
DesignAggregate.ProvideComponentProperties(); //design time
Aggregate.Name = "AggregateComponent";
IDTSPath100 AggregatePath = pipeline.PathCollection.New();
AggregatePath.AttachPathAndPropagateNotifications(pipeline.ComponentMetaDataCollection[Prev_Transform.Transformation_Name].OutputCollection[Prev_Transform.Output_Number], Aggregate.InputCollection[0]);
//update the metadata for the derived columns
DesignAggregate.AcquireConnections(null);
DesignAggregate.ReinitializeMetaData();
DesignAggregate.ReleaseConnections();
// Mark the columns we are joining on
IDTSInput100 AggregateInput = Aggregate.InputCollection[0];
IDTSInputColumnCollection100 AggregateInputColumns = AggregateInput.InputColumnCollection;
IDTSVirtualInput100 AggregateVirtualInput = AggregateInput.GetVirtualInput();
IDTSVirtualInputColumnCollection100 AggregateVirtualInputColumns = AggregateVirtualInput.VirtualInputColumnCollection;
IDTSOutput100 AggregateoutputCollection = Aggregate.OutputCollection[0];
// Note: input columns should be marked as READONLY
foreach (IDTSVirtualInputColumn100 vColumn in AggregateVirtualInputColumns)
{
int sourceColumnLineageId = AggregateVirtualInput.VirtualInputColumnCollection[vColumn.Name].LineageID;
DesignAggregate.SetUsageType(AggregateInput.ID, AggregateVirtualInput, sourceColumnLineageId, DTSUsageType.UT_READONLY);
// create a new output column
IDTSOutputColumn100 newOutputColumn = DesignAggregate.InsertOutputColumnAt(AggregateoutputCollection.ID, 0, vColumn.Name, string.Empty);
// set the data type porperties to the same values as these of the input column
newOutputColumn.SetDataTypeProperties(AggregateVirtualInput.VirtualInputColumnCollection[vColumn.Name].DataType, AggregateVirtualInput.VirtualInputColumnCollection[vColumn.Name].Length, 0, 0, AggregateVirtualInput.VirtualInputColumnCollection[vColumn.Name].CodePage);
newOutputColumn.MappedColumnID = 0;
for (int i = 0; i < newOutputColumn.CustomPropertyCollection.Count; i++)
{
IDTSCustomProperty100 property = newOutputColumn.CustomPropertyCollection[i];
switch (property.Name)
{
case "AggregationColumnId":
property.Value = sourceColumnLineageId;
break;
case "AggregationType":
property.Value = 3;
break;
case "IsBig":
property.Value = 1;
break;
case "AggregationComparisonFlags":
property.Value = 0;
break;
}
}
}

I have a two differnt array & i want to remove items in the second one that have the same property value of array1

inside the code $response['results'] is for google api. And $da is my databse records I am comparing these two using foreach on the basis of latitude of both data records. please help me out.
Here is my code :
$setarraymy= [];
$setarray = [];
foreach($da as $data1){
foreach ($response['results'] as $res){
switch (true){
case (round($data1['location']['lat'],4)!== round($res['geometry']
['location']['lat'],4) && !in_array($res['geometry']['location']['lat'],$setarray)):
array_push($setarray,$res);
break;
case (!in_array($data1['location']['lat'],$setarraymy)):
array_push($setarraymy,$data1);
break;
default:
break;
}
}
}
echo json_encode(array( 'Results' =>$setarraymy,
'status'=>'OK'),JSON_PRETTY_PRINT);
$new_array = array_unique($setarray, SORT_REGULAR);
echo json_encode( array('Results'=>$new_array,
'status'=>'OK'),JSON_PRETTY_PRINT);
return;
Manipulating array will be difficult, better to use collections and lastly convert collection to array as per your logic.
Avinash

Improve function delete rows by contain value

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);
}
}

for loop not iterating over last element of 2D array in google app script (GAS)

I am working on a script that, in part, takes an array of names, compares each name to column A in a sheet, and returns with a row matched value in column B. (Like the vLookup command in sheets)
The setup
var ss = SpreadsheetApp.getActiveSpreadsheet();
var clientsSheet = ss.getSheetByName("Clients");
var cRow = clientsSheet.getLastRow();
var cColumn=clientsSheet.getLastColumn();
var cData=clientsSheet.getRange(1,1,cRow,cColumn).getValues(); //create array of client data
The trouble code
//put each client on their own row and add hour
for(i=0; i < client.length; ++i){
var cl = client[i]
//iterate over array of clients (column A) and hours (Column B) to find match and log the number in column B
for(j=0;j<cData.length;++j){
if (cData[j][0]==cl){
var hour = cData[j][1];
}
}
//return the matched values
Logger.log(cl+" - "+hour);
}
The var 'client' is an array that was split from a list of names in a single cell that are separated by commas (see whole code below)
At the moment it works great except that it misses the last element in the array.
for example:
if I have a sheet with two columns and three rows like so:
A 1
B 2
C 3
I would get back
A-1
B-2
C-
It is missing that last piece on the last element - it should be
A-1
B-2
C-3
I am stumped, and I know that it must be some simple little thing.
Any help would be amazing
Thanks!
The Code:
function logClients()
/*
Take data from a google form check box submissions. Check box submissions put all checked answers into a single cell separated by a comma. The function first takes the most recently submitted row, removes unneeded spaces, and splits each element into its own part of an array.
Then, the function compares each clients name in the array to a sheet with other info, such as the default number of hours we meet. It takes the clients name, the date of submission, and the hours, and logs them on a new row in two different sheets, the Hours sheet and the Trans Log sheet.
*/
var ss = SpreadsheetApp.getActiveSpreadsheet();
var logSheet = ss.getSheetByName("Log"); //Raw data from the Google form
var hourSheet = ss.getSheetByName("Hours"); //logged data for my records, separated into individual clients
var transLog = ss.getSheetByName("Trans Log"); // logged data minus "other" catagory
var clientsSheet = ss.getSheetByName("Clients"); //sheet containing all clients names and the typical hours we meet
var lRow = logSheet.getLastRow();
var hRow = hourSheet.getLastRow();
var tRow = transLog.getLastRow();
var cRow = clientsSheet.getLastRow();
var cColumn = clientsSheet.getLastColumn();
var cData = clientsSheet.getRange(1, 1, cRow, cColumn).getValues();
//get list of clients from cell and split it into an array
var Client = logSheet.getRange(lRow, 2).getValue().replace(", ", ","); //remove all spaces after a comma
var client = Client.split(",");
//get "other" information and do the same
var Other = logSheet.getRange(lRow, 5).getValue().replace(", ", ",");
var other = Other.split(",");
//check the date and set to today if nothing else has been entered
var dcell = logSheet.getRange(lRow, 4).getValue();
var date = new Date()
if (dcell == "") {} else if (dcell == "Yesterday") {
date = new Date(date.getTime() - 1 * (24 * 3600 * 1000));
} else {
date = dcell
}
var date = Utilities.formatDate(date, "GMT-8", "MM/dd/yy"); //format date
//put each client on their own row
for (i = 0; i < client.length; ++i) {
var cl = client[i]
var hour = logSheet.getRange(lRow, 3).getValue(); //hours
if (hour == !"") {
break;
}
for (j = 0; j < cData.length; ++j) {
if (cData[j][0] == cl) {
var hour = cData[j][1];
}
}
Logger.log(date + " - " + cl + " - " + hour);
hourSheet.appendRow([date,cl, hour]);
transLog.appendRow([date, cl, hour]);
}
//put each client on their own row
for (i = 0; i < other.length; i++) {
hourSheet.appendRow([date, other[i], getHour(client[i])]);
}
} //end of function
``
This is a code that I have been working on to teach myself Java and Apps-script
Yup, simple mistake.
Not all of the spaces before each name were being removed from the array, so the if statement would skip right over them because they were not a true match

how to insert an item in Combobox(dropdown) with value in winforms

This is a silly question.
but I searched a lot in Google but not found any good solution for this.
If we write
ddlReleaseMngr.Items.Insert(0, "Naibedya Kar");
This will insert a item in the dropdown but the value of the item is ZERO.
I want to inset an item in the dropdown with some value.
if I do
ddlBA.DataSource = tblBA;
ddlBA.DisplayMember = "Name";
ddlBA.ValueMember = "UserID";
by using above query we can set value to each item.
Like this I want to set a value for item.
Please help me
Thanks in advance
The value of the item is not ZERO. The index is 0.
You can get the VALUE of the checkbox item by using:
ddlReleaseMngr.SelectedItem.ToString();
Which would give you "Naibedya Kar".
You can create an integer variable and assign it a value using the selected item like so:
int myvar = 0;
if(ddlReleaseMngr.SelectedIndex == 0)
{
myvar = 5; //or whatever value you would like
}
or use a switch statement:
switch (ddlReleaseMngr.SelectedIndex)
{
case 0:
Console.WriteLine("Case 1: " + ddlReleaseMngr.SelectedItem.ToString());
myvar = 0;//whatever value you would like
break;
case 1:
Console.WriteLine("Case 2");
break;
default:
Console.WriteLine("Default case");
break;
}
Why not Items.Add instead of Items.Insert like:
ddlReleaseMngr.Items.Add("Naibedya Kar");

Resources