Wednesday, November 4, 2015

SharePoint Blogs: List view issues with lookup and workflow columns

SharePoint Blogs: List view issues with lookup and workflow columns: Hi, I found an issue in my project when the number of lookup and workflow columns exceeded the limit. Please see below. I reduced t...

List view issues with lookup and workflow columns

Hi,

I found an issue in my project when the number of lookup and workflow columns exceeded the limit.
Please see below.


I reduced the no. of columns in the list view and afterwards it worked fine. The list view was displaying the columns without the above error.

Thanks,
Kunal

Wednesday, October 14, 2015

Monday, October 12, 2015

Footer links web part

Hi Folks,

I contributed to a reusable component for my team's contribution project. Using ecma script, we are fetching data from SharePoint list and displaying it to Script editor web part. We did some sorting/filtering using Caml query.

List Settings:


Output:

FooterTest.aspx
more > is navigating to NavigatePage.aspx.
NavigatePage.aspx


Common CSS Used for "FooterTest.aspx" and "NavigatePage.aspx":
<style>
.outerDiv
{
       width:1100px;
       margin-top:10px;
       border-top:1px solid #ccc;
       padding:10px 0 0;
       clear:both;
}
.col {  
         float: left;
         padding: 30px 0 0 35px;
  width: 310px
}
.col li{
  text-decoration:none;
}

.col ul
{
  float:left;
  list-style: none;
  margin: 0;
  padding: 0;
  border-top:1px solid #0B0719;
}
.col li
{
  border-bottom: 1px dotted #BDBDBD;  
  float: left;
  height: 35px;
  margin: 3px 0;
  padding: 0;
  width: 310px;
}
.col li:last-child
{
    border:none;
}
.col li a
{    
  color: black;
  display: block;
  float: left;
         font: normal 12px Arial;
  padding: 10px 0 0 19px;
  text-decoration: none;
}
</style>





Ecma Script Used for "FooterTest.aspx"
1   <script type="text/javascript" src="../../SiteAssets/jquery-1.11.1.js"></script>
<script type="text/javascript" src="../../SiteAssets/jquery-1.11.1.min.js"></script>
<script language="javascript" type="text/javascript">
    var clientContext;
    var website;
    var list;
    var items;
    var html = '<div class="col"><ul>';
    var index = 0;
    var lIndex = 0;
    // Make sure the SharePoint script file 'sp.js' is loaded before your
    // code runs.
    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', sharePointReady);

    // Create an instance of the current context.
    function sharePointReady() {
        clientContext = SP.ClientContext.get_current();
        website = clientContext.get_web();
        list = website.get_lists().getByTitle('TestFooter');
        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml('<View><Query><Where><And><Eq><FieldRef Name=\'IsActive\'/>' +
        '<Value Type=\'Boolean\'>1</Value></Eq><IsNotNull><FieldRef Name=\'Url\'/></IsNotNull></And></Where><OrderBy><FieldRef Name=\'DisplayOrder\' Ascending=\'TRUE\' /></OrderBy></Query></View>');
         items = list.getItems(camlQuery);
        clientContext.load(items);      
        clientContext.executeQueryAsync(onRequestSucceeded, onRequestFailed);
    }
    function onRequestSucceeded() {
        var itemCount = items.get_count();
        console.log(itemCount);
        var enumerator = items.getEnumerator();
        while (enumerator.moveNext()) {           
            var listItem = enumerator.get_current();
            var rotatorTitle = listItem.get_item('Title');
            var rotatorUrl = listItem.get_item("Url");
            var rotatorIsActive = listItem.get_item('IsActive');
            GetData(rotatorTitle, rotatorUrl);
        }      
        $("#siteOwner").append(html);       
    }
    function onRequestFailed(sender, args) {
        alert('Error: ' + args.get_message());
    }

    function GetData(rotatorTitle, rotatorUrl) {
        if (lIndex < 16) {
                if (index <= 4) {
                    html += "<li><a href=" + rotatorUrl + ">" + rotatorTitle + "</a></li>";
                    index++;
                    lIndex++;
                }
                else if (lIndex == 15) {                  
                    html += '<li><a href="https://accobrands.sharepoint.com/ITCompliance/Pages/NavigatePage.aspx"> more > </a></li></ul></div>';
                    lIndex++;
                }
                else {
                    index = 0;
                    html += '<li><a href=' + rotatorUrl + '>' + rotatorTitle + '</a></li></ul></div><div class="col"><ul>';
                }
            }
            else {
                //No action needed
            }
       
    }
</script>
<div id="siteOwner" class="outerDiv">

</div>





