2011-07-27

Taking off Anchor Tag in Drop Down List

A while ago, I encountered a issue about lookup column in a SharePoint list.
If lookups items are over 20 items, lookup column changes the visual.


Under 20 items:



Over 20 items (You can modify in the drop down list.) : 



I found the solution not to change the visual if lookups are over 20 items in bellow blog post.

Sharepoint lookups over 20 items solution?
(The solution is using DVDropDownList instead of FormField.)


I could resolve my issue referencing the post, but I encountered a new problem. The problem is that a lookup column is extended due to anchor tag in EditForm.aspx.



The resolution is using xlst to take off Anchor Tag.


The code is here. I add xslt code and fix SharePoint:DVDropDownList element.

<td width="400px" valign="top" class="ms-formbody">
  <xsl:variable name="lookup" select="substring-after(substring-before(/dsQueryResponse/Rows/Row/@test, '&lt;/a&gt;'), '&quot;&gt;')" />
  <SharePoint:DVDropDownList runat="server" id="ff4{$Pos}" __designer:bind="{ddwrt:DataBind('u',concat('ff4',$Pos),'SelectedValue','SelectedIndexChanged','ID',ddwrt:EscapeDelims(string(@ID)),'@test')}" selectedvalue="{$lookup}" datasourceid="spdatasource1" datatextfield="Title" datavaluefield="ID" AppendDataBoundItems="True" CausesValidation="True"/>


Also see substring-before function and substring-after function.


2011-07-24

How to Get Workflow History Programmatically

I introduced how to check workflow status in the last post.
Today, I introduce how to get workflow history from Workflow History List. You can find Workflow History List's URL by using SharePoint Designer.



Workflow History List is here. There are some columns associated with workflow.



The code is here. The code enables to get all workflow status associated each item in SharePoint site. You can modify the code to get a specific list's workflow status. I identify workflow history list item using "Workflow History Parent Instance" column and "Primary Item ID" column.(see "if" block.)

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;

// This is Console Application //

SPSite site = new SPSite("http://sharepoint-site");
SPWeb web = site.OpenWeb();

foreach (SPList list in web.Lists)
{
    foreach(SPListItem item in list.Items)
    {
        foreach (SPWorkflow workflow in item.Workflows)
        {
            foreach (SPListItem worflowHistoryItem in workflow.HistoryList.Items)
            {
                if (("{" + workflow.InstanceId.ToString() + "}" == worflowHistoryItem["Workflow History Parent Instance"].ToString()) 
                    && (item.ID.ToString() == worflowHistoryItem["Primary Item ID"].ToString()))
                {
                    Console.WriteLine(item.Name + " : " + worflowHistoryItem["Description"]);
                }
            }
        }
    }
}

2011-06-26

How to Check Workflow Status programmatically

Today I'll show checking all workflow statuses in SharePoint site programmatically. Sometimes you may want to check workflow statuses are error or not.

You need workflow status name (list column) when you get a item's workflow status. But you can't get workflow status name from SPWorkflow properties directly. You need to use SPWorkflow.AssociationId property and SPList.WorkflowAssociations property to get workflow status.


The sample code is here.

using System;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Workflow;

// This is Console Application //

SPSite site = new SPSite("http://sharepoint-site");
SPWeb web = site.OpenWeb();

foreach (SPList list in web.Lists)
{
    foreach (SPListItem item in list.Items)
    {
        foreach (SPWorkflow workflow in item.Workflows)
        {
            try
            {
                Console.WriteLine("item url : " + item.Url);
                Console.WriteLine("workflow name : " + list.WorkflowAssociations[workflow.AssociationId].Name);
                Console.WriteLine("workflow status : " + item[list.WorkflowAssociations[workflow.AssociationId].Name]);
                Console.WriteLine();
            }
            catch (ArgumentException)
            {
                //ArgumentException is throwed if the workflow is not exist in the list column. 
                Console.WriteLine("Workflow name : {0} is already not exist in List title : {1}.", 
                    list.WorkflowAssociations[workflow.AssociationId].Name, list.Title);
            }
        }
    }
}

