Value does not fall within the expected range - Exception for SharePoint Lookup Field - sharepoint

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.

Related

NODE.JS: iterating over an array of objects, creating a new key if it does not exist

I am iterating over a collection of data, in my case, an array of objects. Here is a sample of 2 data points from it:
{
violation_id: '211315',
inspection_id: '268804',
violation_category: 'Garbage and Refuse',
violation_date: '2012-03-22 0:00',
violation_date_closed: '',
violation_type: 'Refuse Accumulation' },
{
violation_id: '214351',
inspection_id: '273183',
violation_category: 'Building Conditions',
violation_date: '2012-05-01 0:00',
violation_date_closed: '2012-04-17 0:00',
violation_type: 'Mold or Mildew' }
I need to create a new array of objects from this, one for each "violation_category" property. If Violation category already exists in the new array I am creating, i simply add the information to that existing category object (instead of having two "building conditions" objects for example, I would just add to an existing one).
However, I am having trouble assigning to the existing object if the current one exists (it's easy to check if it does not, but not the other way around). This is what am attempting to do currently:
if (violationCategory.uniqueCategoryName) {
violationCategory.uniqueCategoryName.violations = results[i].violation_id;
violationCategory.uniqueCategoryName.date = results[i].violation_date;
violationCategory.uniqueCategoryName.closed =
results[i].violation_date_closed;
} else {
category.violations = results[i].violation_id;
category.date = results[i].violation_date;
category.closed = results[i].violation_date_closed;
violationCategory.push(category);
}
In first condition, if this category (key) exists, I simply add to it, and in the second condition, this is where I am struggling. Any help appreciated. Thanks guys.
Just add an empty object to the key if there no object there :
violationCategory.uniqueCategoryName = violationCategory.uniqueCategoryName || {};
And only then, add the data you want to the object.
violationCategory.uniqueCategoryName.violations = results[i].violation_id;
violationCategory.uniqueCategoryName.date = results[i].violation_date;
violationCategory.uniqueCategoryName.closed =
results[i].violation_date_closed;
No condition needed.
Good luck!
Assuming that you have an input variable which is an array of objects, where the objects are looking like the objects of the question, you can generate your output like this:
var output = {};
for (var item of input) {
if (!output[item.violation_category]) output[item.violation_category] = [];
output[item.violation_category].push(item);
}
Of course you might customize it like you want.

Programmatically access external list associated column

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.

SharePoint 2010 BaseFieldControl Duplicates first item in list when in DisplayMode

I have come across a problem when using the BaseFieldControl that is driving me to distraction.
Essentinally I am trying to convert a list into a HTML table using the BaseFieldControl to render the fields.
When my table renders it writes out the correct number of lines BUT the data in each line is always the same as the first item in the list.
When I change the ControlMode property from SPControlMode.Display to SPControlMode.Edit the list renders correctly ( apart from being in Edit mode )
When my code running with ControlMode set to SPControlMode.Display I can actually get at the correct value in the BaseFieldControl.ItemFieldValue property but the wretched BaseFieldControl still insists on rendering the first item in the list!
I've also installed the web part on a SharePoint foundation and SharePoint 2010 server and I get the same results!
Finally I've googled around and found other peoples examples. Unfortunately when I try other dev's code ( unmodified ) I get exactly the same results!
This is what I'm doing. Any suggestions would be really appreciated!
foreach (string f in list.DefaultView.ViewFields)
{
TableCell c = new TableCell();
var i = item[f];
if (i != null)
{
SPField spf = item.Fields.GetField(f);
BaseFieldControl bfc = spf.FieldRenderingControl;
bfc.ControlMode = SPControlMode.Display;
bfc.Value = bfc.ItemFieldValue;
bfc.ID = Guid.NewGuid().ToString();
bfc.FieldName = spf.Title;
bfc.ListId = list.ID;
bfc.ItemId = item.ID;
SPContext context = SPContext.GetContext(this.Context, item.ID, list.ID, SPContext.Current.Web);
bfc.ItemContext = context;
bfc.RenderContext = context;
bfc.EnableViewState = true;
bfc.Visible = true;
c.Controls.Add(bfc);
}
else
{
c.Text = "NULL";
}
r.Cells.Add(c);
}
I finally fixed it. Turns out to be a problem with the SPWeb object. I had grabbed it from SPContext and passed it through as a reference to my method.
When I stopped doing that but instead created it within the method ( and created it once per item in the list ) it all worked fine.
Very strange.

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.

SPList Item get value - ArgumentException

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]

Resources