I'm doing a small application which read data from my sharepoint list, my code works when my colum is not in a content type:
List list = web.Lists.GetByTitle("myList");
CamlQuery query = CamlQuery.CreateAllItemsQuery();
ListItemCollection items = list.GetItems(query);
l_objCtx.Load(items, its => its.Include(item => item[ColumnName], item => item.Id));
l_objCtx.ExecuteQuery();
foreach (var item in items)
{
m_strGetprimary = item.Id.ToString();
return true;
}
But if I used my code with a column which in a content type, I get the following error:
Object reference not set to an instance of an object
Any idea of how can I read these items?
Thank you for your help
I add Contacts Content Type in a list and test the code snippet below:
Make sure the fields you needed to access have been add in its.Include lamda expression and the field name should be internal field name.
I am trying to compare two Sharepoint lists. I am using a C# program to add, update, and delete items, based on its ID. If the ID doesnt exist in List1, when the program is ran, I want to delete the IDs from List2. I was wondering how can I delete those items without specifying a specific number in the GetItemById function? Like in this example
using(ClientContext context = new ClientContext(siteUrl)) {
//Retrieve list items from list 1 here code here
using(ClientContext target = new ClientContext(siteUrl2)) {
foreach(ListItem oListItem2 in collListItem2) {
int exists = 0;
foreach(ListItem oListItem in collListItem) {
if (oListItem2["ID"] == oListItem["ID"]) {
exists++;
}
}
if (exists == 0) {
ListItem DeleteItem = list2.GetItemById();
DeleteItem.DeleteObject();
target.ExecuteQuery();
}
return;
}
}
}
To delete the items from the second list not in the first, just get all of the items from the first list, and filter the items in the second list based on those ids. Note you can use a hash based lookup to greatly improve performance over a linear search:
var idsFromFirstList = new HashSet<int>(
collListItem.AsEnumerable()
.Select(item => item.Id));
var itemsToDelete = collListItem2.AsEnumerable()
.Where(item => !idsFromFirstList.Contains(item.Id);
foreach(var item in itemsToDelete)
item.DeleteObject();
target.ExecuteQuery();
Note that you can basically do the exact opposite to find the items to add (create a hashset of the IDs of the items in the target into a set, find all items in the first no tin there, and then add all of those items).
To find items that match you can use a Dictionary<int, ListItem> by putting either set of items into a dictionary, with the ID as the key, and going through the other set, finding the matches. If you are going to do that, you can re-use that dictionary to check for one of the other two conditions as well, to save you one data structure:
var firstSiteItemLookup = collListItem.AsEnumerable()
.ToDictionary(item => item.Id, item => item);
foreach(var item in collListItem2)
{
ListItem match;
if(firstSiteItemLookup.TryGetValue(item.Id, out match))
UpdateItemToMatch(item, match);
else
item.DeleteObject();
}
target.ExecuteQuery();
Can you use the same code to check if an ID in collListItem has been modified then update the same ID in collListItem2? #Servy
I have a
Microsoft.SharePoint.Client.ServerException: Value does not fall
within the expected range
I cant change the List View Lookup Threshold, because it is not in a Server environment and I dont have access to it.
I would need to get the text that is displayed in the list instead of getting the hyperlink (hence the error).
This is the code I`m using:
clientContext.Load(collListItem, items => items.Include(
item => item["IT_x0020_Services"]));
clientContext.ExecuteQuery();
ArrayList itserv = new ArrayList();
foreach (ListItem oListItem in collListItem)
{
itserv.Add(oListItem["IT_x0020_Services"].ToString());
}
What am I missing?
Are you missing the CamlQuery?
I tried your code just changing "IT_x0020_Services" to "Title" on a list I have here and it worked properly for me.
ClientContext clientContext = new ClientContext("http://127.0.0.1");
var oList = clientContext.Web.Lists.GetByTitle("TestList");
CamlQuery camlQuery = new CamlQuery();
ListItemCollection collListItem = oList.GetItems(camlQuery);
clientContext.Load(
collListItem,
items => items.Include(
item => item["Title"]));
clientContext.ExecuteQuery();
ArrayList itserv = new ArrayList();
foreach (ListItem oListItem in collListItem)
{
itserv.Add(oListItem["Title"].ToString());
}
I'm working on one of my first projects. I have a listbox where I select multiple values and I would like to add each selection (selectedItem.Text) to a list of strings.
so far what I was working on is something like ..
selectedItem = new List<string>();
var value = lstpdfList.SelectedItem.Text;
for (int i = 0; i < lstpdfList.SelectedValue.Count(); i++)
{
selectedItem.Add(value);
}
I would really appreciate any advice.
Iterate each item from ListBox.Items collection
foreach (ListItem item in ListBox1.Items)
{
if (item.Selected)
{
selectedItem.Add(item.Text); // selectedImte.Add(item.Value);
}
}
There is SelectedItems property of ListBox, try to iterate throught it. For example, if there is strings in your ListBox, then your code might look like this:
selectedItem = new List<string>();
foreach (string value in lstpdfList.SelectedValues)
selectedItem.Add(value);
You can just cast them to strings:
var selectedItems = listBox1.SelectedItems
.Cast<string>()
.ToList();
If you have populated your ListBox with something other than just strings, just cast to whichever type you need, like so:
var selectedItems = listBox1.SelectedItems
.Cast<WhateverYourTypeIs>()
.Select(item => item.ToString())
.ToList();
In code how can I access a list e.g "MyList" in sharepoint,
then iterate through this list items and get the value of a particular column on that list e.g the "URL" column?
To retrieve all items from a list and iterate through each one, the best solution would be as follows (assuming that this code is run as part of a feature):
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using(SPSite site = properties.Feature.Parent as SPSite)
{
SPList list = site.RootWeb.Lists["ListName"];
SPListItemCollection items = list.Items;
foreach (SPListItem listItem in items)
{
Response.Write(SPEncode.HtmlEncode(listItem["Url"].ToString()) +"<BR>");
}
}
}
But if the list is very large, it would be better to paginate through the list items:
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using(SPSite site = properties.Feature.Parent as SPSite)
{
SPList list = site.RootWeb.Lists["ListName"];
if(items.ItemCount > 100)
{
SPQuery query = new SPQuery();
query.RowLimit = 100;
int index = 1;
do
{
SPListItemCollection items = list.GetItems(query);
foreach (SPListItem listItem in items)
{
Response.Write(SPEncode.HtmlEncode(listItem["Url"].ToString()) +"<BR>");
}
query.ListItemCollectionPosition = items.ListItemCollectionPosition;
index++;
} while (query.ListItemCollectionPosition != null);
}
else
{
SPListItemCollection items = list.Items;
foreach (SPListItem listItem in items)
{
Response.Write(SPEncode.HtmlEncode(listItem["Url"].ToString()) +"<BR>");
}
}
}
}
This is based on the Microsoft's Best Practices for SharePoint.
From this blog post:
The correct way to do it is to store the Items property return value in a SPListItemCollection variable. With this the database is only queried once and we will then iterate over the result set that is stored within the collection object. Here is the changed sample code:
SPListItemCollection items = SPContext.Current.List.Items;
for(int i=0;i<100 && i<items.Count;i++) {
SPListItem listItem = items[i];
htmlWriter.Write(listItem["Title"]);
}
You can also iterate the items directly, and if you're using a URL field you probably want to use the SPFieldUrlValue class, so you don't have to deal with the way SharePoint stores URLs:
foreach(SPListItem item in spList.Items){
SPFieldUrlValue data = item["Url"] as SPFieldUrlValue;
// now you have data.Description, data.Url
}
There are many such SPField* helper classes, and they are very useful, specially when you have multiple values.
Edit:
For some reason some people believe this way is slower, based on the evidence in the blog post of on Greg's post (even got down voted). This, however, has nothing to do with my answer: a foreach loop creates an Iterator, so it shouldn't access the database 99 more times (on the post they used a for loop to access the first 100 items).
if you are in a feature, the feature is activated at a specific scope, (e.g. Site, Web, WebApplication or Farm).
When you want to access a list from the feature, use the SPFeatureReceiver class to bind an event receiver to your feature. Then, in that class, there are overrides for when the feature activated event is triggered. that override receives a parameter of type SPFeatureReceiverProperties.
from that parameter, you can use get into a site:
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using(SPSite site = properties.Feature.Parent as SPSite) //this depends on scope of feature
{
SPList myList = site.RootWeb.Lists["MyList"];
}
}
for how the iterate that list, see the orther answers
I know this question was asked a very long time ago but I hope I am able to help someone out now :)
This is how I was able to accomplish this,
protected void Page_Load(object sender, EventArgs e)
{
// Get the current domain
var current = HttpContext.Current.Request.Url.Host;
// We need to tell the SPSite object the URL of where our List is stored.
// Make sure you have the right location placed after the 'current' variable
using (SPSite spSite = new SPSite("http://"+current+"/DirectoryForLists/Lists"))
{
// Returns the Web site that is located at the specified server-relative or site-relative URL.
using (SPWeb spWeb = spSite.OpenWeb())
{
//Get our list we created.
SPList list = spWeb.Lists["Name Of the List"];
// Create a new SPQuery object that will hold our CAML query.
SPQuery q = new SPQuery();
// CAML query.
// This allows you to controll how you receieve your data.
// Make the data ASC or DESC. Find more on MSDN.
q.Query = "<OrderBy><FieldRef Name='DESCR' Ascending='TRUE' /></OrderBy>";
// We put our list data into a SP list Item Collection.
// Notice that the CAML query is the only parameter for the GetItems() function.
SPListItemCollection items = list.GetItems(q);
// Here you can loop through your list.
foreach (SPListItem spItem in items)
{
// Your code here.
MessageBox(spItem);
// Get URL column
MessageBox(spItem["URL"]);
// Another Column
MessageBox(spItem["DateTime"]);
}
}
}
}
Below is the best option to iterate
SPList list = web.Lists[listname];
SPQuery query = new SPQuery();
query.Query = "<OrderBy><FieldRef Name='ID' /></OrderBy>";
//Scope="Recursive" retrieves items from all folders and subfolders in a list
query.ViewFields = "<FieldRef Name='" + Lists.MRPLibrary.RebateClaimed + "' /><FieldRef Name='ID'/>";
query.ViewAttributes = "Scope=\"RecursiveAll\"";
query.RowLimit = 100;
do
{
SPListItemCollection items = list.GetItems(query);
foreach (SPListItem listItem in items)
{
}
query.ListItemCollectionPosition = items.ListItemCollectionPosition;
} while (query.ListItemCollectionPosition != null);
}
Below code used to delete all bulk list items and here can skip latest 150 items to delete.
Iterating through SPListItemCollection and very quick time like 3000 items will be delete in 2 mints.
SPList list = web.Lists["DemoDelete"];
SPListItemCollection collListItems = list.GetItems();
var watch = System.Diagnostics.Stopwatch.StartNew();
Console.WriteLine("Start Time: " + watch);
//delete all items uncomment this code
//foreach (SPListItem item in collListItems)
//{
// SPListItem delItem = list.GetItemById(item.ID);
// Console.WriteLine("Item Deleted" + delItem.ID);
// delItem.Delete();
// list.Update();
//}
//skip lastest 150 items
for (int i = collListItems.Count - 150; i >= 0; i--)
{
SPListItem listItem = list.GetItemById(collListItems[i].ID); //collListItems[i];
Console.WriteLine("Item Deleted" + listItem.ID);
listItem.Delete();
list.Update();
}
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine("End Time: " + elapsedMs);
As others have said, you shouldn´t iterate the Items collection directly (especially in large collections). Here´s an alternaltive:
// if you need the whole collection. Otherwise use SPQuery on the list
DataTable dt = list.Items.GetDataTable();
foreach (DataRow row in dt.Rows)
{
...
Then you can do numerous things. If you need to do a check to get only some of the items, ex:
if (row["ContentType"].ToString().Equals("Your contenttype id"))
{
SPListItem item = list.GetItemById((int)row["ID"]);
or use the SpQuery to get your column in the query, like:
SPQuery oQuery = new SPQuery();
oQuery.ViewFields = "<FieldRef Name='UrlColumn'/>";
list.Items.GetItems(oQuery).GetDataTable();
...foreach code...
row["UrlColumn"]
If you are in a x86 environment I've recently discovered an awesomely read-only way to get at the data with MSSQL/OLEDB...
SELECT * FROM OPENROWSET (
'Microsoft.ACE.OLEDB.12.0',
'WSS;IMEX=1;RetrieveIds=Yes;DATABASE=http://sharepoint.lsi.local/ops/;LIST={3DCAF100-44A1-4331-8328-748AA98E36AB};',
'SELECT * FROM list'
)
http://www.connectionstrings.com/sharepoint
BTW
When using OPENROWSET...
IMEX=2 is for Read/Write. IMEX=1 is ReadOnly.
List = [Name] works for me instead of needing to use the list={GUID}.