The result is like this :
item url : Lists/Announcement01/1_.000
workflow name : Approval01
workflow status : 2
Workflow status is displayed as a number. The workflow status number are related to SPWorkflowStatus Enumeration. For example, number 2 means "InProgress".

2011-06-17

How to Disable an Expiration Policy (Retention) on a List Using SharePoint Object Model

We usually use Expiration Policy (Retention) in Information Management Policy features. Expiration Policy enables to set expiration date for each item in a list. The item will be deleted when expiration date will come.





If you enable or disable Expiration Policy using SharePoint API, it is little bit complicated.
Expiration Policy including Information Management Policy features is associated list's ContentType. (not list of itself) 


You can see how to enable and create Expiration Policy in bellow blog post.

Using the SharePoint API to Configure an Expiration Policy on a Document Library


If you delete and disable Expiration Policy, please see bellow program code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.Office.RecordsManagement.InformationPolicy;

namespace ConsoleApplication3
{
    class Program
    {
        private const string expirationPolicyFeatureId = "Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration";

        static void Main(string[] args)
        {
            SPSite site = new SPSite("http://sp2010");
            SPWeb web = site.OpenWeb();

            SPList list = web.Lists["Annnounce03"];

            foreach (SPContentType contentType in list.ContentTypes)
            {
                Policy policy = Policy.GetPolicy(contentType);

                if (policy != null)
                {
                    //delete Expiration Policy on the List
                    policy.Items.Delete(expirationPolicyFeatureId);
                }
            }
        }
    }
}

Tips :
- You need to add Reference Microsoft.Office.Policy.dll from /14/ISAPI.
- Expiration Policy is defined as Microsoft.Office.RecordsManagement.PolicyFeatures.Expiration.

2011-06-11

How to Customize Default Approval Workflow (Part.2)

In Part. 1 blog post, I introduced how to add Person or Group TextBox as CC form in Change Request Task Form. Only adding CC form, It doesn't work. So, in this blog post, I introduce how to add logic in custom Approval workflow to use CC form.



The Steps are here.

  • In Approval - Copy05 Top, click "Edit Workflow" and click "Approval Workflow Task (en-US) Copy".


  • Click "Change the behavior of a single task".


  • Add "Set Workflow Variable" in "When a Task Completes" section's top.


  • Click "workflow variable" and click "Create a new variable..." from pulldown. Fill in arbitrary name and choose String Type. Press OK.


  • Click value and click fx. Fill bellow parameters.


  • Click "Current Task:Assigned To" in "When a Task is Pending".


  • Click icon besides CC. Select "Workflow Lookup for a User...". And Fill in bellow parameters.


  • Click OK and publish the workflow.

The steps were finished. Please confirm that you can get CC email when you run the workflow.

Tips:
In the steps, I created a workflow variable in "When a Task Completes" section to get CC form content. And I added the workflow variable as a CC address in "When a Task is Pending" section. The important point is that you can't directly get CC form content in "When a Task is Pending" section. When you fill in CC form and click Send in Change Request form of a workflow task, The workflow task is completed and new workflow task is created. CC form content is associated the completed task. So you need to get CC form content in "When a Task Completes" section.

2011-06-02

How to Customize Default Approval Workflow (Part.1)

I'm sorry it has been taken long time since previous blog post.
Today I'd like to introduce how to customize default approval workflow using only SharePoint Designer (with non code).
This is new feature in SharePoint 2010. In SharePoint 2007, we couldn't customize default approval workflow. So you needed to make new own workflow from zero base if you want to customize approval workflow.


I introduce these steps in two blog posts.



OK, I introduce Part1 first, add bellow Person or Group TextBox as CC in ChangeRequest in Task Form.




The Steps are here.

  • First create a copy of default Approval Workflow in SPD. Click Copy and Modify and create new copy of default Approval Workflow.


  • Click Approval Workflow Task.

  • Click New in Task Form Fields to create CC as Person or Group Field.


  • Fill in these TextBox, choose Person or Group in Information type, and click Next.



  • Click Finish.


  • Save and Publish the .Approval Workflow.
  • Back to Approval - Copy05 page. Click Approval Workflow Task in Form.


  • Task Form is opened in InfoPath 2010. Check the CC form which was created previous step. 

  • Select CC Row and copy it(Control + C). Delete CC Row from default form.

