I have two simple lists. one is called employee which has 1 column called Title. Another is called Company which has 1 column called Title. I added a lookup column in the Employee List and pointed it to the ID of the Company List.
Now I wrote this code using CSOM (no javascript and no server object model)
ClientContext c = new ClientContext(url);
List el = c.Web.Lists.GetByTitle("Employee");
CamlQuery query = new CamlQuery();
query.ViewXml = #"<View>
<ViewFields>
<FieldRef Name='ID'/>
<FieldRef Name='Title'/>
<FieldRef Name='CompanyTitle'/>
</ViewFields>
<Joins>
<Join Type='LEFT' ListAlias='Company'>
<Eq>
<FieldRef Name='Company' RefType='Id'/>
<FieldRef List='Company' Name='ID'/>
</Eq>
</Join>
</Joins>
<ProjectedFields>
<Field Name='CompanyTitle' Type='Lookup' List='Company' ShowField='Title'/>
</ProjectedFields>
<Query>
<Where>
<Eq>
<FieldRef Name='Company' LookupId='TRUE' />
<Value Type='Lookup'>10</Value>
</Eq>
</Where>
</Query>
</View>";
ListItemCollection items = el.GetItems(query);
c.Load(items);
c.ExecuteQuery();
foreach (ListItem i in items) {
Console.WriteLine(i["Title"]);
Console.WriteLine(i["CompanyTitle"]);
}
It works... but it prints
E01
Microsoft.SharePoint.Client.FieldLookupValue
E11
Microsoft.SharePoint.Client.FieldLookupValue
E21
But instead of seeing "Microsoft.SharePoint.Client.FieldLookupValue" I wanted to see the actual content of the column from the parent list.
what is wrong with my code?
Got it
Console.WriteLine(((FieldLookupValue)i["CompanyTitle"]).LookupValue);
putting it here so that it may help someone
Related
When I query my SharePoint 2013 calendar list item I get my event back, but for the RecurrenceData item the value just says V3RecurrencePattern.
How do I get the actual pattern that was set? I'm not looking to get each instance of the item. I really just want the recurrence data.
You need <DateRangesOverlap> for that.
Try with this
SPQuery query = new SPQuery();
string queryString =
#"
<Where>
<DateRangesOverlap>
<FieldRef Name=""EventDate""/>
<FieldRef Name=""EndDate""/>
<FieldRef Name=""RecurrenceID""/>
<Value IncludeTimeValue=""TRUE"" Type=""DateTime"">
<Now/>
</Value>
</DateRangesOverlap>
</Where>
<OrderBy>
<FieldRef Name=""EventDate"" Ascending=""TRUE""/>
</OrderBy>
";
query.Query = queryString;
query.ExpandRecurrence = true;
Reference http://sharepointchan.blogspot.hr/2011/10/situation-i-want-to-get-all-calendar.html
My C# application runs outside SharePoint, so I'm using CSOM with a Caml query. I want to find all calendar events, single and recurring, that are scheduled for a single day. I'm getting ALL recurring calendar events that overlap my selected day even if they do not have any scheduled events on the day in question. Single events are correctly filtered and returned. How do I filter the recurring events to only those that fire on the given date? Is this any easier with a Task list rather than a Calendar list?
var today = DateTime.UtcNow.ToString(#"yyyy-MM-ddT12:00:00Z");
var query = new CamlQuery {
ViewXml = #"<View>
<ViewFields>
<FieldRef Name='ID' />
<FieldRef Name='Title' />
<FieldRef Name='EventDate' />
<FieldRef Name='EndDate' />
<FieldRef Name='Description' />
<FieldRef Name='Category' />
<FieldRef Name='fRecurrence' />
<FieldRef Name='RecurrenceData' />
<FieldRef Name='fAllDayEvent' />
</ViewFields>
<Query>
<Where>
<DateRangesOverlap>
<FieldRef Name='EventDate'></FieldRef>
<FieldRef Name='EndDate'></FieldRef>
<FieldRef Name='RecurrenceID'></FieldRef>
<Value Type='DateTime'><Today/></Value>
</DateRangesOverlap>
</Where>
<OrderBy><FieldRef Name='EventDate' /></OrderBy>
</Query>
<QueryOptions>
<CalendarDate>"+ today + #"</CalendarDate>
<RecurrencePatternXMLVersion>v3</RecurrencePatternXMLVersion>
<ExpandRecurrence>TRUE</ExpandRecurrence>
</QueryOptions>
</View>"
};
It is possible using the DateRangesOverlap CAML operator and the Lists web service (no support in the Client OM or in OData / REST!) from the client side, see description here.
You can define a variable for the current date as:
var today = DateTime.UtcNow.Date;
var todayAsString = today.ToString("yyyy-MM-dd");
Then you COULD use its value in your query to restrict the result for the events scheduled for today:
string.Format("<Query><Where><And><Eq><FieldRef Name='EventDate' /><Value Type='DateTime' IncludeTimeValue='FALSE'>{0}</Value></Eq><Eq><DateRangesOverlap><FieldRef Name='EventDate' /><FieldRef Name='EndDate' /><FieldRef Name='RecurrenceID' /><Value Type='DateTime'><Month/></Value></DateRangesOverlap></And></Where><Query>", todayAsString);
But based on my experience, this kind of query won't work as you might expect. If you include another DateTime-based condition in the query beyond DateRangesOverlap, the recurring events won't be expanded again. Just another 'kind' surprise from SharePoint. The expanding of recurring events seems to work only if you use DateRangesOverlap, and you use only this kind of DateTime-based condition in your query (but no other condition like <Eq> or <Gt> combined with a DateTime field).
You CAN however combine DateRangesOverlap with other kind of conditions (like <Eq> or <Gt>), as long as they are related to other field types, like Number or Text.
It means you should query for all event in the current Month (as in the sample CAML query above), for example by setting the CalendarDate QueryOption, then you should add a loop with an extra condition in your code (I mean C# or JavaScript, not in CAML!) to compare the event dates with the current one. Really cumbersome.
Here's what I'm doing (this is a quick search on Google and just one of the first results):
http://msdn.microsoft.com/en-us/library/cc300163(v=office.12).aspx
My databound DropDownList items looks like this:
<listitem>All Providers</listitem>
<listitem>Provider 1</listitem>
<listitem>Provider 2</listitem>
My current CAML query in the view looks like:
<Query>
<Where>
<And>
<Or>
<Eq>
<FieldRef Name="Status" />
<Value Type="Lookup">Submitted</Value>
</Eq>
<Eq>
<FieldRef Name="Status" />
<Value Type="Lookup">In Progress</Value>
</Eq>
</Or>
<Eq>
<FieldRef Name="Provider"/>
<Value Type="Text">{Param1}</Value>
</Eq>
</And>
</Where>
<OrderBy>
<FieldRef Name="ID" Ascending="FALSE"></FieldRef>
</OrderBy>
</Query>
What I NEED is this...
In psuedocode:
If {Param1} equals "All Providers" just filter on Status where Status is equal to "Submitted" or "In Progress"
else if {Param1} is not equal to "All Providers" filter on Status and Provider where Status is equal to "Submitted" or "In Progress" and Provider is equal to {Param1}
How do I put this into View XML schema?
I know it can be done as Microsoft already uses it in SharePoint and there's 3rd-party controls that do it.
For example...
1) In SP, click on "Lists" in the left nav menu.
2) To the far right, under the search box', you'll see "View:" with a dropdown.
3) Based on which view you choose, the URL's querystring contains "BaseType" that changes to the value of your choice. If "All Site Content" is chosen, the "BaseType" is left out of the querystring.
Thanks,
Joshua
First off, I think you are better off adding a filter webpart for the Provider field, as this allows you to not filter with a blank value.
If you must have a parameter that filters on "All Providers" you can create a calculated field on the list call AllProviders say, with the formula:
="All Providers"
This then allows your query clause to be entered thusly:
<Query>
<Where>
<And>
<Or>
<Eq>
<FieldRef Name="AllProviders"/>
<Value Type="Text">{Param1}</Value>
</Eq>
<Eq>
<FieldRef Name="Provider"/>
<Value Type="Text">{Param1}</Value>
</Eq>
</Or>
<Or>
<Eq>
<FieldRef Name="Status"/>
<Value Type="Lookup">In Progress</Value>
</Eq>
<Eq>
<FieldRef Name="Status"/>
<Value Type="Lookup">Submitted</Value>
</Eq>
</Or>
</And>
</Where>
</Query>
The Status field will always match either "In Progress" or "Submitted".
If your parameter = "All Providers" then you will match the calculated field, otherwise you will match on the Provider field.
Note that this does prevent you from having a Provider call "All Providers".
I have the following code:
SPQuery oQuery = new SPQuery();
oQuery.Query = #"<Query>
<Where>
<And>
<Eq>
<FieldRef Name='PublishToSM' />
<Value Type='Boolean'>1</Value>
</Eq>
<IsNull>
<FieldRef Name='SMUpdateDate' />
</IsNull>
</And>
</Where>
</Query>";
SPListItemCollection collListItems = list.GetItems(oQuery);
NevCoSocialMedia.NevCoFacebook fb = new NevCoSocialMedia.NevCoFacebook();
foreach (SPListItem oListItem in collListItems)
{
if (oListItem.Fields.ContainsField("PublishToSM") && Convert.ToBoolean(oListItem["PublishToSM"]) == true)
{
.
.
.
My question is why do I need to have the last if statement? If I don't have this it will throw an error saying that the identifier does not exist when it tries to do oListItem["PublishToSM"]. This seems impossible since my CAML query is checking that that has an appropriate value...
remove the
"query" element
wrapping your caml
Try changing the value type to an integer
<Eq>
<FieldRef Name='PublishToSM' />
<Value Type='Integer'>1</Value>
</Eq>
http://www.sharepointblues.com/2010/02/22/caml-and-querying-boolean-fields/
Always add ViewFields, if you don't, only basic fields like ID and Title get filled in the returned listitems.
I've encountered a weird problem with using the Boolean type in a caml query before as well. In 6 out of our 7 environments Boolean worked fine, but in one of them it did not and it totally messed up one of our workflows. We were never able to figure out why.
Try Integer or Bit for the 'PublishToSM' field and see if you get a different result.
How do you limit groups displayed on a Sharepoint 2010 list view with CAML?
<Query>
<GroupBy Collapse="FALSE">
<FieldRef Name="MyField" Ascending="FALSE" />
</GroupBy>
<OrderBy>
<FieldRef Name="MyField" />
</OrderBy>
</Query>
I want to display only first 3 groups. Is it possible to do that with CAML?
I exported a view with sharepoint designer and it has
<Query>
<GroupBy Collapse="FALSE" GroupLimit="3">
<FieldRef Name="MyField" Ascending="FALSE" />
</GroupBy>
</Query>
But it isnt in the schema
http://msdn.microsoft.com/en-us/library/ms415157.aspx
if you want to limit rows returned by caml query use this :
SPQuery qry = new SPQuery();
qry.RowLimit = 3;
string camlquery = " ";
qry.Query = camlquery;