Showing posts with label CAML. Show all posts
Showing posts with label CAML. Show all posts

Sunday, August 28, 2011

Print button for Custom list with Infopath form

Scenario:
We wanted to extend the Ribbon to have a Print button for Custom list with Infopath form.

While I found so many articles to extend Ribbon UI, most of them are for a regular list / library. In SP2010, now we do have an option to use a Infopath for a custom list which uses a brand new Ribbon Tab/Grouping and I found nothing much on Web.

Solution:
Use the following Element manifest.

Code:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Id="InfopathformPrintButton"
Location="CommandUI.Ribbon" Rights="ViewListItems">
<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition
Location="Ribbon.Tabs.InfoPathListDisplayTab.Manage.Controls._children">
<Button Id="Ribbon.Tabs.InfoPathListDisplayTab.Manage.Controls.Print"
Command="CallPrint"
Sequence="1"
Description="Print the infopath form"
Image16by16="/_layouts/images/placeholder32x32.png"
Image32by32="/_layouts/images/placeholder32x32.png"
LabelText="Print"
TemplateAlias="o1"/>
</CommandUIDefinition>
</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler
Command="CallPrint"
CommandAction="javascript:function processPrint(){window.print()};processPrint();" />
</CommandUIHandlers>
</CommandUIExtension>
</CustomAction>
</Elements>

Tuesday, April 19, 2011

SharePoint Custom Publishing Layout feature

Scenario:
I am surprise that I have used this so many times but never blogged this. We often need a custom content type and custom page layout.

Solution:
Here's quick snippet of Element manifest.

Content Type Provisioning Element Manifest:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<!-- Parent ContentType: Page (0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF39) -->
<ContentType ID="0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900New_GUID_Here"
Name="Custom Page"
Description="Custom Page is the default content type for any Publishing Pages."
Group="SKN"
Inherits="TRUE"
Version="0">

<FieldRefs>
<FieldRef ID="{GetGUIDFromBelow}" Name="CustomColumn" />
</FieldRefs>
</ContentType>

<Field ID="{NewGUID}"
Name="CustomColumn"
DisplayName="Custom Column"
Type="Text"
Group="SKN">
<Default></Default>
</Field>

</Elements>
Page Layout Provisioning (with Default WP) Element Manifest:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="CustomPageLayouts" Url="_catalogs/masterpage" Path="PageLayouts" RootWebOnly="TRUE">
<File Url="CustomLayoutPage.aspx" Type="GhostableInLibrary">
<Property Name="Title" Value="Custom Page Layout Blank" />
<Property Name="MasterPageDescription" Value="$Resources:cmscore,PageLayout_BlankWebPartPage_Description;" />
<Property Name="ContentType" Value="$Resources:cmscore,contenttype_pagelayout_name;" />
<Property Name="PublishingPreviewImage" Value="~SiteCollection/_catalogs/masterpage/$Resources:core,Culture;/Preview Images/BlankWebPartPage.png, ~SiteCollection/_catalogs/masterpage/$Resources:core,Culture;/Preview Images/BlankWebPartPage.png" />
<Property Name="PublishingAssociatedContentType" Value=";#WH Page;#SAME_AS_CONTENT_TYPE_ID_ABOVE;#" />

<AllUsersWebPart WebPartOrder="0" WebPartZoneID="Header">
<![CDATA[<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="CustomCode.DefaultWp, CustomCode, Version=1.0.0.0, Culture=neutral, PublicKeyToken=abcdcc1c43254ae6" />
<importErrorMessage>Cannot import Default WP Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">Default Information</property>
<property name="Description" type="string">Description for Default WP</property>
</properties>
</data>
</webPart>
</webParts>]]>
</AllUsersWebPart>

</File>
</Module>
</Elements>
Content Type Association Element Manifest:
  <ContentTypeBinding ContentTypeId="CONTENT_TYPE_ID_FROM_ABOVE" ListUrl="Pages" />
New Page Provisioning using Layout ( with Test WP ) Element Manifest:
 <File Path="SampleBlankWPPage.aspx" Url="Home.aspx" Type="GhostableInLibrary" NavBarHome="True">
<Property Name="Title" Value="Custom Home" />
<Property Name="PublishingPageLayout" Value="~SiteCollection/_catalogs/masterpage/CustomLayoutPage.aspx, Custom Layout Page" />
<Property Name="ContentType" Value="Custom Page" />

