how to select multiple Values for a lookup column? - c#-4.0

I have a list that has a lookup column that comes from external list records.
I want to select multiple records from the external list while setting the value of this lookup column ??
So how to select multiple Values for a lookup column ?

What you want to use is the SPFieldLookupValueCollection object which will allow you to specify multiple lookup values for a field value. Here is some sample code that gets two values from the "Options" list (based on ID, but you could use an SPQuery) and then creates a SPFieldLookupValueCollection based on those items. It then sets the "OptionsLookup" field on the "TestList" list.
SPList optionsList = currentWeb.GetList(currentWeb.ServerRelativeUrl + "Lists/Options");
SPListItem value1 = optionsList.GetItemById(1);
SPListItem value2 = optionsList.GetItemById(2);
SPFieldLookupValueCollection optionValues = new SPFieldLookupValueCollection();
optionValues.Add(new SPFieldLookupValue(value1.ID, value1.Title));
optionValues.Add(new SPFieldLookupValue(value2.ID, value2.Title));
SPList oneList = currentWeb.GetList(currentWeb.ServerRelativeUrl + "Lists/TestList");
SPListItem addedItem = oneList.AddItem();
addedItem["Title"] = "Setting Multiple Values";
addedItem["OptionsLookup"] = optionValues;
addedItem.Update();

Related

Unable to retrieve custom list value from saved search in netsuite

Creating saved search in suitescript using nlapiSearchRecord. All the column value returns except one column which is type is custom list.
How could I get value of custom list?
To get the value I'm using code lines below.
columns[0] = new nlobjSearchColumn( 'customlist' );
var searchresults = nlapiSearchRecord( 'customrecord', null, filters, columns );
To get the column value
var listValue = searchresult.getListValue( 'customlist' );
I assume you've simplified your code in trying to be clear or confidential but there will never be fields or records with those ids.
from a search you would do:
var searchResult = searchResults[0];
searchResult.getValue(fieldId, joinName, summary)
// or in your case
searchResult.getValue('customlist'); //returns id of list value or simple result of non-list/record fields
or (and I think this is the one you want)
searchResult.getText('customlist'); // returns the display value of the list/record field.

Xpages: Keep view sort order when filtering on view

My Xpage has a dataView that points to a view which is sorted by employee name. One of the other fields in the employee view is their Location. I have a combobox in the header of the view that allows a user to subset to one location. When subsetted the correct employees appear, but the sort order is lost.
I have looked at a few answers in Stack overflow such as this and this. but cannot get them to work. I think the difference is that
I am not trying to filter on a value that is sorted.
Here is my code for the FT Search:
var tmpArray = new Array("");
var cTerms = 0;
//Geo Location Search
if(viewScope.key != null & viewScope.key != "" & viewScope.key != "All Locations" & viewScope.key != "--Select a Location--") {
tmpArray[cTerms++] = "(FIELD HR_GeoLocation = " + viewScope.key + ")";}
qstring = tmpArray.join(" AND ").trim();
viewScope.queryString = qstring; // this just displays the query
return qstring // this is what sets the search property
The view's first field is the users last name, first name, descending.
FTSearch doesn't return found documents in view's order:
The collection of documents that match the full-text query are sorted
by relevance, with highest relevance first.
Use an additional view which is categorized by Location and use Location as key in
Filter by category name (categoryFilter) or
Filter by column value
(keys/keysExactMatch)
The columns after Location-column are the same as in your current view.

How to get all possible values for SPFieldLookup

I have a lookup field in sharepoint which just references another list. I wonder how do I programatically enumerate all possible values for this field?
For example, my lookup field "Actual City" refers list "Cities" and column "Title", I have 3 cities there. In code I would like to get list of all possible values for field "Actual City", smth like (metacode, sorry):
SPFieldLookup f = myList["Actual City"];
Collection availableValues = f.GetAllPossibleValues();
//this should return collection with all cities a user might select for the field
I wrote some code to handle this for my project just the other day. Perhaps it will help.
public static List<SPFieldLookupValue> GetLookupFieldValues(SPList list, string fieldName)
{
var results = new List<SPFieldLookupValue>();
var field = list.Fields.GetField(fieldName);
if (field.Type != SPFieldType.Lookup) throw new SPException(String.Format("The field {0} is not a lookup field.", fieldName));
var lookupField = field as SPFieldLookup;
var lookupList = list.ParentWeb.Lists[Guid.Parse(lookupField.LookupList)];
var query = new SPQuery();
query.Query = String.Format("<OrderBy><FieldRef Name='{0}'/></OrderBy>", lookupField.LookupField);
foreach (SPListItem item in lookupList.GetItems(query))
{
results.Add(new SPFieldLookupValue(item.ID, item[lookupField.LookupField].ToString()));
}
return results;
}
Then to use it, your code would look something like this:
var list = SPContext.Current.Web.Lists["My List"];
var results = GetLookupFieldValues(list, "Actual City");
foreach (SPFieldLookupValue result in results)
{
var value = result.LookupValue;
var id = result.LookupId;
}
I think there is no explicit method returning what you want. But the SPFieldLookup class stores all the info you need to request this information manually: LookupField and LookupList
So you could retrieve the information by getting it form the list you lookup field uses. To make it reusable you could implement it as a Extension Method. So the next time you could really call f.GetAllPossibleValues();.
As I understand you want to query all values that are in use?
If so, you would have to query items where Actual City is not null, query would look something like:
<Where><IsNotNull><FieldRef Name='Actual City'/></IsNotNull></Where>
Then, for each queried item you would
List<SPFieldLookupValue> result = new List<SPFieldLookupValue>(returnedItemCount * 5);
foreach (SPListItem item in queriedItems) {
object lookup = item["Actual City"];
SPFieldLookupValueCollection lookupValues = new SPFIeldLookupValueCollection(
(lookup != null) ? lookup.ToString() : ""
);
foreach (SPFieldLookupValue lookupValue in lookupValues) {
if (!result.Contains(lookupValue)) {
result.Add(lookupValue);
}
}
}
Or you could use HashTable where LookupId would be string and LookupValue would be int id and then check if HashTable.ContainsKey(lookupId)... must be faster to find an integer in hashtable rather than string in list, but the resource intensive part is to probably query all items where that field contains some value and then loop...
If you want to enumerate all possible values, that means you basically want to get all the Title field values from all the items in the Cities list. I don't think there is a method like GetAllPossibleValues() in SharePoint, but you can either just list all the items in Cities and get their titles, if there's just a few, or use a CAML query if there's plenty.

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.

