Using 'Filter by Column Value' and multi column filtering using a java vector - xPages - vector

I have an xPage which I have built with 3 combo boxes and 1 view control. I would like to use the 'Filter by column value' option within the view control to provide the options to filter the values, allowing the user to display any combination of the combo boxes. e.g. Only comboBox1, or comboBox1 and comboBox2, or comboBox3 only, or comboBox1 and comboBox2 and comboBox3.
I used the example in the 'xPages Demonstration Application' (http://www-10.lotus.com/ldd/ddwiki.nsf/dx/xpagesdemoapp.htm or http://xpagesblog.com/XPagesHome.nsf/Entry.xsp?documentId=AAC8E26599256FDC852578CB0066CC13) to do the multi-column filtering using a vector of non-categorized columns.
So, I have come across what appears to be a fairly major issue whereby the data needs to be sorted by date. Date is not one of the filters, but it needs to be the first column in order for the data to be sorted correctly. So my first column is a string, YYYYMMDD, to ensure the data is sorted correctly. I tried to use the sort option within the view control and that does not appear to work with the column filtering implemented in this manner.
So, as Date one of the criteria I am filtering by, I have passed that as an empty string - using the thought process that an empty string will select all (as in the url examples above).
The code I have used to do the filtering is:
var vtr:java.util.Vector = new java.util.Vector();
var t1 = sessionScope.Email;
var t2 = sessionScope.Own;
var t3 = sessionScope.Module;
vtr.addElement("");
#If(sessionScope.Own=="My calls",vtr.addElement(t1),vtr.addElement(""));
#If(sessionScope.Own=="My calls",vtr.addElement(""),vtr.addElement(t2));
#If(sessionScope.Status=="Open",vtr.addElement("Open"),vtr.addElement(""));
#If(sessionScope.Module=="All",vtr.addElement(""),vtr.addElement(t3));
return vtr;
What I have found is that not all data is being returned. I thought this might be due to the date field. So I removed it (changing the view and removing the first add element), and yet I still find that not all data is being returned. I suspect that this might be due to the empty strings being passed, or, that this does not actually work the way I had hoped.
Does anyone know if I can get this working the way I want it to, and if not, do you have any suggestion on how I can go about this?

Date is not needed as the first sortable column in the view. The first column does need to be sorted for the lookup to work just like the Notes view needs to be sorted for #DbColumn and #DbLookup to work. XPages uses the same underlining architecture. This example - http://dev.openntf.org/demos/demoapp.nsf/viewFilteringVector.xsp - works without the data being sorted by Date.
My guess as to why your example isn't working is down to how your Notes view sorted. Try creating a new view with column 1 (email) ascending sort, column 2 (own) ascending sort, and column 3 (module) again ascending sort. You should be able to get vector filtering working in this situation.
If all that doesn't work for you, you might consider multi-layer category filtering (new to 853). This filtering type in XPages is related to how categoryFilter works but allow you to filter a view by the sub-category (or sub-categories) too. This technique might suit your scenario better. Hope this helps.

Related

Presenting relational data as columns in table

Trying to figure out how to present/edit related data in a table, could really use a push in the right direction!
Broadly, this is looking at subscription data - I want to see how much each client is paying per month. If a client gets upsold halfway through the year - I need the data to reflect that.
So, I have a database of clients, and a database of months, with a Many-One relationship. I also have a "monthlyallocation" database related to both, so I can say Client A has $40 for Jun 2017, for eg. I'm looking to present the data like so in a table, and make the numbers editable:
Jun Jul Aug Sep
Client A 20 20 22 20
Client B 15 20 15 15
Client C null 11 11 12
So I can filter out months (columns), and I can filter out Clients (rows). Any help appreciated!
************EDIT - So I've managed to get partway there.
First, the datasource for the table needs to Client - since I want my table rows to be grouped by client.
Next, the page has a custom property "datenum" which I can change to help filter out columns.
Each column header now becomes #datasources.Months.items..MonthName[#properties.datenum + Insert Column Number Here]. As the datenum changes, the columns display different names. Great.
The last piece of the puzzle though - the values shown IN the table need to filter by the column header name. I can't do the "[#properties.datenum + Insert Column Number Here]" trick here, in case I'm missing a value.. If I did that, I could accidentally get the Sep value under Aug, for eg.
Really hope that makes sense - my first instinct is to make a script that takes the rows datasource, and the "MonthName[#properties.datenum + Insert Column Number Here]", and return the correct value, but maybe I'm just misunderstanding how binding works and there's a simpler way to do this.
For filtering out clients, check out this tutorial: https://developers.google.com/appmaker/tutorials/establish-relations/
It shows how to create a data query with a filter, which is basically what you need for that.
Filtering out columns is a bit tougher, at least I haven't figured an easy way to do it yet.
DISCLAIMER: Out there, there are probably solutions that are much better than this one. This is just to give you a thought.
I've solved this problem by using a custom property List named 'isVisible' for the page the table is in. Then I've added a multi select named 'ColumnPicker' into the page.
After each change in the ColumnPicker, I sync the changes with isVisible. Each column's visibility (for both header and data parts) are connected to:
#widget.root.properties.isVisible[#widget.childIndex]
So using the widget's index, I relate it to the isVisible list.
Here's the sync function I'm using:
function syncColumnPickerValuesWithIsVisible(columnPickerWidget, newValues) {
setIsVisibleAllSameValue(columnPickerWidget, false);
newValues.forEach(function(element) {
columnPickerWidget.root.properties.isVisible[element] = true;
});
}
So in the sync, I first set all isVisible values to false. Then I use the newValues array that the multi select provides to set the correct isVisible elements as true.
=> Items selected from the multi select are shown as columns in the table.

Is it possible to filter the list of fields when outputting a Full Dataset?

I have a DataTable that I'm passing to a FlexCel report. It contains a variable number of columns, so I'm using the Full Dataset feature (e.g. <#table_name.*>).
However, only a subset of the fields are dynamically generated (I have a variable number of attachments). The column name for each attachment field starts with a common word (e.g. "Attachment0", "Attachment1", etc).
What I would like to do is output the known finite set of fields and then the variable number of attachments. It would be nice if I could write something like <#table_name.Attachment*> (and <#table_name.Attachment**>). Is there any way in FlexCel Reports I can achieve the same result?
A side benefit to such a solution means that I could keep the formatting for the known/finite set of fields.
Update
I added place holder columns to the document, each with a <#delete column> tag, so that the un-wanted columns/data are removed.
Although this works, it's not ideal. For example, if I want to see how the columns fit in the page width (in print preview), then I need to hide the columns. Then I have to remember to un-hide them again, so other developers can see/understand my handy work.
It would be much more straight forward if I could filter the fields before they're output to the document.
I realised there's an alternate way around this problem. I broke up the data into two sets of data - <#table_name.*> and <#table_name_attachments.*>.
The fixed set of fields are in the first table and the variable set of fields is in the second table (all the "Attachment*" fields). When the report is run, I place them next to each other (in the same order) in the same worksheet. This means I have two table ranges - "_table_name_" and "_table_name_attachments_" on the one sheet.
Now I'm able to run my print preview without hiding/re-showing the columns-to-be-deleted. I've also eliminated human error - it was all to easy to accidentally set the wrong number of padded/delete columns.

"Calculated columns cannot contain volatile functions like Today and Me" error message on Sharepoint

I try to add a new calculated column to sharepoint list that will show elapsed day. I enter name and write a formula like;
=ABS(ROUND(Today-Created;0))
The data type returned from this formula is: Single line of text
When I want to save I get an error like
Calculated columns cannot contain volatile functions like Today and
Me.
Calculated Column Values Only Recalculate As Needed
The values in SharePoint columns--even in calculated columns--are stored in SharePoint's underlying SQL Server database.
The calculations in calculated columns are not performed upon page load; rather, they are recalculated only whenever an item is changed (in which case the formula is recalculated just for that specific item), or whenever the column formula is changed (in which case the formula is recalculated for all items).
(As a side note, this is the reason why in SharePoint 2010 you cannot create or change a calculated column on a list that has more than the list view threshold of 5000 items; it would require a mass update of values in all those items, which could impact database performance.)
Thus, in order for calculated columns to accurately store "volatile" values like "Me" and "Today", SharePoint would need to somehow constantly recalculate those column values and continuously update the column values in the database. This simply isn't possible.
Alternatives to Calculated Columns
I suggest taking a different approach entirely instead of using a calculated column for this purpose.
Conditional Formatting: You can apply conditional formatting to highlight records that meet certain criteria. This can be done using SharePoint Designer or HTML/JavaScript.
Filtered List views: Since views of lists are queried and generated in real time, you can use volatile values in list view filters. You can set up a list view web part that only shows items where Created is equal to [Today]. Since you can place multiple list view web parts on one page, you could have one section for today's items, and another web part for all the other items, giving you a visual separation.
A workflow, timer job, or scheduled task: You can use a repeating process to set the value of a normal (non-calculated) column on a daily basis. You need to be careful with this approach to ensure good performance; you wouldn't want it to query for and update every item in the list if the list has surpassed the list view threshold, for example.
I found some conversations about this issue. Many people suggest to creating a new Date Time column, visible is false, default value is Today's Date and it will be named as Today. Then we can use this column in our formulas.
I tried this suggestion and yes error is gone and formula is accepted but calculated columns' values are wrong. I setted column Today is visible and checked, it was empty. Default value Today's Date was not working. When I looking for a solution for this issue I deleted column Today carelessly. Then I realized calculated columns' values are right.
Finally; I don't know what is trick but before using Today keyword in your formulas if you create a column named as Today and after your formula saving if you delete Today column, it is working.
UPDATE
After #Thriggle's answer I realized this approach doesn't work like a charm. Yes, formula doesn't cause an error when calculated column saving but it works correctly only first time, in the next day the calculated column shows old values, because its values are static as Thriggle explained.

Filtering data and Display Heading based on filters

being a newbie to SSRS, I am trying to figure out the following:
say for instance I have a dataset which does a :
SELECT [cols...] from [some view]
I want to be able to further filter this based on parameters given from an ASP.NET site (I am using the AJAX control toolkit for the report viewer). There could be x amount of parameters and potentially can be filtered on 1 or more columns.
First question is, how would I filter the dataset and pass along the parameters along with which field the filter should apply to? I may have [col1] and I want to filter it with x values.
Second question Is, I want to be able to group the results per page based upon a column. So for each grouped result set, I want them to be displayed per page (per group per page).
Then on the headers of the page, I want it to display what the page grouping is. How would I do this?
In terms of what have I tried - nothing as I DO NOT KNOW HOW, it is why I am asking the question here to see what the experts (you) can suggest and guide me.
thank you!
To do this you can create Parameters in SSRS, they do not need to be in your query or anything. Then, go to your tablix and click either ROW or column depending on the filter type and set it show/hide visibility. For example I have a report that has personal information, so i have true/false parameter that hides/shows those columns, similar I have one that hides/shows any row with a -1 for the total paid.

AdvancedDataGrid (grouping) quick jump to row

I have a problem with the AdvancedDataGrid widget. When the dataProvider is an ArrayCollection (of arrays), the nth array (within the collection) is also the nth row within the grid, and I can jump and display the i-th row by scripting
adg.selectedIndex = i;
adg.scrollToIndex(i);
now, when I add a Grouping, the dataProvider ends up being a GroupingCollection2, and now the index in the dataprovider's source does not correspond to the index in the adg anymore (which is understandable, because it's being grouped).
How can I select and display a row in grouped data efficiently? Currently, I have to traverse the adg and compare each found item with its data attributes in order to find the correct index of the row within the adg, and jump to it like above. This process is very slow. Any thoughts?
edited later:
We already used a caching object as Shaun suggests, but it still didn't compensate for the search times. In order to fully construct a sorting of a list of things (which this problem equates to, as the list is completely reordered by the grouping), you always have to know the entire set. In the end we didn't solve that problem. The project is over now. I will accept Shaun's answer if no one knows a better way in three days.
Depending on what values your comparing against you can store the objects in a dictionary with the lookup using the property/properties that would be searched for, this way you have a constant time look-up for the object (no need to look at every single item). Say for example your using a property called id on an object then you can create an AS object like
var idLookup:Object = {};
for(myObject in objects)
idLookup[myObject.id] = myObject;
//Say you want multiple properties
//idLookup[myObject.id]={};
//idLookup[myObject.id][myObject.otherProp] = myObject;
now say the user types in an id you go into the idLookup object at that id property and retrieve the object:
var myObject:Object = idLookup[userInput.text];
myAdg.expandItem(myObject, true);
now when you want to get an object by id you can just do
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/controls/AdvancedDataGrid.html#expandItem()
I haven't done any thorough testing of this directly, but use a similar concept for doing quick look-ups for advanced filtering. Let me know if this helps at all or is going in the wrong direction. Also if you could clarify a bit more in terms of what types/number of values you need to lookup and if there's the possibility for multiple matches etc. I may be able to provide a better answer.
Good luck,
Shaun

Resources