Xpages: how to use viewEnt.getColumnValues() to retrieve all relevant value when export data? - xpages

In the Xpage, it will display officer name, officer type and department (I use sessionScope variable to do that). There is a combobox to allow the user to select
the officer type that the user wants to compare. And then a button is used for export the data.
The export data will show the comparison between the document that the selected officer type needs to read and the document that the current officer has been read.
If the officer has read document that matches the selected officer type needs to read, it will show "Document has been read", otherwise, it will
show "Document has not read"
Due this post export data from panel let me know how to export data from panel, I begin to follow the code from the post and modify some code to fulfill the user requirement.
I have two views to do the comparison:
Each officer type needs to read various documents, so there is a view to store the value, the first column is the officer type and the second column is the document
that the officer type should read. The second column is multi value field and I am able to set the Multi-value separator is New Line.
Another view the includes officer name, the related officer type and document read by the officer.(no column for multi value)
I use #DbLookup and for loop to do the comparison and here is part of code:
var officer = sessionScope.Officer;
var officerType = sessionScope.OfficerType;
var showSelectedTypeDoc = #DbLookup(#DbName(),"view1", officerType, 2);
var showUserHasReadDoc= #DbLookup(#DbName(),"view2", officer, 3);
var result = "";
while (viewEnt != null)
{
if(viewEnt.getColumnValues()[1] == officer) //get the value related to the officer in the session
{
writer.write("<tr>");
for(var s = 0; s < showSelectedTypeDoc.length;s++) //loop in view1 first
{
for(var r = 0; r < showUserHasReadDoc.length;r++)//then loop the view2
{
if(showSelectedTypeDoc[s] == showUserHasReadDoc[r])//if value matches between 2 views
{
result = "Document has been read";
}
else
{
result = "Document has not read";
}
}
}
//display the list of the document category related to specific officer type
writer.write("<td>" + viewEnt.getColumnValues()[2] + "</td>"); //Problem occurs here, it only shows the first value, the appearance depends on the loop
writer.write("<td>" + result+ "</td>"); // only display the else part
writer.write("</tr>");
}
}
Actually I suppose
viewEnt.getColumnValues()[2]
will show all the relevant values, however when I export the value, it only display the first value e.g. [first value].
The code
writer.write("<td>" + result+ "</td>");
I review the if condition, it should be fine, but it only shows the else part
I tried
showSelectedTypeDoc[s]
instead of
viewEnt.getColumnValues()[2]
it shows undefined and the appearance depends on the looping.
But if I try
showSelectedTypeDoc[0] //or showSelectedTypeDoc[1], etc
it can show the correct value and the appearance depends on the looping.
However I will not know how many values that the variable stored, so I prefer
showSelectedTypeDoc[s]
to find all relevant values but not successful.
I start to think why it only shows the first value. I revise the code and the view, I guess probably is the multi value column cause the problem. It is because In Louts Client, in the view I only click once to particular value, if the value has multi value, it will show the "tick" symbol to relevant data.
So I would like to know to how to use
viewEnt.getColumnValues()[2]
to retrieve all the data related to a specific value. Grateful for your advice please. Thank you.

getColumnsValues() returns a Java Vector. So the syntax you need to get a specific element in the Vector is getColumnValues().get(2) (which will get the third column).
Getting a column values doesn't need it to be categorised. Categorisation is only required for retrieving the entry, not the column values.
I believe when using the index that static columns (e.g. with formula set to a static value like 1 or "<tr>") are skipped.

Related

Creating a Unique ID for each record on Form Submission

I am new to Google Apps Script and have just begun to understand its working. A team member wrote out a simple simple script for some work i was doing. The script, in essence, triggered when any of a permitted set of users (could vary) submits inputs to a 'Form Responses 1' spreadsheet via a Google Form.
Basically, I have a form that users complete and then submit. Upon submission, the script checks for the active row, The code adds 1 to the number of the cell W2 (which is a 'do not edit' cell, and replaces W2 with the new number, then checks if the Unique ID field on the Active Row is null and then replaces it with a concatenated ID thats alphanumeric. ie, it prefixes a set alphabetical prefix and takes the numerical input from the cell W2 on the same form to create a new Unique ID.
The script was working perfectly until the team member left and I removed her access from the Google sheets with no change to the script at all. I've been scrambling trying to figure out what happened after that, because since access was removed, when I haven't made any changes to my code. I have searched many different places and cannot seem to find what is wrong.
If i post it on a new google sheet, it's working fine .. but not on this sheet which already has around 900 critical entries.
Any guidance is welcome. the Script is as below. HELP!
//Logger.log(SpreadsheetApp.getActiveSpreadsheet().getUrl());
//Logger.log(SpreadsheetApp.getActive().getUrl());
// Get the active sheet
var sheet = SpreadsheetApp.getActiveSheet();
// Get the active row
var row = sheet.getActiveCell().getRowIndex();
// Get the next ID value. NOTE: This cell should be set to the last record counter value
var id = sheet.getRange("X2").getValue()+1;
Logger.log("HKG0"+id);
// Check if ID column is empty
if (sheet.getRange(row, 1).getValue() == "") {
// Set new ID value
sheet.getRange(2, 24).setValue(id);
sheet.getRange(row, 1).setValue("HKG0"+id);
}
}
If your code is running off of a form submit trigger then this should work for you.
function formsubit(e) {
Logger.log(JSON.stringify(e));
var sheet = e.range.getSheet();
var id = sheet.getRange("X2").getValue() + 1;
if (sheet.getRange(e.range.rowStart, 1).getValue() == "") {
sheet.getRange(2, 24).setValue(id);
sheet.getRange(e.range.rowStart, 1).setValue("HKG0" + id);
}
}
The Logger.log will help you to learn more about the event object. You can learn more about event objects here
If you're looking for a unique id for each submission try: const id = new Date(e.values[0]).valueOf(); it's the number of milliseconds since Jan 1, 1970