What is the best way to retrieve distinct / unique values using SPQuery?

I have a list that looks like:
Movie Year
----- ----
Fight Club 1999
The Matrix 1999
Pulp Fiction 1994
Using CAML and the SPQuery object I need to get a distinct list of items from the Year column which will populate a drop down control.
Searching around there doesn't appear to be a way of doing this within the CAML query. I'm wondering how people have gone about achieving this?
Another way to do this is to use DataView.ToTable-Method - its first parameter is the one that makes the list distinct.
SPList movies = SPContext.Current.Web.Lists["Movies"];
SPQuery query = new SPQuery();
query.Query = "<OrderBy><FieldRef Name='Year' /></OrderBy>";
DataTable tempTbl = movies.GetItems(query).GetDataTable();
DataView v = new DataView(tempTbl);
String[] columns = {"Year"};
DataTable tbl = v.ToTable(true, columns);
You can then proceed using the DataTable tbl.
If you want to bind the distinct results to a DataSource of for example a Repeater and retain the actual item via the ItemDataBound events' e.Item.DataItem method, the DataTable way is not going to work. Instead, and besides also when not wanting to bind it to a DataSource, you could also use Linq to define the distinct values.
// Retrieve the list. NEVER use the Web.Lists["Movies"] option as in the other examples as this will enumerate every list in your SPWeb and may cause serious performance issues
var list = SPContext.Current.Web.Lists.TryGetList("Movies");
// Make sure the list was successfully retrieved
if(list == null) return;
// Retrieve all items in the list
var items = list.GetItems();
// Filter the items in the results to only retain distinct items in an 2D array
var distinctItems = (from SPListItem item in items select item["Year"]).Distinct().ToArray()
// Bind results to the repeater
Repeater.DataSource = distinctItems;
Repeater.DataBind();
Remember that since there is no CAML support for distinct queries, each sample provided on this page will retrieve ALL items from the SPList. This may be fine for smaller lists, but for lists with thousands of listitems, this will seriously be a performance killer. Unfortunately there is no more optimized way of achieving the same.
There is no DISTINCT in CAML to populate your dropdown try using something like:
foreach (SPListItem listItem in listItems)
{
if ( null == ddlYear.Items.FindByText(listItem["Year"].ToString()) )
{
ListItem ThisItem = new ListItem();
ThisItem.Text = listItem["Year"].ToString();
ThisItem.Value = listItem["Year"].ToString();
ddlYear.Items.Add(ThisItem);
}
}
Assumes your dropdown is called ddlYear.
Can you switch from SPQuery to SPSiteDataQuery? You should be able to, without any problems.
After that, you can use standard ado.net behaviour:
SPSiteDataQuery query = new SPSiteDataQuery();
/// ... populate your query here. Make sure you add Year to the ViewFields.
DataTable table = SPContext.Current.Web.GetSiteData(query);
//create a new dataview for our table
DataView view = new DataView(table);
//and finally create a new datatable with unique values on the columns specified
DataTable tableUnique = view.ToTable(true, "Year");
After coming across post after post about how this was impossible, I've finally found a way. This has been tested in SharePoint Online. Here's a function that will get you all unique values for a column. It just requires you to pass in the list Id, View Id, internal list name, and a callback function.
function getUniqueColumnValues(listid, viewid, column, _callback){
var uniqueVals = [];
$.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_layouts/15/filter.aspx?ListId={" + listid + "}&FieldInternalName=" + column + "&ViewId={" + viewid + "}&FilterOnly=1&Filter=1",
method: "GET",
headers: { "Accept": "application/json; odata=verbose" }
}).then(function(response) {
$(response).find('OPTION').each(function(a,b){
if ($(b)[0].value) {
uniqueVals.push($(b)[0].value);
}
});
_callback(true,uniqueVals);
},function(){
_callback(false,"Error retrieving unique column values");
});
}
I was considering this problem earlier today, and the best solution I could think of uses the following algorithm (sorry, no code at the moment):
L is a list of known values (starts populated with the static Choice options when querying fill-in options, for example)
X is approximately the number of possible options
1. Create a query that excludes the items in L
1. Use the query to fetch X items from list (ordered as randomly as possible)
2. Add unique items to L
3. Repeat 1 - 3 until number of fetched items < X
This would reduce the total number of items returned significantly, at the cost of making more queries.
It doesn't much matter if X is entirely accurate, but the randomness is quite important. Essentially the first query is likely to include the most common options, so the second query will exclude these and is likely to include the next most common options and so on through the iterations.
In the best case, the first query includes all the options, then the second query will be empty. (X items retrieved in total, over 2 queries)
In the worst case (e.g. the query is ordered by the options we're looking for, and there are more than X items with each option) we'll make as many queries as there are options. Returning approximately X * X items in total.

Resources