<AllUsersWebPart WebPartOrder="0" WebPartZoneID="Header">
<![CDATA[<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="CustomCode.TestWp, CustomCode, Version=1.0.0.0, Culture=neutral, PublicKeyToken=abcdcc1c43254ae6" />
<importErrorMessage>Cannot import Test WP Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">Test Information</property>
<property name="Description" type="string">Description for Test WP</property>
</properties>
</data>
</webPart>
</webParts>]]>
</AllUsersWebPart>
</File>

Sunday, February 7, 2010

Solution Generator web part toolbar issue

Scenario:
I often use Solution Generator and have found many workaround to fit this tool to my needs. Recently I found 2 strange behavior, when I reverse engineer a site definition which has some list view web parts on one of the pages.

1. These web parts had toolbar set to Standard toolbar, it was not respecting the Toolbar type selected.

2. I have added some extra columns to the views, not getting the match when deploying the generated solution.

Solution:
When I took a closer look at the CAML which got generated for the Webpart it had the right Toolbar value and columns in ViewFields.

Actually issue was the BaseViewID attribute for the tag.

Setting BaseViewID to Zero solved the issue.

Other important thing to use Solution Generator:
1. Always create a brand new site from out of box templates to generate a site definition

2. For ListView web parts, don't switch the View from the drop even if it matches your requirement.Always edit the Current View > Edit this View option.

Friday, October 23, 2009

Adding a list item more efficiently

Scenario:
For one of our requirement we were suppose to add 100s of item to multiple lists and we got into some performance issues.

Solution:
Here's a workaround to avoid the overhead of calling SPList.Items.Add() method.

SPList.Update() must be called to save the newly created item.

Code:

public static SPListItem AddItem(this SPList list){

SPQuery query = new SPQuery()
{
Query = "<Where><Eq><FieldRef Name=\"ID\"/><Value Type=\"Integer\">-1</Value></Eq></Where>",
ViewFields = "<FieldRef Name=\"ID\"/>"
};
return list.GetItems(query).Add();
}

Wednesday, September 30, 2009

SPQuery returning no result

Scenario:
One common scenario with SPQuery object is that it returns zero results.
OR
It does return something in DEV but not into PRODUCTION.
OR
Its giving results for Site Collection Administrator but not for some users.

Also you need to recompile\deploy the code if you want to do some trial error with SPQuery's query property value... which can be painful.

Solution:
One of things which can be used is Content and Structure report without recompiling the SPQuery object.

Steps:
Steps for one of the sample report is here
All Checked Out Documents Query Test

Now you can edit the CAML as many times as you want and test the results. Great thing about this is without any code you can test your CAML Query in PRODUCTION.

Friday, September 25, 2009

All checked out documents for site collection

Scenario:
Can we generate a list of documents checked out to anyone – a list of all checked out documents not just Checked Out To me

Steps ( MOSS only ) :

1. Navigate to Home > View All Site Content > Content and Structures Reports > Create a new report with following CAML Query

<Where><Geq><FieldRef Name="CheckoutUser" LookupId="TRUE"/><Value Type="int">0</Value></Geq></Where>
all checkout report

2. Navigate to Site Action > Manage Content and Structure > Change the view to All Checked Out documents ( from right side view drop down)

Tuesday, September 1, 2009

Finding items between dates

Scenario:
Wanted to find out documents getting expired in next 30 min ?
Wanted to find out announcements getting expired in next 30 min ?
Wanted to find out news going live in next 30 min ?

Solution:
Simple CAML query can do the trick. You can also tweak it to do things like..

Documents got modified in past 30 min ?
Issues created in past 30 min ?

Code:

int gapInMin  = 30;

string currentDate = SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now);
string currentDatePlusMinutes = SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now.AddMinutes(gapInMin));


string CAMLQuery = string.Format(@"<Where>"+
"<And>"+
"<Gt>"+
"<FieldRef Name='Expires' />"+
"<Value Type='DateTime' IncludeTimeValue='TRUE' >{0}</Value>"+
"</Gt>"+
"<Leq>"+
"<FieldRef Name='Expires' />"+
"<Value Type='DateTime' IncludeTimeValue='TRUE' >{1}</Value>"+
"</Leq>"+
"</And>"+
"</Where>",currentDate,currentDatePlusMinutes);

Tuesday, August 25, 2009

Uploading file only at Root level

Scenario:
Uploading file only at Root level

Solution:
You can package files as feature and then can upload the files using Module tag, also using RootWebOnly=TRUE will ensure that this file get executed on RootWeb only