Can I apply a filter dynamically to List lookup on Nintex Forms 2013?

I have a requirement wherein I need to filter the List lookup dynamically. My list has a column called category that can either contain value 'A' or 'B'. Then there is a field -'Selection' on the Content type that can either take value 'A' or 'B' or 'All' . If its 'A' I need the List lookup to take rows where category = 'A' , same goes for'B'. However if the 'Selection' is - 'All' then I need to display all the items from the list.
I was thinking of filtering the List lookup for the column - 'Category' . But the problem is as I am on a content type form , I do not have any variables that can be set dynamically.
I can not use the Filter by control mapped to 'Selection' as the it does not work when the selection is 'All' (There is no value called 'All' under category in the list).
I tried using a calculated value that operates on a formula and tried using it in Filter by specific value in List lookup , but the filter doesn't work as the list lookup loads before the calculated value on form load and hence the calculated value is always empty for the filtering.
Is there any way I can achieve this functionality.
Thanks in advance
I have thought of two solutions to this problem.
Have 3 separate list lookup controls that are laid over top of each other. Filter one by A, one by B, and let one have no filter. Then create rules to show the one with the filter you want to show, and hide the others. To save the value, you'd have to use JavaScript to copy the value from the list lookup to a hidden text box when one of the controls changes value. This solution isn't great and gets worse if you have more options...but it works.
You can use JavaScript to filter the list based off the Selection. This is a little more tricky, but you wouldn't need more lookup controls for more options. You would need only 2 list lookups no mater how many options you have for Category/Selection. You need one that shows the info that you want the user to chose from (unfiltered) and the other is from the same list, and same view, but the column should be the Category column ( you can hide this lookup with javascript). This is the code I used to get what you are describing.
//get the original html to 'reset' the dropdown after a change
var originalTitle = NWF$("#" + title).html();
//when the selection changes
NWF$("#" + selection).change(function () {
//put the original html in the dropdown to check all the options
NWF$("#" + title).html(originalTitle);
//get the new value of the selection
var choice = NWF$("#" + selection + " :checked")[0].value
//if choice is all then we are done because the original html is in the dropdown again with all the options
if (choice == "All") {
return;
}
//create the array where you will store the ids of the options that match the choice
var filteredIds = [];
//for each option in the category drop down, see if the text matches the choice (this is your filtering)
NWF$("#" + categoryDD + " option").each(function (i, n) {
//if the text of the option matches the choice add the id to the array.
if (n.text == choice) {
filteredIds.push(n.value);
}
});
//initialize string of html
var filteredTitlesHTML = ""
//for each of the ids in the list, get the option html with that id from the title dropdown and add it to the resulting HTML string
NWF$(filteredIds).each(function (i, n) {
filteredTitlesHTML += NWF$("#" + title + " option[value = '" + n + "']")[0].outerHTML
})
//put the html in the dropdown to show only filtered values
NWF$("#" + title).html(filteredTitlesHTML);
})
You can see in the picture the javascript variable names I gave the controls to use the javascript I have provided.

Highlight Duplicate list item in SharePoint 2013

