Monday, July 27, 2015

Achieve Composite Unique Key using jQuery SPServices

The below code is to achieve composite unique key for the combination of two fields.

<script language="javascript" type="text/javascript" src="../../SiteAssets/jquery-1.11.1.min.js"></script>
<script language="javascript" type="text/javascript" src="../../SiteAssets/jquery.SPServices-2013.01.js"></script>

<script type="text/javascript">
//Validate for Composite primary key (Sku Number, Serial Number)
        function ValidateData() {        
            var skuSearch = $("#iSku option:selected").val();
            var serialSearch = $("#iSerial").val();
            var revSearch = $("#iRev").val();
            var cond = false;
            $().SPServices({
                operation: "GetListItems",
                async: false,
                listName: "ListName",
                CAMLViewFields: "<ViewFields><FieldRef Name='SkuNum'/><FieldRef Name='SerialNo'/></ViewFields>",
                completefunc: function (xData, Status) {
                    $(xData.responseXML).SPFilterNode("z:row").each(function () {
                        if (skuSearch == $(this).attr("ows_SkuNum") && serialSearch == $(this).attr("ows_SerialNo")) {
                            cond = true;
                        }

                    });
                }
            });
            //If Valid
            if (cond == true) {
                //GetData(skuSearch, serialSearch);//Method to fetch the field values. Not Mentioned in blog
            }
            else {
               // ClearData(); //Method to clear the fields. Not specified in blog.
                alert("Data not found. Please try different combination.");
            }
        }
</script>


If you want to achieve composite unique key for the combination of more than two fields, the above code will help but prefer the below link to modify the CAML query accordingly.
http://aasai-sharepoint.blogspot.in/2013/02/caml-query-with-multiple-conditions.html 

Wednesday, July 22, 2015

Looping in SharePoint Designer 2013 Workflow

1. When you just need to loop through list items/item fields, then prefer the below steps.


2. When you need to loop through list items / item fields and also testing a condition, then prefer the below link.

Hi Folks,

I worked on a requirement to read all the list items from a list and compare its fields "Blackout Date" and "Team" value for each item with the current item fields "StartDate" and "Team" in current list.
I used looping in SPD 2013 to implement this function. 

Developers would know how to compare using conditions. I'll just focus on looping part.

1. We need to use HttpServices action to read list items.



For the first step, we did the below steps to build the dictionary




For the second step, follow the below steps.



The URL is : https://accobrands.sharepoint.com/sites/ITAppDev/CCISDev/_vti_bin/client.svc/web/lists/getbyid('E704B0F5-58DE-4627-9769-6415E0677AEB')/Items



The rest steps are pretty straight. Follow them.



Now comes the looping part. We need to initiate the loop with workflow variable say "index". Check the below steps.

The below steps from the above image retrieves data from JSON results.



The last 2 steps we had to implement in order to increment the loop.




The entire Workflow steps combined here as below.



Thursday, July 9, 2015

How to create a search page using SharePoint search functionality to search data in a particular list

These are the following steps i used to achieve the same in my project.

  1.  I created metadata properties in the search service application to match the fields in the discussion board list and mapped them to crawled properties. Here is a list of properties we are searching on: IssueNumber, Title, Author, SystemImpacted, Status, Priority.
    ---Central Admin
    àManage Service applicationsàSearch Service ApplicationàIn the quick launch section, Click ‘Metadata Properties’ under “Queries & Results”àClick “New Managed Property”àProvide ‘Property name’ and ‘Type’àAdd Mapping in “Mapping to Crawled Properties” sectionàSearch for the field name prefixed with “ows_” , select it and press OK.
  2. Then I wrote a quick user control form to construct the query string based on the values for these          properties entered by the user in the form. I will add the code to source control as soon as I get access  to source safe. The user control itself resides here (Server_name)                                                                    C:\inetpub\wwwroot\wss\VirtualDirectories\80\UserControls. I did not put it in the 14 hive because                  the smarts parts solution looks in this directory.
IssueTrackerListSearch.ascx.cs
using System;