Ecma Script Used for "NavigatePage.aspx"
<script type="text/javascript" src="../../SiteAssets/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="../../SiteAssets/jquery-1.11.1.min.js"></script>
<script language="javascript" type="text/javascript">
    var clientContext;
    var website;
    var list;
    var items;
    var html = '<div class="col"><ul>';
    var index = 0;
    var lIndex = 0;
    var mIndex = 0;
    // Make sure the SharePoint script file 'sp.js' is loaded before your
    // code runs.
    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', sharePointReady);

    // Create an instance of the current context.
    function sharePointReady() {
        clientContext = SP.ClientContext.get_current();
        website = clientContext.get_web();
        list = website.get_lists().getByTitle('TestFooter');
        var camlQuery = new SP.CamlQuery();
        camlQuery.set_viewXml('<View><Query><Where><And><Eq><FieldRef Name=\'IsActive\'/>' +
        '<Value Type=\'Boolean\'>1</Value></Eq><IsNotNull><FieldRef Name=\'Url\'/></IsNotNull></And></Where><OrderBy><FieldRef Name=\'DisplayOrder\' Ascending=\'TRUE\' /></OrderBy></Query></View>');
        items = list.getItems(camlQuery);
        clientContext.load(items);
        //clientContext.load(website);
        clientContext.executeQueryAsync(onRequestSucceeded, onRequestFailed);
    }
    function onRequestSucceeded() {
        var itemCount = items.get_count();
        console.log(itemCount);
        mIndex = itemCount - 4;
       
        var enumerator = items.getEnumerator();
        while (enumerator.moveNext()) {
            var listItem = enumerator.get_current();
            var rotatorTitle = listItem.get_item('Title');
            var rotatorUrl = listItem.get_item("Url");
            var rotatorIsActive = listItem.get_item('IsActive');
            GetData(rotatorTitle, rotatorUrl);
        }
        $("#siteOwner").append(html);
        //alert(website.get_url());
    }
    function onRequestFailed(sender, args) {
        alert('Error: ' + args.get_message());
    }

    function GetData(rotatorTitle, rotatorUrl) {       
            if (index <= 4) {
                html += "<li><a href=" + rotatorUrl + ">" + rotatorTitle + "</a></li>";
                index++;
                lIndex++;
            }
            else if (lIndex == mIndex) {
                html += '<li><a href=' + rotatorUrl + '>' + rotatorTitle + '</a></li></ul></div>';
            }           
            else {
                index = 0;
                html += '<li><a href=' + rotatorUrl + '>' + rotatorTitle + '</a></li></ul></div><div class="col"><ul>';
            }
    }
</script>
<div id="siteOwner" class="outerDiv">
   
</div>

Display list data in jQuery tables without using Data View web part

Hi folks,

I did a small POC in my project to fetch data using REST API and feed the results into jQuery data tables. Using this we can apply sorting, paging, filtering to the results received.
Please check the code below.

<script type="text/javascript" charset="utf8" src="../SiteAssets/Scripts/jquery-1.11.3.min.js"></script>
<script type="text/javascript" charset="utf8" src="//cdn.datatables.net/1.10.7/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.datatables.net/1.10.7/css/jquery.dataTables.min.css">

Job Status: <input type="text" id="Status">

<input type="button" value="Get Records" onclick="LoadRecords($('#Status').val());" >

<table width="100%" cellpadding="0" cellspacing="0" border="0" class="display" id="example">
<thead>
<th>Job Name</th>
<th>Job Status</th>
<th>Source</th>
<th>Client Number</th>
</thead>
</table>

<script type="text/javascript">
console.log(_spPageContextInfo.webAbsoluteUrl);
function LoadRecords(state)
{
var call = $.ajax({
url: _spPageContextInfo.webAbsoluteUrl + "/_api/Web/Lists/GetByTitle('SAP Batch Jobs')/items?$select=Job_x0020_Name,Title,Source,Client_x0020_Number&$filter=(Title eq '"+state+"')&$top=5000",
type: "GET",
dataType: "json",
headers: {
Accept: "application/json;odata=verbose"
}
});
call.done(function (data,textStatus, jqXHR){

$('#example').dataTable({
"bDestroy": true,
"bProcessing": true,
"aaData": data.d.results,
"aoColumns": [
{ "mData": "Job_x0020_Name" },
{ "mData": "Title" },
{ "mData": "Source" },
{ "mData": "Client_x0020_Number" }
]
});

});
call.fail(function (jqXHR,textStatus,errorThrown){
alert("Error retrieving Tasks: " + jqXHR.responseText);
});
}
</script>

For complete details of jQuery plugin, please check the below link
http://summit7systems.com/who-needs-a-data-view-web-part-sharepoint-rest-and-datatables-net/

Monday, August 31, 2015

SharePoint Designer 2013 Workflows: Best Practices to follow

Rules to follow while working on SharePoint Designer workflows. It can prevent you to recreate the workflow from scratch once the workflow became corrupt.
(Can also refer 'http://blog.eastridge.net/sharepoint-designer-2013-worklows-copy-paste-and-delete-best-practices')

  • Never delete a stage before deleting all actions and conditions within that stage first.
  • Never delete a stage if another stage is transitioning to it. Make sure to modify the transition portion of the other stage first.
  • Never copy and paste a stage. Create the stage manually and then copy and paste the actions into the new stage.
  • Never delete an "IF" or "ELSE" without first deleting all the actions in the condition first.
  • Never copy and paste an "IF" or "ELSE" block. Create the "IF" and "ELSE" conditions manually and then copy and paste the actions into the condition.
  • Take backups of your workflow often using the "Save as Template" feature described here, http://msdn.microsoft.com/en-us/library/office/jj819316(v=office.15).aspx. This will allow you to rule back to the last backup if your workflow did get corrupted.

Wednesday, August 5, 2015

Navigate SharePoint List Save button to different page.

Hi,

We got a small task to navigate SharePoint list form to different page after click of "Save" button.

Please follow the below steps.
1. Open the SharePoint list form in designer.

2. Search for the below tag. Comment it.
<SharePoint:SaveButton runat="server" ControlMode="New" id="savebutton1"/>
As we had task on custom NewForm.aspx so we applied in this page.

3. Add the below code for new Save button.
<input type="button" value="Save" name="btnSave" onclick="javascript: {ddwrt:GenFireServerEvent('__commit;__redirect={https://accobrands.sharepoint.com/sites/ITRequestTool/Pages/MyRequests.aspx}')}" />

4. Save the form and Open it in browser. You will get the proper navigation as expected.

You can also prefer the below link.
http://beginnerssharepointtips.blogspot.in/2014/07/redirecting-to-page-from-list-form.html 


Thanks,

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.