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.
Related
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.
I am trying to copy data from one list to other list (both lists are on different sites) along with lookup columns. But, I am getting an error for lookup field as:
Value does not fall within the expected range
Code works and data gets copied for other non-lookup fields. I tried every possible way including increasing List View Lookup Threshold and all possible ways of code but still error persists at ExecuteQuery().
Below is my code for lookup field:
if (field is FieldLookup && field.InternalName == "Country")
{
var CountryLookup = (item.FieldValues["Country"] as FieldLookupValue).LookupValue.ToString();
var CountryLookupId = (item.FieldValues["Country"] as FieldLookupValue).LookupId.ToString();
FieldLookupValue flvRDS = new FieldLookupValue();
flvRDS.LookupId = int.Parse(CountryLookupId);
itemToCreate["Country"] = flvRDS;
itemToCreate.Update();
destContext.ExecuteQuery();
}
Help is really appreciated.
I assume item is the new ListItem you're trying to create on your target list.
But you're never in fact reading any value from field here! So basically, you're trying to set your new FieldLookup.LookupId with the item["Country"].LookupId, which should logically be empty at this moment.
Here's a method I use to retrieve a lookup field ListItem from a value, feel free to modify it to fit your need, since I don't know how you want to retrieve it (SPList is an alias for Microsoft.SharePoint.Client.List).
private ListItem GetLookupItem(FieldLookup lookupField, string lookupValue)
{
string mappingField = lookupField.LookupField;
Microsoft.SharePoint.Client.List lookupList = Context.Web.Lists.GetById(new Guid(lookupField.LookupList));
Context.Load(lookupList);
Context.ExecuteQuery();
ListItemCollection libListItems = lookupList.GetItems(CamlQuery.CreateAllItemsQuery());
Context.Load(libListItems, items => items.Include(
itemlookup => itemlookup.Id,
itemlookup => itemlookup[mappingField]));
Context.ExecuteQuery();
foreach (ListItem mappedItem in libListItems)
{
object mappedField = mappedItem[mappingField];
if (mappedField != null && mappedField.ToString().Equals(lookupValue))
return mappedItem;
}
return null;
}
Now that you have the corresponding ListItem, you can set your item.LookupId with its Id:
if (field is FieldLookup && field.InternalName == "Country")
{
FieldLookupValue flvRDS = new FieldLookupValue();
flvRDS.LookupId = GetLookupItem(field as FieldLookup, "France").Id; // here, dunno how you get your country's name
itemToCreate["Country"] = flvRDS;
itemToCreate.Update();
destContext.ExecuteQuery();
}
Feel free to add some more previous code if you want an answer more suited for your specific issue.
I have the follwing objects
objItem (id,name,qty) - list<items>
objSel(selId) - list<int>
objSel.selId is the selected item id of objItem.
How to write the LINQ query to change item qty to 0 if the items are not selected and return objItem.
Your pseudo-code is quite confusing, but I suspect you want something like:
List<Item> items = ...;
List<int> selectedIds = ...;
foreach (var item in items.Where(x => !selectedIds.Contains(x.Id)))
{
item.Quantity = 0; // Property name adjusted for readability and convention
}
For more efficiently, use HashSet<int> for the selected IDs instead.
Note that it's not the LINQ query which performs the change - the query just gives the items which require changing. While you can abuse LINQ to change data, it's a bad idea to do so. The clue is in the word "query" - it's about asking a question. What you do with the answer to that question is a different matter.
Hi I have 2 external lists 'A' and 'B'. with an associated column in A, that looks up for B.
When i view/edit item in browser, it shows correct values as shown in picture below.
But when i try to access the list in code, i can access all column values, but associated column value comes null.
The code look something like this :
items = listReports.GetItems();
System.Collections.Generic.List<ReportItem> reportItems = new List<ReportItem>();
foreach (SPListItem it in items)
{
if (it != null)
{
ReportItem item = new ReportItem();
// extItem comes null
var extItem = it["ExtCol"];
// extItem comes null
DateTime date;
if (DateTime.TryParse(it["GeneratedOn"].ToString(), out date))
{
item.dateGenerated = date.Date;
}
DateTime time;
if (DateTime.TryParse(it["GeneratedOn"].ToString(), out time))
{
item.timeGenerated = time.Date;
}
reportItems.Add(item);
}
}
I'm not sure, but, "ExtCol" - is that rigth name for field in your external type? For external items sharepoint may substitute a name of external item/column in the source field name.
I have an SPListItem and I have an array of column names.
When I try to access the SPListItem values using the code below:
for(int i=0;i<arrColName.length;i++)
{
string tempValue = item[arrColName[i]].ToString();
// Works fine in case the the specific column in the list item is not null
// Argument exception - Values does not fall witing expected range
// exception in case the value //is null
}
I think that you used an SPQuery to get the list items and forgot to add the field into the viewfields property of SPQuery.
query.ViewFields = string.Format("<FieldRef Name=\"{0}\" Nullable=\"True\" />", mFieldName);
Usually when you test your program with the farm account the code will work, with normal users you get an ArgumentException.
Another problem/feature which causes ArgumentException is the new ListView Threshold. If th elist you try to access has too many items, this Exception is raised. A way to handle this is to increase the threshold with powershell for the list.
Not only check if item != null but also item["FieldName"] != null. Because if you will try to call .ToString() on null, you will get exception.
And if that field with internal name "FieldName" name does not exist, you will also get an exception. So you would probably try
SPFieldCollection fields = list.Fields;
foreach (SPListItem item in list.Items) {
if (fields.Contains("FieldName") && item["FieldName"] != null) {
string fieldValue = item["FieldName"].ToString();
}
}
I had a similar situation with custom cascade field (or column). I did it following way and it seemed to work for the custom field types.
item.Properties["Country"] = "Mexico"; // custom field
item.Properties["nCity"] = "Cancun"; // custom field
item["Document Descriptions"] = "Test document description.";
Note: I added item.Properties for the custom columns. No need to add properties for built in field type (else they don't work).
Does your array contain the internal names or the display names of the columns? If it's the latter you might try item[item.Fields[arrColName[i]].InternalName].ToStrinng(); instead.
Sharepoint Lists aren't stored as a array with a static size.
You have to use the built in sharepoint iterator to go through each element
For example:
SPList checklist = //Some initiliaztion
foreach (SPListItem item in checklist.Items){
//work
}
This will do work on each item in your SPlist
Edit:
Wrong advice, I didn't see the code until after the edit.
Maybe try a cast?
(String)item[colname]