I am trying to convert a SharePoint SPListItem into a ListItem to put into a Drop Down List. My problem is that the data in the SharePoint list is stored like this:
;#Daylight;#
;#Design;#Employee Engagement;#
But Obviously this does not work for me. I need to remove the ;# symbols which should be as simple as String.Replace but where I am running into some problems is what should I do for list items that contain multiple selections (my second example above). The ultimate goal here is to generate a drop down list (that does not contain duplicates) of all the items in the SharePoint List. Any ideas?
using (SPSite site = new SPSite(SPContext.Current.Web.Url.ToString()))
using (SPWeb oWebsiteRoot = site.OpenWeb())
{
SPList oList = oWebsiteRoot.Lists["WplData"];
SPListItemCollection items = null;
SPQuery query = new SPQuery();
query.Query = "<Where><IsNotNull><FieldRef Name='Topic' /></IsNotNull>" +
"</Where><OrderBy><FieldRef Name='Topic' Ascending='True' /></OrderBy>";
items = oList.GetItems(query);
DataTable tmpTable = new System.Data.DataTable();
tmpTable = items.GetDataTable();
DataView view = new DataView(tmpTable);
String[] columns = { "Topic" };
DataTable table = view.ToTable(true, columns);
foreach (DataRow row in table.Rows)
{
foreach (var item in row.ItemArray)
{
ListItem listItem = new ListItem();
listItem.Value = item.ToString();
listItem.Text = item.ToString();
TopicDropDownList.Items.Add(listItem);
}
}
}
Instead of a DataTable, try SPFieldLookupValueCollection:
SPList oList = oWebsiteRoot.Lists["WplData"];
SPListItemCollection items = null;
SPQuery query = new SPQuery();
query.Query = "<Where><IsNotNull><FieldRef Name='Topic' /></IsNotNull>" +
"</Where><OrderBy><FieldRef Name='Topic' Ascending='True' /></OrderBy>";
items = oList.GetItems(query);
foreach (SPListItem item in items)
{
SPFieldLookupValueCollection values =
new SPFieldLookupValueCollection(item["Topic"].ToString());
foreach (SPFieldLookupValue value in values)
{
ListItem listItem = new ListItem();
listItem.Value = value.LookupId.ToString();
listItem.Text = value.LookupValue;
TopicDropDownList.Items.Add(listItem);
}
}
Note, since you specified SharePoint 2007, I am avoiding the use of LINQ because that requires the .NET Framework 3.5. Also, as long as each list item contains a distinct set of topics, you will be fine. But if topics can be repeated among list items, you will want to modify this code so that TopicDropDownList contains a distinct set of topics.
LINQ it, something like (psuedocode)
...
var ddlItems = (from i in items
select i["Topic"]).Distinct();
TopicDropDownList.Items.AddRange(ddlItems);
...
If Topic is a multi-choice field you can split the field value by ;#:
var listItems = items.Cast<SPListItem>()
.SelectMany(i => Convert.ToString(i["Topic"]).Split(";#", StringSplitOptions.RemoveEmptyEntries))
.Distinct();
TopicDropDownList.Items.AddRange(listItems);
You can directly operate on the SPListItemCollection returned by oList.GetItems(query). You do not need to convert it in a DataTable.
You might considering including the Topic field as ViewField in your query.
If you don't want to split the field value manually, you could use the SPFieldMultiChoiceValue class. Unfortunately there is no handy way to access the choices in this class. There is only a count and an indexer so you have to use a for-loop.
Related
I am trying to get a list of items from a specific view. Below is the code
Microsoft.SharePoint.Client.List _lists = context.Web.Lists.GetByTitle("Invoice Register");
context.Load(_lists);
context.ExecuteQuery();
int listCount = _lists.ItemCount; // i get 49000+ count here
View _listsView = _lists.Views.GetByTitle("IT Testing");
context.Load(_listsView);
context.ExecuteQuery();
CamlQuery _query = new CamlQuery();
_query.ViewXml = _listsView.ViewQuery;
Microsoft.SharePoint.Client.ListItemCollection items = _lists.GetItems(_query);
context.Load(items);
context.ExecuteQuery();
int _viewCount = items.Count; // I get nothing here.
The error I get is The attempted operation is prohibited because it exceeds the list view threshold enforced by the administrator
I have created indexes already
I have set the limit for "IT Testing" to 5000 as seen here.
If someone can guide, it would be helpful. I have gone through all the links I could.
Regards
#Ather Siddiqui,
there is no direct way to get items under a view as the view only has query schema and does not have any items. The caml query may get the same items that are under the view, but it will trigger the list view threshold.
#user2250152 has provided a good method, it's possible to get over 5000 items through Pagination. If you want to use the view query, you could change the query as below:
List tList = context.Web.Lists.GetByTitle("My test list");
CamlQuery camlQuery = new CamlQuery
{
ViewXml = #"<View><Query><Where><Gt><FieldRef Name='ID' /><Value Type='Counter'>20</Value></Gt></Where></Query><OrderBy><FieldRef Name ='FileLeafRef' /></OrderBy><RowLimit>4990</RowLimit></View>" // your view query
};
var itemColl = new List<ListItem>();
do
{
ListItemCollection listItemCollection = tList.GetItems(camlQuery);
context.Load(listItemCollection);
context.ExecuteQuery();
//
itemColl.AddRange(listItemCollection);
camlQuery.ListItemCollectionPosition = listItemCollection.ListItemCollectionPosition;
} while (itemColl.Count < 999); //view row limit
Console.WriteLine(itemColl);
I'm using this code to load a lot of items.
var itemsPerPage = 100;
var query = CamlQuery.CreateAllItemsQuery(itemsPerPage);
var loadMoreItems = false;
do
{
var items = list.GetItems(query);
ctx.Load(items);
ctx.ExecuteQuery();
loadMoreItems = items.Count == itemsPerPage;
query.ListItemCollectionPosition = items.ListItemCollectionPosition;
}
while (loadMoreItems);
It's based on this
CalmQuery.CreateAllItemsQuery
I am creating a sample program to check ListItem existence at Sharepoint list.
My SharePoint list has one of column (field) named 'Title' or it can be any other name with text type.
I Know that when we create a list at SharePoint for each item in the list a "ID" field is assigned by SharePoint list item itself.
I am creating my sample application in C# using Microsoft.SharePoint.Client and Microsoft.SharePoint.Client.Runtime dlls.
PROBLEM: I want to get a specific item in the list on the basis of the value of 'Title' column using CAML query.
My List may contains thousands of items,
Using CAML Query :
"<View><Query><Where><Leq>" +
"<FieldRef Name='ID'/><Value Type='Number'>100</Value>" +
"</Leq></Where></Query><RowLimit>7000</RowLimit></View>"
I am successfully retrieving ListItemCollection and throw that I can get ListItem. But its very time consuming and inefficient way, to traverse whole list to get particular item.
Although it is possible to get a specific item in list through the ID field using CAML query, but as i don't know what is the ID of the Item, therefore i want to fetch it through my "Title" field,
for this i tried the following CAML Query
`
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View><Query><Where><eq>" +
"<FieldRef Name='TITLE'/><Value Type='TEXT'>2</Value>" +
"</eq></Where></Query></View>";`
but I get the following exceptions when I run the code
1. Value does not fall within the expected range. this exception is generated when I try to fetch Item through the 'Title' instead of 'ID' field, in the FieldRef Name parameter.
2. One or more field types are not installed properly when i created a coloumn manually in the list, and passed it in the FieldRef Name parameter
My code snippet is as follows
class sharepoint1
{
ClientContext context = null;
string OBJECTMETATADTA_ID = "Title";
private class Configuration
{
public static string ServiceSiteUrl = "";
public static string ServiceUserName = "";
public static string ServicePassword = "";
}
private ListItemCollection getListItemCollectionFromSP(String listName)
{
Web oWebsite = context.Web;
ListCollection collList = oWebsite.Lists;
List oList = collList.GetByTitle(listName);
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = "<View><Query><Where><eq>" +
"<FieldRef Name='Title'/><Value Type='Text'>abc</Value>" +
"</eq></Where></Query></View>";
ListItemCollection collListItem = oList.GetItems(camlQuery);
context.Load(collListItem,
items => items.IncludeWithDefaultProperties(
item => item.DisplayName));
context.ExecuteQuery();
return collListItem;
}
ListItem checkItem(string listname, string fileName)
{
ListItem result = null;
ListItemCollection collListItem =
getListItemCollectionFromSP(listname);
string itemName = fileName.Substring(0, 3);
foreach (ListItem oListItem in collListItem)
{
if (oListItem[OBJECTMETATADTA_ID].Equals(itemName))
{
{
// my business logic;
}
}
}
context.Dispose();
return result;
}
}
It would be great if I get some help on this Issue from any person who knowns about this.
Did you try with 'Eq' instead of 'eq' in your query? CAML query is case sensitive
I need to create a view for all the lists. The view has to show the fields that are mandatory (is different in every list).
It all goes wrong when the second list is retrieved. The first for-each gives the following error message:
Collection was modified; enumeration operation may not execute
I really don't know why I get this bug.
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb myWeb = SPContext.Current.Web;
SPListCollection myLists = myWeb.GetListsOfType(SPBaseType.DocumentLibrary);
StringCollection viewFields = new StringCollection();
String viewName = "Mandatory fields view";
String query = "<OrderBy><FieldRef Name='Modified'/></OrderBy><Where><Eq><FieldRef Name='Author'/><Value Type='Integer'><UserID Type='Integer' /></Value></Eq></Where>";
foreach (SPList list in myLists)
{
foreach (SPField field in list.Fields)
{
if (field.Required)
{
viewFields.Add(field.ToString());
}
}
list.Views.Add(viewName, viewFields, query, Int32.MaxValue, true, false);
viewFields.Clear();
}
}
Or you could just use a for loop instead of a foreach:
for(int i = 0; i< myLists.Count; i++){
SPList list = myLists[i];
//etc..
}
Try changing foreach (SPList list in myLists) to foreach (SPList list in myLists.ToList()). This will copy the values of myLists to a separate list that can not be modified during each foreach loop.
I have a function which searches some articles in the Sitecore content items and give me the value. So far I have build up my indexes and it is showing in my IndexViewer. But the return of the function is 0. I looked up this link: http://sitecoregadgets.blogspot.com/2009/11/working-with-lucene-search-index-in_25.html for more information.
protected IEnumerable<Item> ShowHomePageNews(int numOfArticles, string stringofCountries)
{
List<Item> items = new List<Item>();
Sitecore.Search.Index indx = SearchManager.GetIndex("newsArticles");
using (IndexSearchContext searchContext = indx.CreateSearchContext())
{
var db = Sitecore.Context.Database;
CombinedQuery query = new CombinedQuery();
QueryBase catQuery = new FieldQuery("countries", stringofCountries); //FieldName, FieldValue.
SearchHits results = searchContext.Search(catQuery); //Searching the content items by fields.
SearchResultCollection result = results.FetchResults(0, numOfArticles);
foreach (SearchResult i in result)
{
items = result
.Where(r => !r.Title.StartsWith("*"))
.Select(r => db.GetItem(new Sitecore.Data.ItemUri(r.Url).ToDataUri()))
.ToList();
//Lucene.Net.Documents.Field url = i.Document.GetField("_url");
//Sitecore.Data.ItemUri itemUri = new Sitecore.Data.ItemUri(url.StringValue());
//Sitecore.Data.Items.Item item = Sitecore.Context.Database.GetItem(itemUri.ToDataUri());
//items.Add(item);
}
}
return items;
}
Over here the result is 0. What I am doing wrond here?
This is the snapshot of what I am seeing in my IndexViewer:
EDIT:
I am passing a "NZ" in the 'catQuery' and I am getting the result back. Because in my index viewer I am seeing the Field Name = _name, which contains NZ in it. I got this part. However, I want my every field to be indexed. I am seeing only 3 fields in my IndexViewer: _url, _group & _name.
So your countries should be tokenized by the indexer. As a multilist, they will be tokenized by GUID. Searching for a single country by GUID with your code above should work. However, if you want to search for multiple countries, where any of the passed in countries can trigger a match, you need to structure your query differently.
CombinedQuery query = new CombinedQuery();
//apply other filters here to query if need be
//and country filter by creating a new clause (combinedquery) and "ORing" within it (QueryOccurance.Should)
CombinedQuery query3 = new CombinedQuery();
//here you would actually iterate over your country list
query3.Add(new FieldQuery("countries", country1GUID), QueryOccurance.Should);
query3.Add(new FieldQuery("countries", country2GUID), QueryOccurance.Should);
query.Add(query3, QueryOccurance.Must);
I need to extract the items from a list in reverse order (from last entry to the first). I've managed to get all the items but, from the first to the last. Here is part of the code I am using:
The List is on a different site collection.
using (SPSite oSite = new SPSite("urltolist"))
{
using (SPWeb oWeb = oSite.RootWeb)
{
SPList FItem = oWeb.Lists["List"];
foreach (SPListItem item in FItem.Items)
{
//Display entries
}
}
}
You don't need to dispose of the RootWeb in this case.
using(var site = new SPSite("urltolist"))
{
var list = site.RootWeb.Lists["List"];
foreach(var li in list.Items.Cast<SPListItem>().Reverse().ToList())
{
// Display entries
}
}
Get the SPListItemCollection, then iterate through it in reverse:
var itemCollection = FItem.Items;
for(int i = itemCollection.Count - 1; i >= 0; i--)
{
var item = itemCollection[i];
//Display entries
}
If you just iterate over FItem.Items (i.e. call FItem.Items[i] repeatedly) you end up querying the list repeatedly, so don't do that.
The question you need to ask is what order the items are to begin with - the way you do it, they'll be sorted by ID (analogous to time of creation). If you want to sort them in another way, use an SPQuery with an OrderBy clause to retrieve the list items.
this can also be accomplished with a CAML Query. Do you need to return ALL items? If you can limit the query you can use the CAML node.