Using CAML to compare SharePoint "Person or Group" fields - sharepoint

I have a SharePoint 2007 (MOSS) list with 2 "Person or Group" columns which I would like to compare, essentially:
SELECT * FROM List WHERE (Analyst = Developer)
In my code (C#) I've built this as:
SPQuery itemQuery = new SPQuery();
itemQuery.Query = "<Where><Eq><FieldRef Name='Analyst' /><FieldRef Name='Developer' /></Eq></Where>";
SPListItemCollection queryResults = list.GetItems(itemQuery);
But this is throwing an exception ("Exception from HRESULT: 0x80020009 (DISP_E_EXCEPTION)").
I've seen some information regarding the Type attribute of a Value element when comparing against a "Person or Group" column, but nothing about comparing two of these columns against each other.
I've also tried adding "LookupId='TRUE'" to each FieldRef, with no change.

It is not possible to compare two fields like that using CAML. You have to use a literal value. This means, that you'll likely have two queries:
Retrieve the Analyst/Developer's user ID
Retrieve items where Analyst and Developer are the same
Example of #2:
<Where>
<And>
<Eq><FieldRef Name="Analyst" LookupId="TRUE"/><Value Type="Integer">42</Value></Eq>
<Eq><FieldRef Name="Developer" LookupId="TRUE"/><Value Type="Integer">42</Value></Eq>
</And>
</Where>
FYI, you can also use <UserID/> for the "Current User" instead of user ID (in this example, 42).

The logic you are looking for, I believe, is this:
<Where>
<Eq>
<FieldRef Name='Analyst'/>
<Value Type="Text"><FieldRef Name='Developer'/></Value>
</Eq>
</Where>
I tested and this is not possible so the two options, as I see it, are:
Get all list items , then iterate through with JQuery with a find and compare for the two fields being equal.
Create a calculated column that sets a true or false value if the two columns are equal in the list and then do your select based on that column. This is probably the most expedient and also most effective from a performance perspective.

Try this:
<Where>
<Eq>
<FieldRef Name="Analyst" />
<Value Type="Text">Developer</Value>
</Eq>
</Where>
I have found a list that has two matching values to compare and I got a CAML query to work with the comparison; however, it is a boolean value so I am not sure if this is what you are looking for. It does compare two fields but I think the literal is still getting in the way. This list has about 25 entries in it and this is the only one that matched so I thought this would be a good test.
Here is the code:
private DataTable ExecuteQuery(SPList list)
{
SPQuery qry = new SPQuery();
qry.Query = "<Where><And><Contains><FieldRef Name='Show' /><Value Type='Boolean'>1</Value></Contains><Contains><FieldRef Name='Highlight' /><Value Type='Boolean'>1</Value></Contains></And></Where>";
qry.ViewFields = "<FieldRef Name='Show' /><FieldRef Name='Highlight' />";
qry.IncludeMandatoryColumns = true;
return list.GetItems(qry).GetDataTable();
Sorry if this is not what you are looking for. Good Luck!!

Related

SharePoint Online: Get Document Library Children Count Using CSOM

My requirement is to get the children item count of Document Library using CSOM. The count should only be the immediate children count, and should not include the sub-children count. I am trying to use below code to achieve this:
var newObjClientContext = this.GetSharePointClientContext(accessToken, fullUri);
WebCollection collWeb = newObjClientContext.Web.GetSubwebsForCurrentUser(new SubwebQuery());
var documentLibrary = newObjClientContext.Web.Lists.GetById(docID);
ListItemCollection ltitems = null;
string vquery = #"<View >
<Query>
<Where>
<Or>
<Eq>
<FieldRef Name='FSObjType' />
<Value Type='Lookup'>1</Value>
</Eq>
<Eq>
<FieldRef Name='FSObjType' />
<Value Type='Lookup'>0</Value>
</Eq>
</Or>
</Where>
<OrderBy><FieldRef Name='FileLeafRef' Ascending='TRUE'></FieldRef></OrderBy>
</Query>
<RowLimit>" + recCount + #"</RowLimit>
</View>";
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = vquery;
ltitems = documentLibrary.GetItems(camlQuery);
newObjClientContext.Load(documentLibrary);
newObjClientContext.Load(ltitems, lists => lists.IncludeWithDefaultProperties(l => l.ParentList));
newObjClientContext.ExecuteQuery();
int totalcount = documentLibrary.ItemCount; //It includes count of all the items present at all levels.
Can anyone suggest how can I get children count in above step?
If I have interpreted your requirement correctly you want the root level child item count of the document library? This is easily achieved using the ItemCount property of document libraries RootFolder.
var list = web.Lists.GetByTitle("Documents");
cc.Load(list.RootFolder, l => l.ItemCount);
cc.ExecuteQuery();
var rootChildItemCount = list.RootFolder.ItemCount;
Or do you require the child item count of every folder in your document library? This can be achieved with a CamlQuery. Let me know if your require a solution for this.

CAML person or Group field with Multiple values

I have a Field with Name TargetedPeople in a Sharepoint list. This is a Person or User group which can have multiple values.
The CAML I used for Querying is
siteDataQuery.Query = #"<Where><Includes><FieldRef Name='TargetedPeople' LookupId='TRUE'/><Value Type='Integer'>" + webInContext.CurrentUser.ID + "</Value></Includes></Where>";
This works fine if we have set the Allow Multiple Selections for "No" in the field. But this seems like not working for if it set to "Yes".
Please share me how to query a multiple field.
After some changes I was able to figure out this. If the field has multiple values we should define the value Type as LookupMulti. Following is the working code sample
siteDataQuery.Query = #"<Where><Contains><FieldRef Name='TargetedPeople' LookupId='TRUE'/><Value Type='LookupMulti'>" + webInContext.CurrentUser.ID + "</Value></Contains></Where>";
Also works and looks like simpler (tested on SP Online):
<Contains>
<FieldRef Name='TargetedPeople' />
<Value Type="Integer">
<UserID Type="Integer" />
</Value>
</Contains>

Query on Date Fields using CAML

I am trying to run a query against a sharepoint list (using the client object model), finding an item that matches on a date field.
My query is:
2012-07-24T02:50:28
1
I know that there is an item in the list where the EmDateSent field has the value 2012-07-24T02:50:28 and yet when I run this I get 0 rows back.
Having spent hours researching and experimenting I found that the date formatting I have used works - or so I thought. It seems that now it doesn't.
My code is below.
Can anybody suggest something else I can try?
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml = String.Format(
#"<View>
<Query>
<Where>
<Eq>
<FieldRef Name='{0}'/>
<Value Type='DateTime' IncludeTimeValue='True'>{1}</Value>
</Eq>
</Where>
</Query>
</View>", EMAIL_FIELD_DATE_SENT, details.DateSent.HasValue ? details.DateSent.Value.ToString("yyyy-MM-ddTHH:mm:ss") : "");
ListItemCollection listItems = upLoadList.GetItems(camlQuery);
_context.Load(listItems);
_context.ExecuteQuery();
if (listItems.Count > 0) // At this point I expect listItems.Count to be 1, but it is 0
{
....
Your example looks correct, and there is not an issue with using the "T" in the time stamp. However, from what I can find, most of the examples like yours use the SPQuery class instead of the CamlQuery class. I believe this is causing your issue.

Sharepoint SPQuery problem

I'm trying to use GetItems() method on a SPList and I pass SPQuery to it. The problem is, it return all the items from my SPList instead of just the filtered ones. My query looks like this:
<WHERE><Eq><FieldRef Name='Type' /><Value Type='Text'>Analysis</Value></Eq></WHERE>
Thye typye of the'Type' column is Single line of text, which i believe translates to Text in CAML. Then I just do the standard stuff:
SPQuery q = new SPQuery();
q.Query = CAMLQuery.ToString();
var filtered = _NoticeList.GetItems(q);
filtered.Count is 4 instead of 2... perhaps someone cann se whats wrong with this code
I think CAML is Case sensitive so it'd have to be:
<Where><Eq><FieldRef Name='Type' /><Value Type='Text'>Analysis</Value></Eq></Where>
Otherwise you could try renaming the 'Type' field, because it might be interpreted as an internal field.

Sharepoint GetListItems using rowLimit parameter is not limiting the results returned

In SharePoint I am using the default view of a list. When I use GetListItems method I can pass into it the following:
public XmlNode GetListItems (
string listName,
string viewName,
XmlNode query,
XmlNode viewFields,
string rowLimit,
XmlNode queryOptions,
string webID
)
I am passing in "" for the viewName and am passing a rowLimit of 1000. By Default view only returns 100 items. 100 Items are still being returned not 1000.
Can you use the rowLimit when not specifying a view? Is it possible to bring back 1000 items using the query instead? I do not really want to use a GUID for the viewName as I would have to look it up for each list and perform a big refactor.
Update
I am now using the guid of the view and my list still returns the incorrect number of items. I know the guid is being used as I sued an incorrect one and it errord out.
Any ideas what could be wrong?
The code that is being sent to the service is as follows:
<GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'>
<listName>Media Outlet</listName>
<viewName>{2822F0D9-A905-44B5-8913-34E6497F1AAF}</viewName>
<query><Query><Where><Eq><FieldRef Name='Outlet_x0020_Type' /><Value Type='Lookup'></Value></Eq></Where><OrderBy><FieldRef Name='Title' /></OrderBy></Query></query>
<ViewFields></ViewFields>
<RowLimit>1000</RowLimit>
<QueryOptions></QueryOptions>
<webID></webID>
</GetListItems>
Update
I have tried with a RowLimit as 1 and I still get a lot of the results back???
The xml should be as follows:
<GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'>
<listName>Media Outlet</listName>
<viewName>{2822F0D9-A905-44B5-8913-34E6497F1AAF}</viewName>
<query><Query><Where><Eq><FieldRef Name='Outlet_x0020_Type' /><Value Type='Lookup'></Value></Eq></Where><OrderBy><FieldRef Name='Title' /></OrderBy></Query></query>
<viewFields></viewFields>
<rowLimit>1000</rowLimit>
<queryOptions></queryOptions>
<webID></webID>
</GetListItems>
You need lower-case names so rowLimit rather than RowLimit.

Resources