Code:

 <Module Name="CommonFiles" Url="" Path="" RootWebOnly="TRUE">
<File Url="Dashboard.aspx" Type="Ghostable" />
</Module>

Adding Content Type to a List

Scenario:
Often we write new content type and want to attach it to existing list.

Solution:
This can be done through code by I always avoid it if i can do the same using CAML

Code:

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<ContentTypeBinding
ContentTypeId="0x010100ABCDEFGHABCDEFGHABCDEFGHABCDEFGH"
ListUrl="/Lists/CustomList" />
</Elements>

Getting updated item using CAML

Scenario:
Often we need to get items which got changed. Its hard to do it using UI, and also using custom code usually we need to compare values, which can be tedious.

Solution:
CAML supports accessing previous and after property using Old / New keywords.

Someone else changes an event last modified by me:

<Query><And><Eq><Value type="string">spvm\administrator</Value><FieldRef Name="Editor/Old"/></Eq><Neq><Value type="string">spvm\administrator</Value><FieldRef Name="Editor/New"/></Neq></And></Query>
Someone else changes an event created by me:
<Query><And><Or><Eq><Value type="string">spvm\administrator</Value><FieldRef Name="Author/New"/></Eq><Eq><Value type="string">spvm\administrator</Value><FieldRef Name="Author/Old"/></Eq></Or><Neq><Value type="string">spvm\administrator</Value><FieldRef Name="Editor/New"/></Neq></And></Query>
Someone else changes an event:
<Query><Neq><Value type="string">spvm\administrator</Value><FieldRef Name="Editor/New"/></Neq></Query>
The time or location of an event changes:
<Query><Or><Or><Neq><FieldRef Name="EventDate/New"/><FieldRef Name="EventDate/Old"/></Neq><Neq><FieldRef Name="EndDate/New"/><FieldRef Name="EndDate/Old"/></Neq></Or><Neq><FieldRef Name="Location/New"/><FieldRef Name="Location/Old"/></Neq></Or></Query>

Tuesday, July 28, 2009

SPQuery Few important things

1. Always specify the RowLimit to get limited results.

oQuery.RowLimit = 100;
2. To Get the Search Items from the sub folders of the list using SPQuery you can do following. Check here
SPQuery.ViewAttributes = "Scope='Recursive'";
or
SPQuery.ViewAttributes = "Scope='RecursiveAll'";
3. Be sure to create a new SPQuery instance each time you use it. You cannot create one SPQuery instance and then reuse it multiple times in a loop where you alter the SPQuery's Query value.
 for (int i = 0; i < 10 ; i++)
{
SPQuery oQuery = new SPQuery();
oQuery.Query = "<Where><Eq><FieldRef Name='AssignedTo' /><Value Type='UserMulti'>"+i +"</Value></Eq></Where>";
SPListItemCollection collListItems = list.GetItems(oQuery);
}
4. SPQuery query object doesn't need to include tags
oQuery.Query = "Completed";
5. If you want to do CAML query which also consider the time in datetime fields then try this
<Where><Eq><FieldRef Name='Created'/><Value Type='DateTime' IncludeTimeValue='TRUE'><Today /></Value></Eq></Where>
6. SPQuery can't be used to search across site collection.One can use SPSiteDataQuery class to search across multiple Lists.

To query the lookup based value items
<where><eq><fieldref name="Employee" lookupid="TRUE"><value type="User">1</value></eq></where>  
7. To restrict the items to approved, use moderationtype attribute. more details here
SPQuery.ViewAttributes = "Scope='Recursive' ModerationType='HideUnapproved'";
8. If you want your query to return empty columns, you have to add Nullable='TRUE' to the viewfields.
query.ViewFields="<FieldRef Name='Description' Nullable='TRUE'/>";
To get the item related within past few days , you can use OffsetDays attribute along with Today.
<Where><Eq><FieldRef Name='Created'/><Value Type='DateTime' ><Today OffsetDays='-7' /></Value></Eq></Where>
Article:
SPQuery Best Practice

Sunday, July 19, 2009

List Definition with no search results

Scenario:
Once in a while we need some hidden list to store some information which we programtically want to consume without letting end users know about it.

Another important thing is that search should not display anything from this list.

Solution:
List Definition does support a tag Privatelist to do similar to this.

Example:

<List 
Name="Private Documents"
Title="Private Documents"
Description="This library store some internal documents used with in the site."
PrivateList="TRUE"
Direction="0"
BaseType="1"
Url="PrivateDocuments"
DisableAttachments="TRUE"
Type="101"
Id="NewGUID"
xmlns="http://schemas.microsoft.com/sharepoint/">
.....
</List>
Note:
Earlier in this ( post ) I already showed you how to create an instance of any list with NoCrawl=True , making that particular instance of the list hidden from search results. Above example is different in the sense , that here list definition itself is hidden and so will be all the instances created from this list definition.

Setting listview webpart properties in CAML

Scenario:
List View web parts are different than other kind of Sharepoint web part in their CAML representation.

Other web parts uses AllUsersWebPart tag which allow easy access to all the properties, so setting properties is easy.

List View webparts uses View Tag to place them on the page. Now we wanted to set some
of it properties which has different values from its default settings.

Solution:
Its was not that difficult to that but finding this undocumented solution was the difficult part :-)

Below example shows how to set AllowZoneChange property to false by default.

Sample Code ( Elements.xml) :

<?xml version="1.0" encoding="utf-8"?>
<Elements Id="NewGUID" xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="Default" Url="" Path="">
<File Url="default.aspx" NavBarHome="True">
<View List="Lists/Announcements" BaseViewID="0" WebPartZoneID="Left" WebPartOrder="1" Type="HTML">
<![CDATA[
<WebPart xmlns="http://schemas.microsoft.com/WebPart/v2">
<Assembly>Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c</Assembly>
<TypeName>Microsoft.SharePoint.WebPartPages.ListViewWebPart</TypeName>
<Title>Announcements</Title>
<AllowRemove>false</AllowRemove>
<AllowZoneChange>false</AllowZoneChange>
<AllowMinimize>false</AllowMinimize>
<AllowConnect>false</AllowConnect>
<AllowEdit>false</AllowEdit>
<AllowHide>false</AllowHide>
</WebPart>
]]>
</View>
</File>
</Module>
</Elements>

Tuesday, July 14, 2009

Add a Button to the Ribbon

Scenario:
To add a button to the sharepoint 2010 ribbon interface, is pretty much the same as adding Custom Action in MOSS 2007.

Solution:
Here's the element manifest file for developing a feature for adding a button to the ribbon to the Library tab in the Actions group for a document library (Type=101).

Element Manifest for the Feature:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction Id="Ribbon.Library.Actions.AddAButton"
Location="ViewToolbar"
RegistrationId="101"
RegistrationType="List"
Title="Add a Ribbon Button">
<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition
Location="Ribbon.Library.Actions.Controls._children">
<Button Id="Ribbon.Library.Actions.NewRibbonButton"
Command="NewRibbonButtonCommand"
Image16by16="/_layouts/images/FILMSTRP.GIF"
Image32by32="/_layouts/images/PPEOPLE.GIF"
LabelText="New Button"
TemplateAlias="o2" />
</CommandUIDefinition>
</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler
Command="NewRibbonButtonCommand"
CommandScript="javascript:alert('This is a new button!');" />
</CommandUIHandlers>
</CommandUIExtension>
</CustomAction>
</Elements>

Sunday, July 5, 2009

CAML query and Sharepoint Groups

Scenario:
Task list is one of the most commonly used list in sharepoint. But I think it is missing a view in which someone can filter what tasks are either directly assigned him or any of the Active Directory Group/SharePoint Group he belongs to.

Solution:
After some digging into CAML , I got the right CAML query for getting me exactly the same thing.

CAML

Code:

<Where>
<Or>
<Membership Type="CurrentUserGroups">
<FieldRef Name="AssignedTo"/>
</Membership>
<Eq>
<FieldRef Name="AssignedTo"></FieldRef>
<Value Type="Integer">
<UserID/>
</Value>
</Eq>
</Or>
</Where>
<OrderBy>
<FieldRef Name="Status"/>
<FieldRef Name="Priority"/>
</OrderBy>

Thursday, April 9, 2009

Using SPQuery with Views for dynamically controlling fields

Scenario:
For one of the webpart we wanted to get data from a list but client wanted to dynamically decide the columns displayed.

Solution:
Using SPQuery and SPView we can dynamically control fields.

Code:

using (SPWeb oWebsite = SPContext.Current.Site.AllWebs["Site_Name"])
{
SPList oList = oWebsite.Lists["DocLib_Name"];
SPView oView = oList.Views["View_Name"];

SPQuery oQuery = new SPQuery(oView);
oQuery.ViewAttributes = "Scope=\"Recursive\"";
SPListItemCollection collListItemsAvailable =
oList.GetItems(oQuery);

foreach (SPListItem oListItemAvailable in collListItemsAvailable)
{
Response.Write(SPEncode.HtmlEncode(oListItemAvailable["Name"]));
}
}

Tuesday, March 31, 2009

Adding a title link to an item in a document list

Scenario:
If some one ask me my favorite topic, its CAML , so much can be done with CAML.
I wanted to display document title using a custom field.

Solution:
Field tag support Display pattern.

Code:

<Field ReadOnly="TRUE" Type="Computed" Name="LinkedToTitle"
DisplayName="Document Title" DisplayNameSrcField="Title"
AuthoringInfo="(linked to document)">
<FieldRefs>
<FieldRef Name="Title"/>
<FieldRef Name="FileRef"/>
</FieldRefs>
<DisplayPattern>
<HTML><![CDATA[<A HREF="]]></HTML>
<HttpHost URLEncodeAsURL="TRUE"/>
<LookupColumn Name="FileRef" URLEncodeAsURL="TRUE"/>
<HTML><![CDATA[">]]></HTML>
<Switch>
<Expr>
<Column Name="Title"/>
</Expr>
<Case Value="">
<UrlBaseName HTMLEncode="TRUE">
<LookupColumn Name="FileRef"/>
</UrlBaseName>
</Case>
<Default>
<Column Name="Title" HTMLEncode="TRUE"/>
</Default>
</Switch>
<HTML><![CDATA[</A>]]></HTML>
</DisplayPattern>
</Field>
Article:CAML Viewer

Monday, March 30, 2009

Using ListView by Query in webpart

Scenario:
I wanted to display information into grid using a CAML query

Solution:
Share Point has a ListViewByQuery Control which can help.

Code:

using System;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

namespace Training
{
public class myWebPart: System.Web.UI.WebControls.WebParts.WebPart
{
public override void RenderControl(HtmlTextWriter writer)
{
ListViewByQuery view = new ListViewByQuery();

SPWeb currentweb = SPContext.Current.Web;
SPList list = currentweb.Lists["Shared Documents"];
view.List = list;
SPQuery query = new SPQuery(view.List.DefaultView);
query.ViewFields = "<FieldRef Name='Title'/>";
query.Query = "<Where><Contains><FieldRef Name='Subject'/><Value Type='Text'>Sample</Value></Contains></Where>";
view.Query = query;
EnsureChildControls();
view.RenderControl(writer);
RenderChildren(writer);
}
}
}
Article:

Wednesday, March 25, 2009

Creating List Instance with Default values

Scenario:
I wanted to create a list instance in my site definition with some properties already set including no crawling and hidden.

Solution:
Schema support setting lot of properties.

Code:

<ListTemplate Name="SpecialDocumentLib"
DisplayName="SpecialDocumentLib"
Description="SpecialDocumentLib"
SetupPath="SpecialDocumentLib" Type="101" BaseType="1" Hidden="TRUE"
HiddenList="TRUE" NoCrawl="TRUE" FolderCreation="FALSE" Unique="TRUE"
RootWebOnly="FALSE" Catalog="FALSE" OnQuickLaunch="FALSE" SecurityBits="11"
AllowDeletion="FALSE" Image="/_layouts/image/specialdoclib.gif"
DontSaveInTemplate="TRUE" DocumentTemplate="100" />
</ListTemplates>
Note:
Hidden=TRUE will hide the list definition from the Create page.
and
HiddenList=TRUE will hide the list instance you have created using this list definition.

Tuesday, February 17, 2009

Creating navbar links from site definition

Scenario:
We were working on a small assignment to create a Help Desk application. And while writing the site definition we wanted to add Quick Nav Menus.

Solution:
This solution came from my student Vasu.
You can use NavBars and NavBarLink tags to add quick launch links.

Code:

<NavBar Name="HelpDesk"
Separator="&nbsp;&nbsp;&nbsp;"
Body="<a ID='onetleftnavbar#LABEL_ID#'
href='#URL#' accesskey='H' >#LABEL#</a>" Url="#" ID="1100">

<NavBarLink Name="Open new Ticket"
Url="Lists/TicketContact/NewForm.aspx">
</NavBarLink>
<NavBarLink Name="All Tickets"
Url="Lists/TicketContact/AllItems.aspx">
</NavBarLink>
</NavBar>