I have a SharePoint 2013 (The Cloud version) custom list where 1 column is a text field where contact numbers are keyed in.
How can I get SharePoint to highlight duplicate values in that column so that every time a new item is added to the list, I'll know if the contact number has been used previously?
Ideally, here's what I'd get if I were to enter 816's details for the 2nd time:
CNO....Name.......Issue
816.....Blink........Login Problem (highlighted in red)
907.....Sink.........Access Denied
204.....Mink.........Flickering Screen
816.....Blink........Blank Screen (highlighted in red)
I've been struggling with this for awhile and would be very grateful for any advice. Thanks!
Since SharePoint 2013 uses Client Side Rendering (CSR) as a default rendering mode I would recommend the following approach. Basically the idea is to customize List View on the client side as demonstrated below.
Assume the Requests list that contains RequestNo column.
The following JavaScript template is intended for highlighting the rows when list item with RequestNo column occurs more then once:
SPClientTemplates.TemplateManager.RegisterTemplateOverrides({
OnPostRender: function(ctx) {
var rows = ctx.ListData.Row;
var counts = getItemCount(rows,'RequestNo'); //get items count
for (var i=0;i<rows.length;i++)
{
var count = counts[rows[i]["RequestNo"]];
if (count > 1)
{
var rowElementId = GenerateIIDForListItem(ctx, rows[i]);
var tr = document.getElementById(rowElementId);
tr.style.backgroundColor = "#ada";
}
}
}
});
function getItemCount(items,propertyName)
{
var result = {};
for(var i = 0; i< items.length; i++) {
var groupKey = items[i][propertyName];
result[groupKey] = result[groupKey] ? result[groupKey] + 1 : 1;
}
return result;
}
How to apply the changes
Option 1:
Below is demonstrated probably one of easiest way how to apply those changes:
Open the page in Edit mode
Add Content Editor or Script Editor web part on the page
Insert the specified JavaScript template by enclosing it using
script tag into web part
Option 2:
Save the specified JavaScript template as a file (let's name it duplicatehighlight.js) and upload it into Site Assets library
Open the page in Edit mode and find JSLink property in List View web part
Specify the value: ~sitecollection/SiteAssets/duplicatehighlight.js and save the changes.
Result
SharePoint has some basic conditional formatting for Data View Web Parts and XSLT List Views, but the conditions you can use are rather limited. You can compare a field in the current item with a value that you specify. There are no formulas to count the number of items with the same name or similar, which would be the approach to use to identify duplicates.
If you need to identify duplicates, you may want to create a view that groups by the CNO number. Grouping will also include an item count, so you can run down the list and spot groups with more than one item.

getting a list of forms that contain a specified field, is there a better method

The following code is a script object on an XPage in it I loop through an array of all the forms in a database, looking for all the forms that contain the field "ACIncludeForm". My method works but it takes 2 - 3 seconds to compute which really slows the load of the XPage. My question is - is there a better method to accomplish this. I added code to check to see if the sessionScope variable is null and only execute if needed and the second time the page loads it does so in under a second. So my method really consumes a lot of processor time.
var forms:Array = database.getForms();
var rtn = new Array;
for (i=0 ; i<forms.length; ++i){
var thisForm:NotesForm = forms[i];
var a = thisForm.getFields().indexOf("ACIncludeForm");
if (a >= 0){
if (!thisForm.isSubForm()) {
if (thisForm.getAliases()[0] == ""){
rtn.push(thisForm.getName() + "|" + thisForm.getName() );
}else{
rtn.push(thisForm.getName() + "|" + thisForm.getAliases()[0] );
}
}
}
thisForm.recycle()
}
sessionScope.put("ssAllFormNames",rtn)
One approach would be to build an index of forms by yourself. For example, create an agent (LotusScript or Java) that gets all forms and for each form, create a document with for example a field "form" containing the form name and and a field "fields" containing all field names (beware of 32K limit).
Then create a view that displays all these documents and contains the value of the "fields" field in the first column so that each value of this field creates one line in this view.
Having such a view, you can simply make a #DbLookup from your XPage.
If your forms are changed, you only need to re-run the agent to re-build your index. The #DbLookup should be pretty fast.
Place the form list in a static field of a Java class. It will stay there for a long time (maybe until http boot). In my experience applicationScope values dissappear in 15 minutes.

Creating an associative array using a while loop for select list?

I am dynamically generating a selectlist in Drupal and I want to create an associative array to populate the node ID as the value, and the title of the node as the option.
By default, it makes the value for each option the index of the select list. This is no good because the select list is dynamic, meaning the values won't be in the same order.
I used drupal_map_assoc to make the value the same as the option, but I have queries based on the value stored in this field, so if someone updates the value stored, the queries won't match.
<option value="Addison Reserve Country Club Inc.">Addison Reserve Country Club Inc.</option>
I want to replace the value with the Node ID also pulled with the query.
$sql = 'SELECT DISTINCT title, nid FROM {node} WHERE type = \'accounts\' ';
$result = db_query($sql);
while ($row = db_fetch_array($result)) {
$return[] = $row['title'];
//Trying to do something like 'Addison Reserve Country Club' => '2033' - where 2033 is the nid
}
$return = drupal_map_assoc($return);
I think you just want to do this inside the loop:
$return[$row['nid']] = $row['title'];
Based on your comment, you would also want to do an array_flip() right after the loop, but I think your comment may just have it backwards.

Resources