using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace IssueTrackerSearch
{
    public partial class IssueTrackerListSearch : System.Web.UI.UserControl
    {

        protected void Page_Load(object sender, EventArgs e)
        {
        }

        protected void btnClear_Click(object sender, EventArgs e)
        {
            ClearControl(this);
        }

        protected void btnSubmit_Click(object sender, EventArgs e)
        {
            Response.Redirect(CreateSearchStringQuery());
        }

        private string CreateSearchStringQuery()
        {
            StringBuilder queryString = new StringBuilder();
            queryString.Append("<SiteUrl>/Search/Pages/IssueTrackerResults.aspx?k=");

            if (!String.IsNullOrEmpty(txtIssueNumber.Text))
            {
                queryString.AppendFormat(" {0}:{1}", "IssueNumber", txtIssueNumber.Text.Trim());
            }

            if (!String.IsNullOrEmpty(txtIssue.Text))
            {
                queryString.AppendFormat(" {0}:{1}", "Title", txtIssue.Text.Trim());
            }

            if(!String.IsNullOrEmpty(txtSubmittedBy.Text))
            {
                queryString.AppendFormat("{0}:{1}","Author",txtSubmittedBy.Text.Trim());
            }

            if (!String.IsNullOrEmpty(txtSystemImpacted.Text))
            {
                queryString.AppendFormat(" {0}:{1}", "SystemImpacted", txtSystemImpacted.Text.Trim());
            }

            if (!String.IsNullOrEmpty(ddlStatus.SelectedValue))
            {
                queryString.AppendFormat(" {0}:{1}", "Status", ddlStatus.SelectedValue.Trim());
            }

            if (!String.IsNullOrEmpty(ddlPriority.SelectedValue))
            {
                queryString.AppendFormat(" {0}:{1}", "Priority", ddlPriority.SelectedValue.Trim());
            }

            if (!String.IsNullOrEmpty(txtCustomerName.Text))
            {
                queryString.AppendFormat(" {0}:{1}", "CustomerName", txtCustomerName.Text.Trim());
            }
            if (!String.IsNullOrEmpty(txtItemNumber.Text))
            {
                queryString.AppendFormat(" {0}:{1}", "ItemNumber", txtItemNumber.Text.Trim());
            }
            if (!String.IsNullOrEmpty(txtItemDescription.Text))
            {
                queryString.AppendFormat(" {0}:{1}", "ItemDescription", txtItemDescription.Text.Trim());
            }
            if (!String.IsNullOrEmpty(txtOrderNumber.Text))
            {
                queryString.AppendFormat(" {0}:{1}", "OrderNumber", txtOrderNumber.Text.Trim());
            }
            if (!String.IsNullOrEmpty(ddlBusinessSegment.SelectedValue))
            {
                queryString.AppendFormat(" {0}:{1}", "BusinessSegment", ddlBusinessSegment.SelectedValue.Trim());
            }
            return queryString.ToString();

        }

        private void ClearControl(Control control)
        {
            TextBox textbox = control as TextBox;
            if (textbox != null)
                textbox.Text = string.Empty;

            DropDownList dropDownList = control as DropDownList;
            if (dropDownList != null)
                dropDownList.SelectedIndex = 0;
            foreach (Control childControl in control.Controls)
            {
                ClearControl(childControl);
            }
        }
    }
}


IssueTrackerListSearch.ascx

<%@ Control Language="C#" AutoEventWireup="true" 

CodeFile="IssueTrackerListSearch.ascx.cs" 
Inherits="IssueTrackerSearch.IssueTrackerListSearch" %>

<style type="text/css">
    .style1
    {
        height: 26px;
    }
    .style2
    {
        height: 30px;
    }
</style>

<h3>Search issues based on the following criteria:</h3>
<table>
<tbody>
<tr>
<td colspan="3"><strong>Business Issue</strong></td>
<td>
    <strong></strong>
    </td>
<td colspan="3">
    <strong>Customer Issue</strong></td>
</tr>

<tr>
<td>Issue Number</td>
<td></td>
<td>
    <asp:TextBox ID="txtIssueNumber" runat="server" Width="250px" Wrap="False"></asp:TextBox>
    </td>
