Sharepoint 2010 adding multiple values to a Managed Metadata column - sharepoint

Having a problem with the code below only adds the latest value in the TestTaxonomyControl.Text to the metadata column. ( multiple values is turned on )
TaxonomyFieldValueCollection values = new TaxonomyFieldValueCollection(String.Empty);
values.PopulateFromLabelGuidPairs(TestTaxonomyControl.Text);
TaxonomyField entKeyword = (TaxonomyField)item.Fields["Metadata"];
foreach (TaxonomyFieldValue value in values)
{
TaxonomyFieldValue term = new TaxonomyFieldValue("1;#" + value.Label + "|" + value.TermGuid);
entKeyword.SetFieldValue(item, term);
}
item.Update();

I'd say you only need something like:
TaxonomyFieldValueCollection values = new TaxonomyFieldValueCollection(String.Empty);
values.PopulateFromLabelGuidPairs(TestTaxonomyControl.Text);
item["Metadata"] = values;
item.Update();

Related

Value does not fall within the expected range - Exception for SharePoint Lookup 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.

CSV file transposed to ILookup

A vendor is providing us a csv file nightly. We need to take that csv, pull out some of the columns, then import them into our in-house application. The csv, as we receive it, looks a bit like this:
StudentId, GradYear, 2014 Thing1, 2014 Thing2, 2015 Thing1, 2015 Thing2
and so on, adding columns seemingly to perpetuity.
When I first saw this csv, my first inclination was to transpose it to 2 columns: thus:
StudentId, 123456
GradYear, 2016
2014 Thing1, overdue
2015 Thing1, completed
My inclination is use csvHelper to read this file in, and transpose it by constructing an ILookup. So I would have a Lookup that would look like:
var theLookup = ILookup<string, KeyValuePair<string, string>>
The key being the StudentId, and the KeyValuePair being the column header : cell value.
I can almost work it out using a Dictionary, with a counter for the dictionary key, but I can't make the leap to Lookup with the StudentId as the key.
Here is how I'm constructing the Dictionary:
Dictionary<int, List<KeyValuePair<string, string>>> vendorDictionary = new Dictionary<int, List<KeyValuePair<string, string>>>();
using (var fileReader = File.OpenText(sourcePath))
using (var reader = new CsvHelper.CsvReader(fileReader))
{
while (reader.Read())
{
var dynamicVendor = reader.GetRecord<dynamic>() as IDictionary<string, object>;
foreach (var rec in dynamicVendor)
{
var recordDictionary = dynamicVendor.ToDictionary(k => k.Key, k => k.Value.ToString());
vendorDictionary.Add(counter, recordDictionary.ToList());
++counter;
}
}
I can view the records with the following code. Do I need to do a version of this foreach to make into a Lookup? Or, should I just use a Dictionary with some "if it's 'StudentId' then make it the key?
foreach (var rec in vendorDictionary)
{
Console.WriteLine("Vendor Dictionary record # " + rec.Key + " values are:");
foreach (var value in rec.Value)
{
Console.WriteLine("Key: '" + value.Key + "' Value: '" + value.Value + "'");
}
}
Mostly I want to know if I'm even on the right track here.
When I have whatever object of vendor data I end up with, I will need to loop through it, compare student with our student record and make decisions about updating records in our app.

Save lookup value to SharePoint 2010

I've figured out how to add a record into a library. The only thing I am trying to figure out is how (or maybe where) do I save a user's selection from a lookup list?
In the below code snippet, I am saving a new list item. It saves without error, but the fields "AwardType" and "AwardReason" are lookup fields and, although I do not get an error, nothing gets saved to them. How do I save to a lookup field selection from a user?
using (SPSite site = new SPSite(SPContext.Current.Web.Url))
{
using (SPWeb web = site.OpenWeb())
{
using (FileStream fs = (new FileInfo(fileUpload.PostedFile.FileName)).OpenRead())
{
SPList list = web.Lists["Awards"];
Hashtable ht = new Hashtable();
ht.Add("wfRecipientName", txtRecipientName.Text);
ht.Add("Office", txtOrganization.Value);
ht.Add("AwardType", ddAwardTypes.SelectedValue);
ht.Add("AwardReason", ddAwardReasons.SelectedValue);
SPFile destfile = list.RootFolder.Files.Add(fileUpload.FileName, fs, ht, false);
}
}
}
Storing a lookup's value is done with SPFieldLookupValue(ID, Value).
You need to store the object returned by this method in a list item field, not a property via a hash table. In my example below, Awards list is document library and AwardType is a field of type lookup.
SPList list = web.Lists["Awards"];
Hashtable ht = new Hashtable();
ht.Add("Office", "Chicago"); // standard property
SPFile file = list.RootFolder.Files.Add(System.IO.Path.GetFileName(FileUpload1.PostedFile.FileName), fs, ht, true);
SPListItem item = file.Item; // get the item for the just-added file.
// assign the lookup column using SPFieldLookupValue
item["AwardType"] = new SPFieldLookupValue(
Int32.Parse(DropDownList1.SelectedValue),
DropDownList1.Text);
item.Update(); // to save the lookup column.
Interestingly, the line
SPListItem item = file.Item; // get the item for the just-added file.
is key.
I had trouble when I used the code below - the lookup did not update consistently!?
file.Item["AwardType"] = new SPFieldLookupValue(
Int32.Parse(DropDownList1.SelectedValue),
DropDownList1.Text);
You must add the SPFieldLookUpValue as string to the HashTable, not the value of the Lookup.
Properties stored on HashTable other than int, string, date will not be parsed on Document creation.
SPFieldLookupValue v = new SPFieldLookupValue(item["lookUpField"].ToString());
Hashtable documentProperties = new Hashtable();
documentProperties.Add("key", v.ToString());
SPFile file = docLib.RootFolder.Files.Add("fileName", memoryStream, documentProperties, true);
The same can be done with complex objects as SPUser.
SPFieldUserValue userValue = new SPFieldUserValue(web, web.CurrentUser.ID, web.CurrentUser.LoginName);
documentProperties.Add("SPuSER", userValue.ToString());

Adding a mock Datatable in Unit Testing

I am Unit Testing one of my functions. Here is my code:
public void TestLabels()
{
//Step 1: Creating a mock table with columns exactly like in the real table.
DataTable table = new DataTable();
DataRow mydatarow;
mydatarow = table.NewRow();
//Step 2: Adding the row as same as the Real Data!
mydatarow["Name"] = "Test";
mydatarow["Address"] = "00000 ST.";
mydatarow["ZipCode"] = "77665";
mydatarow["Tracking#"] = "";
table.Rows.Add(mydatarow);
foreach (DataColumn column in table.Columns)
Console.WriteLine(column.ColumnName);
//Step 3: Call method we are testing.
var updateTable = IceTechUPSClient.Instance.CreateLabels(table);
foreach (DataRow row in updateTable.Rows)
{
var trackingNumber = row["Tracking#"].ToString();
Assert.IsFalse(String.IsNullOrWhiteSpace(trackingNumber), "Expecting tracking number generated for every row!");
Assert.IsTrue(File.Exists(trackingNumber + ".gif"));
}
}
Now I am getting an error: Column 'Name' does not belong to table. As you can see I have specified column name "Name" here and also added that particular row. Then why I am getting this error? Any help?
Thanks!
You haven't set up your columns (unless you've missed out some code in your example).
You need to create the columns with the required names before you can access them like this:
var columnSpec = new DataColumn
{
DataType = typeof(string),
ColumnName = "Name"
};
this.table.Columns.Add(columnSpec);
When you read data from the database if you've set AutoGenerateColumns to true (the default) you don't need to do this explicitly as it's done for you behind the scenes.

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.

Resources