Tips : You can also add CC from Fields property menu. But you can't resolve names in CC by using Enter key if you drag & drop CC from Fields property menu to ChangeRequest form. So you had better use the copy from default form.

  • Click Page Design Tab and choose ChangeRequest from View pulldown.

  • Add new Row and paste CC Row (Control + V) in ChangeRequest form.


  • Save the InfoPath form to local and Publish it.


Steps were finished.
I'll introduce how to use the CC in next blog post.


2011-05-05

Setting Default Value in List's NewForm.aspx Using Javascript

I introduced how to get column data on each list items row in a Xslt List View WebPart in the previous blog post.



Today, I'd like to introduce how to create "links" by using column data and enable to copy the column data to textboxes. When the link is clicked and opened, another list's NewForm.aspx page will appear.


The scenario is like this :


  • If you click the link on each list items


  • "Title" value and "Categories" value of each list items are copied in another list's NewForm.aspx textboxes.   


In inside I created "Notice the Announce" link with URL's parameters which has "Title" value and "Categories" value.

http://sp2010/Lists/Notice/NewForm.aspx?title=Let's go to drink with us !!&category=invitation

And I copied URL's parameters to textboxes on NewForm.aspx using Javascript.



So, I'll show you steps ! Please check its !

  • Open AllItems.aspx and enable "Advanced Mode" and display xslt view. (see previous post.
  • Drag & Drop the ASP.NET HyperLink in a column.


  • You can check if the code is added in code view and design view.



  • Create a link in asp:HyperLink tag using NavigateURL property and change link name from "HyperLink" to "Notice the Announce".  (also see previous post.)

 http://sp2010/Lists/Notice/NewForm.aspx?title=&category=
Notice the Announce



  • Open another list's NewForm.aspx of the link target and enable "Advanced Mode".
  • Add Javascript code under the asp:content tag.





////////


The Javascript code details :
First, I added column data from URL's parameters to Array class instance.
Second, I made "copyColumnData" function and added column data from Array class instance to textboxes. "aspnetForm" means the name property in Form tag in html. "ctl00_m_g_f3ae55fa_9a6e_4277_b7b3_e011e50d2977_ctl00_ctl05_ctl03_ctl00_ctl00_ctl04_ctl00_ctl00_TextField" means the id property in its textbox's input tag in html. You can check it in NewForm.aspx html source.




Third, I added "copyColumnData" function as a listener in window.attachEvent method. "onload" means  window.attachEvent method is called after page load is finished.


  • Steps are done ! Save aspx pages and check the motion !



I see bellow blog post by reference. It's very understandable.
Passing default values to a SharePoint list's NewForm.aspx page.




I usually go to cafe on a weekend. I can concentrate a few hours.


2011-04-30

How To Get Column Data On Each List Items row in a Xslt List View WebPart

In SharePoint 2007, We can get all column data bellow xslt code.
This sample is getting "Title" column value in "Modified" column.


Also we can get same result bellow code.


The Bellow image is result.



In SharePoint 2010, we cannot use the above code. We should use bellow code.



The Bellow image is result.


Then, I introduce how to add this code easily in SharePoint Designer.


  • Open AllItems.aspx or other new view page in SharePoint Designer.
  • Click "Advanced Mode" in Home tab to enable to edit entire page.



  • Click List View Web Part in Design View.

  • Click "Customize XSLT" - "Customize Entire View" in Design Tab. 



  • Drag & Drop "Title" from Data Source Detail to Xslt List View Web Part.

  • You can check the code in Code View.


After cherry blossoms, we can see a lot of field mustard !


2011-04-19

ItemAdded Event Sometimes Cannot Get AfterProperties

-ed Event such as "ItemAdded" method sometimes cannot get AfterProperties which is added by Document Parser from a list item. I heard this from one of my colleagues and I haven't reproduced it yet.
Document Parser enables to binding the document properties to list item's columns. Here is the sample :


  • Click New Document.




  • Fill in the form and click Save.
  • You can see the form data were binded to list item's columns.



We usually write event handler code which gets list item's column data when an item is added. But sometimes we cannot get item's column data by using AfterProperties.
This is because -ed event (ItemAdded) runs asynchronously. That means -ed event and document parser which add data to column run different threads. In this case, what we need to do is adding Thread.Sleep in -ed event code. Thread.Sleep is specified in milliseconds unit. 
 Here is the sample :

public override void ItemAdded(SPItemEventProperties properties)
{
    Thread.Sleep(100);
    string name = (string)properties.AfterProperties["Name"];
    string title = (string)properties.AfterProperties["Title0"];
    string discription = (string)properties.AfterProperties["Discription"];
    SPDiagnosticsService.Local.WriteTrace(0, new SPDiagnosticsCategory("ItemAdded", TraceSeverity.Unexpected, EventSeverity.Error), TraceSeverity.Unexpected, "ItemAdded" + " " + name + " " + title + " " + discription, "ItemAdded" + " " + name + " " + title + " " + discription);
}



I love Terje Sorgjerd's creations. They are my favorites. So beautiful, so creative. I'll share his another creation.




2011-04-16

Using the SharePoint 2010 Modal Dialog in Custom Aspx Page

SharePoint 2010 provides a new dialog framework using Client OM (javascript).
You can see the following dialog when you click an item from the list.


Modal dialog is provided by SP.UI.ModalDialog class.
Today, I'd like to introduce how to create a link to show modal dialog in a custom aspx page.
The steps are here.


  • Create Empty SharePoint Project.


  • Add new Application page in the new project.


  • Open new Application page, and add HyperLink tag in "PlaceHolderMain".

    HyperLink


  • Open code view of new Application page, and Write the code bellow.

This code indicates : 
  1. Get workflow task item's URL.
  2. Register modal dialog's script by using ScriptManager class.
  3. Bind javascript method for task url link.
StringBuilder taskUrl = new StringBuilder();

        protected void Page_Load(object sender, EventArgs e)
        {
            SPWeb web = SPContext.Current.Web;
            SPList list = web.Lists["Announcements"];

            foreach (SPListItem item in list.Items)
            {
                if (item.Workflows != null)
                {
                    foreach (SPWorkflow workflow in item.Workflows)
                    {
                        if (workflow.Tasks != null)
                        {
                            foreach (SPListItem task in workflow.Tasks)
                            {
                                //create task item url.
                                taskUrl.Append("http://sharepoint/_layouts/WrkTaskIP.aspx?List=");
                                taskUrl.Append(workflow.TaskListId);
                                taskUrl.Append("&ID=" + task.ID + "&IsDlg=1&Web=");
                                taskUrl.Append(web.ID);
                            }
                        }
                    }
                }
            }
            
            //make modal dialog script.
            string script =
                @"
    var modalDialog;
    function ShowDialogTest() {
        var options = {
            url: '" + taskUrl.ToString() + @"',
            tite: 'Workflow Task',
            allowMaximize: false,
            showClose: false,
            width: 800,
            height: 600 };
        modalDialog = SP.UI.ModalDialog.showModalDialog(options);
    }";
            //register the script.
            ScriptManager.RegisterStartupScript(this, this.GetType(), ClientID, script, true);
            //bind the script for hyperlink.
            HyperLink1.NavigateUrl = "javascript:ShowDialogTest()";
        }

The code is very simple. If there are more than two task items, the code doesn't work.


  • Deploy and access the new application page.


If you create Application page in SharePoint Empty Project, the aspx page is deployed in "_layouts" and master page tag is attached automatically. This is very nice function !! 
Sample url is here. "ShowModalDialog" is the project name.

http://sharepoint/_layouts/ShowModalDialog/ApplicationPage1.aspx


  • Click "HyperLink" link. Modal Dialog is displayed !!



Tips :

I also created an application page in ASP.NET Web Application project. But the code didn't work even after I added the script reference. 



I got "'Type' is undefined (sp.js)" error when I clicked hyperlink to display modal dialog. I can't understand why the error appears.
I'm trying to find out why it happens.




I found tremendously beautiful movie in Vimeo !!
The movie was recorded on a mountain in Spain.