<td>
    &nbsp;</td>
<td>
    Customer Name</td>
<td>
    &nbsp;</td>
<td>
    <asp:TextBox ID="txtCustomerName" runat="server" Width="250px"></asp:TextBox>
    </td>
</tr>

<tr>
<td>Issue</td>
<td></td>
<td>
    <asp:TextBox ID="txtIssue" runat="server" Width="250px" Wrap="False"></asp:TextBox>
    </td>
<td>
    &nbsp;</td>
<td class="style1">
    Item Number</td>
<td>
    &nbsp;</td>
<td>
    <asp:TextBox ID="txtItemNumber" runat="server" Width="250px"></asp:TextBox>
    </td>
</tr>

<tr>
<td>Submitted by</td>
<td></td>
<td>
    <asp:TextBox ID="txtSubmittedBy" runat="server" Width="250px" Wrap="False"></asp:TextBox>
    </td>
<td>
    &nbsp;</td>
<td class="style1">
    Item Description</td>
<td>
    &nbsp;</td>
<td>
    <asp:TextBox ID="txtItemDescription" runat="server" Width="250px"></asp:TextBox>
    </td>
</tr>

<tr>
<td class="style1">System Impacted</td>
<td class="style1"></td>
<td class="style1">
    <asp:TextBox ID="txtSystemImpacted" runat="server" Width="250px" Wrap="False"></asp:TextBox>
    </td>
<td class="style1">
    </td>
<td>
    Order Number</td>
<td class="style1">
    </td>
<td class="style1">
    <asp:TextBox ID="txtOrderNumber" runat="server" Width="250px"></asp:TextBox>
    </td>
</tr>
<tr>
<td>Status</td>
<td></td>
<td>
    <asp:DropDownList ID="ddlStatus" runat="server" Width="253px" Height="22px">
        <asp:ListItem></asp:ListItem>
        <asp:ListItem>Submitted</asp:ListItem>
        <asp:ListItem>Open</asp:ListItem>
        <asp:ListItem>Close</asp:ListItem>
        <asp:ListItem>Reassign</asp:ListItem>
    </asp:DropDownList>
    </td>
<td>
    &nbsp;</td>
    <td>Business Segment</td>
<td>
    &nbsp;</td>
<td>
    <asp:DropDownList ID="ddlBusinessSegment" runat="server" Width="253px" Height="22px">
        <asp:ListItem></asp:ListItem>
        <asp:ListItem>Dated</asp:ListItem>
        <asp:ListItem>Office</asp:ListItem>
        <asp:ListItem>School</asp:ListItem>
        <asp:ListItem>Multiple</asp:ListItem>
    </asp:DropDownList>
    </td>
</tr>
<tr>
<td>Priority</td>
<td></td>
<td>
    <asp:DropDownList ID="ddlPriority" runat="server" Width="253px" Height="22px">
        <asp:ListItem></asp:ListItem>
        <asp:ListItem>Low</asp:ListItem>
        <asp:ListItem>Medium</asp:ListItem>
        <asp:ListItem>High</asp:ListItem>
<asp:ListItem>Urgent</asp:ListItem>
    </asp:DropDownList>
    </td>
<td>
    &nbsp;</td>
    <td>&nbsp;</td>
<td>
    &nbsp;</td>
<td>
    &nbsp;</td>
</tr>
<tr><td></td><td></td><td></td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr>
<tr><td class="style2"><asp:Button ID="btnSubmit" runat="server" Text="Submit" 
        onclick="btnSubmit_Click" /></td>
<td class="style2"></td>
<td class="style2"><asp:Button ID="btnClear" runat="server" Text="Clear" 
        onclick="btnClear_Click" /></td>
<td class="style2"></td>
<td class="style2"></td>
<td class="style2"></td>
<td class="style2"></td>
</tr>
</tbody>
</table>


3.  I attempted to create a user control host web part but was experiencing .Net version issues, so I decided to use SmartPart for SharePoint 2010 CodePlex solution to host the user control. This was much faster and worked great.









Click "open the tool pane". Then select your SmartPart. In this case its "usercontrols_issuetrackerlistssearch.ascx"


Then Check-in and Publish your page.


4.  I created a search results page and filtered the core results web part to only show results from the issue list. Configured the search box on the results page to go against the issue list as well.

                a) Create a FAST Search center site in the top level site.


                b) Create a new page under Pages section. I've named it as "IssueTrackerResults" in my case.

        
c) Edit the page and the edit “Search Core Results” web part.

                d) In ‘Results Query Options’ provide the list url in “Append Text To Query” section. Then Press OK. Check-In and Publish the page.

jQuery SPServices code to hide fields based on the login user

The below code works only for IE

<script language="javascript" type="text/javascript" src="../../SiteAssets/jquery-1.11.1.min.js"></script>
<script language="javascript" type="text/javascript" src="../../SiteAssets/jquery.SPServices-2013.01.js"></script>

<script language="javascript" type="text/javascript">
_spBodyOnLoadFunctionNames.push('Test');

function Test()
{
        //alert("Try now");
 
  jQuery().SPServices({
  operation: "GetGroupCollectionFromUser",
  userLoginName: jQuery().SPServices.SPGetCurrentUser(),
  async: false,
  completefunc: function(xData, Status) {
  var xml = xData.responseXML.xml; //Different in case of IE

   //If the current User does belong to the group "Visitors" and "Issue Functional Area"
    if (xml.search('Issue Functional Area') != -1)
     {
           //alert("No, User Doesn't Exists!");                 
           // jQuery("select[title=Status]").parent().parent().parent().hide();
          //or use: jQuery('td.ms-formlabel:contains("Status")').parent().hide();
         
             jQuery('nobr:contains("Status")').closest('tr').hide();
           //jQuery(".ms-formtable tbody > tr > td:contains('Status')").closest("tr").hide();
       } 
    }
 });


}</script>



Now the following code works for Google Chrome and Firefox
<script language="javascript" type="text/javascript" src="../../SiteAssets/jquery-1.11.1.min.js"></script>
<script language="javascript" type="text/javascript" src="../../SiteAssets/jquery.SPServices-2013.01.js"></script>

<script language="javascript" type="text/javascript">

_spBodyOnLoadFunctionNames.push('Test');

function Test()
{
                //alert("Try now");
 
  jQuery().SPServices({
  operation: "GetGroupCollectionFromUser",
  userLoginName: jQuery().SPServices.SPGetCurrentUser(),
  async: false,
  completefunc: function(xData, Status) {
  var xml = xData.responseText; //Different in case of Google Chrome and Firefox

   //If the current User does belong to the group "Visitors" and "Issue Functional Area"
    if (xml.search('Issue Functional Area') != -1)
     {
           //alert("No, User Doesn't Exists!");                  
           // jQuery("select[title=Status]").parent().parent().parent().hide();
          //or use: jQuery('td.ms-formlabel:contains("Status")').parent().hide();
                 
             jQuery('nobr:contains("Status")').closest('tr').hide();
                   //jQuery(".ms-formtable tbody > tr > td:contains('Status')").closest("tr").hide();
       } 
    }
 });

}

</script>

Tuesday, July 7, 2015

Adding PeoplePicker field using HTML, JavasScript in Content Editor WebPart

HTML Tag:

<tr id="mgr">
<td class="lbl">Manager:</td>
<td class="val">
<!--People Picker//-->
<div id="ppApp" style="width:350px">
<span id="ctl00_PlaceHolderMain_pe" editorOldValue="" RemoveText="Remove" value="" NoMatchesText="&lt;No Matching Names>" allowEmpty="1" MoreItemsText="More Names..." preferContentEditableDiv="true" showDataValidationErrorBorder="false" EEAfterCallbackClientScript="" inValidate="false" allowTypeIn="true" ShowEntityDisplayTextInTextBox="0"><input name="ctl00$PlaceHolderMain$pe$hiddenSpanData" type="hidden" id="ctl00_PlaceHolderMain_pe_hiddenSpanData" /><input name="ctl00$PlaceHolderMain$pe$OriginalEntities" type="hidden" id="ctl00_PlaceHolderMain_pe_OriginalEntities" value="&lt;Entities />" /><input name="ctl00$PlaceHolderMain$pe$HiddenEntityKey" type="hidden" id="ctl00_PlaceHolderMain_pe_HiddenEntityKey" /><input name="ctl00$PlaceHolderMain$pe$HiddenEntityDisplayText" type="hidden" id="ctl00_PlaceHolderMain_pe_HiddenEntityDisplayText" />
<table id="ctl00_PlaceHolderMain_pe_OuterTable" class="ms-usereditor" cellspacing="0" cellpadding="0" border="0" style="border-collapse:collapse;">
<tr valign="bottom">
<td valign="top" style="width:88%;">
<table cellpadding="0" cellspacing="0" border="0" style="width:100%;table-layout:fixed;">
<tr>
<td id="ctl00_PlaceHolderMain_pe_containerCell"><div id="ctl00_PlaceHolderMain_pe_upLevelDiv" tabindex="0" onfocusin="StoreOldValue('ctl00_PlaceHolderMain_pe');saveOldEntities('ctl00_PlaceHolderMain_pe');" onclick="onClickRw(true, true,event,'ctl00_PlaceHolderMain_pe');" onchange="updateControlValue('ctl00_PlaceHolderMain_pe');" onfocusout="if(typeof(ExternalCustomControlCallback)=='function'){ if(ShouldCallCustomCallBack('ctl00_PlaceHolderMain_pe',event)){if(!ValidatePickerControl('ctl00_PlaceHolderMain_pe')){ShowValidationError();return false;}else {ExternalCustomControlCallback('ctl00_PlaceHolderMain_pe');}}}" onPaste="dopaste('ctl00_PlaceHolderMain_pe',event);" AutoPostBack="0" rows="1" onDragStart="canEvt(event);" onkeyup="return onKeyUpRw('ctl00_PlaceHolderMain_pe');" onCopy="docopy('ctl00_PlaceHolderMain_pe',event);" title="People Picker" onkeydown="return onKeyDownRw('ctl00_PlaceHolderMain_pe', 3, true, event);" aria-multiline="true" contentEditable="false" aria-haspopup="true" class="ms-inputuserfield" style="word-wrap: break-word;overflow-x: hidden; background-color: window; color: windowtext;border:1px solid #999" preferContentEditableDiv="true" name="upLevelDiv" role="textbox"></div><textarea name="ctl00$PlaceHolderMain$pe$downlevelTextBox" rows="1" cols="20" id="ctl00_PlaceHolderMain_pe_downlevelTextBox" class="ms-inputuserfield" AutoPostBack="0" onkeyup="return onKeyUpRw('ctl00_PlaceHolderMain_pe');" title="People Picker" onfocus="StoreOldValue('ctl00_PlaceHolderMain_pe');saveOldEntities('ctl00_PlaceHolderMain_pe');" onblur="if(typeof(ExternalCustomControlCallback)=='function'){ if(ShouldCallCustomCallBack('ctl00_PlaceHolderMain_pe',event)){if(!ValidatePickerControl('ctl00_PlaceHolderMain_pe')){ShowValidationError();return false;}else {ExternalCustomControlCallback('ctl00_PlaceHolderMain_pe');}}}" onkeydown="return onKeyDownRw('ctl00_PlaceHolderMain_pe', 3, true, event);" renderAsContentEditableDiv="true" onchange="updateControlValue('ctl00_PlaceHolderMain_pe');" style="width:100%;display: none;position: absolute; "></textarea></td>
</tr>
</table>
</td>
<td align="center" valign="top" nowrap="true" style="padding-left:5px;padding-right:5px;"><!--<a id="ctl00_PlaceHolderMain_pe_checkNames" title="Check Names" onclick=" if(!ValidatePickerControl('ctl00_PlaceHolderMain_pe')){ ShowValidationError(); return false;} var arg=getUplevel('ctl00_PlaceHolderMain_pe'); var ctx='ctl00_PlaceHolderMain_pe';EntityEditorSetWaitCursor(ctx);WebForm_DoCallback('ctl00$PlaceHolderMain$pe',arg,EntityEditorHandleCheckNameResult,ctx,EntityEditorHandleCheckNameError,true);return false;" href="javascript:"><img title="Check Names" src="/_layouts/images/checknames.png" alt="Check Names" style="border-width:0px;" /></a>//-->&#160;<a id="ctl00_PlaceHolderMain_pe_browse" title="Browse" onclick="__Dialog__ctl00_PlaceHolderMain_pe(); return false;" href="javascript:"><img title="Browse" src="/_layouts/images/addressbook.gif" alt="Browse" style="border-width:0px;" /></a> (click icon to browse for user)</td>
</tr>
<tr>
<td colspan="3"><span id="ctl00_PlaceHolderMain_pe_errorLabel" class="ms-error"></span></td>
</tr>
</table>
</span>
</div>

JavaScript code:
//PEOPLE PICKER CODE
    document.write('<script type="text/javascript" src="/_layouts/entityeditor.js?rev=1%2Fj%2Ba5PO0xZXnRjXxVHOkg%3D%3D"></' + 'script>');
    function CallbackWrapperctl00_PlaceHolderMain_pe(xml) {
        if (xml == null)
            return;

        var ctx = 'ctl00_PlaceHolderMain_pe';
        EntityEditorCallback(xml, ctx);
        // run the custom script
        RunCustomScriptSetForPickerControl(ctx);
    }

    function __Dialog__ctl00_PlaceHolderMain_pe(defaultSearch) {
        if (defaultSearch == undefined)
            defaultSearch = '';
        var sDialogUrl = '\u002fProcesses\u002fGPP\u002f_layouts\u002fPicker.aspx?MultiSelect=False\u0026CustomProperty=User\u00253B\u00253B15\u00253B\u00253B\u00253BFalse\u0026DialogTitle=Select\u002520People\u0026DialogImage=\u00252F\u00255Flayouts\u00252Fimages\u00252Fppeople\u00252Egif\u0026PickerDialogType=Microsoft\u00252ESharePoint\u00252EWebControls\u00252EPeoplePickerDialog\u00252C\u002520Microsoft\u00252ESharePoint\u00252C\u002520Version\u00253D14\u00252E0\u00252E0\u00252E0\u00252C\u002520Culture\u00253Dneutral\u00252C\u002520PublicKeyToken\u00253D71e9bce111e9429c\u0026ForceClaims=False\u0026DisableClaims=False\u0026EnabledClaimProviders=\u0026EntitySeparator=\u00253B\u0025EF\u0025BC\u00259B\u0025EF\u0025B9\u002594\u0025EF\u0025B8\u002594\u0025E2\u00258D\u0025AE\u0025E2\u002581\u00258F\u0025E1\u00258D\u0025A4\u0025D8\u00259B';
        sDialogUrl = sDialogUrl + '&DefaultSearch=' + escapeProperly(defaultSearch);
        var sFeatures = 'resizable: yes; status: no; scroll: no; help: no; center: yes; dialogWidth : 575px; dialogHeight : 500px; zoominherit : 1';

        var rv = commonShowModalDialog(sDialogUrl, sFeatures, CallbackWrapperctl00_PlaceHolderMain_pe);
    }

    var currentEntityEditorXml = '\u003cEntities Append=\u0022False\u0022 Error=\u0022\u0022 DoEncodeErrorMessage=\u0022True\u0022 Separator=\u0022;\u0022 MaxHeight=\u00223\u0022 \u002f\u003e';
    var currentEntityEditorContextId = 'ctl00_PlaceHolderMain_pe';
    EntityEditorCallback(currentEntityEditorXml, currentEntityEditorContextId, true); PickerAdjustHeight('ctl00_PlaceHolderMain_pe', 3);

    var EntityEditor_ItemTooLong = 'Item cannot be more than 256 characters.'; var L_PleaseWait_TEXT = 'Searching...';
    var EntityEditor_UseContentEditableControl = true;


    //END: PEOPLE PICKER CODE