May 12

I've been searching the web for how to populate a drop down list with all available SharePoint users and although I did manage to find things, it wasn't exactly what I was looking for. The solutions I found did not list all users and it lists groups in there too (which I did not want). Anyway, after searching some more, I found something called a Contact Selector for InfoPath. The Contact Selector is an ActiveX control which is installed with InfoPath 2007. There are 2 main steps to get the Contact Selector to work however there is a third step if you plan on using the Contact Selector more than once on a single form (which I had to do in my case).

Step 1 - Add the Contact Selector to InfoPath 2007

  1. In Office InfoPath 2007, on the Design Tasks pane, click Controls.
  2. On the Controls pane, click Add or Remove Custom Controls.
  3. In the Add or Remove Custom Controls dialog box, click Add.
  4. The Add Custom Control Wizard appears.
  5. Under Select a Control Type, select ActiveX Control. Click Next.
  6. In the list of ActiveX controls, select Contact Selector. Click Next.
  7. Under Specify Installation Options, select Don’t include in a .cab file. Click Next.
  8. Under Binding property, select value. Click Next.
  9. For Field or group type, select Field or group (any data type). Click Finish. Click Close. Click OK.

Step 2 - Configuring the Contact Selector

  1. Open your form in Design mode in InfoPath 2007.
  2. Select View-Design Tasks from the menu.
  3. Click the Data Source link.
  4. Right-click in the section where you want to add the control and select "Add…". Specify a name. Set the Type option to Group. Do not check the repeating check box. Click OK to save.
  5. Right-click the new group added in the previous step and select "Add…". For the name, type in Person. Set the Type option to Group. Check the repeating check box. Click OK to save.
  6. Right-click on the Person group and select "Add…". For the name, type in DisplayName. Click OK to save.
  7. Right-click on the Person group and select "Add…". For the name, type in AccountId. Click OK to save.
  8. Right-click on the Person group and select "Add…". For the name, type in AccountType. Click OK to save.
  9. Drag the group created in step #5 to the location in your form where you want the Contact Selector to be displayed. A popup menu will display – select Contact Selector.
  10. Open a text editor (eg. Notepad).
  11. Type in the following and replace yourservername: <Context siteUrl="http://<yourservername>"/>
  12. Save the file as Context.xml.
  13. In InfoPath, select Tools-Data Connections from the menu.
  14. Click the Add button, check the "Create a new connection to" option, and check the "Receive data" option. Click the Next button.
  15. Check the "Xml document" option. Click the Next button.
  16. Browse to the location where you saved the Context.xml file and open it. Click the Next button.
  17. Check the "Include the data as a resource file in the form template or template part" option. Click the Next button.
  18. Enter the name Context. Click the Finish button.
  19. Save the form.
  20. Publish the form.

Now if you try adding a second Contact Selector and publish the form, you'll get an error.

To be able to use more than 1 Contact Selector, you need to complete Step 3.

Step 3 - Using multiple Contact Selectors in a single form

  1. Complete Step 2.4 above for every contact selector you want to add.
  2. Right click on the Person group and click on "Reference"
  3. A window should pop up. Select the group that you created above in Step 3.1
  4. Drag and drop the group to the location where you want the Contact Selector to appear on your form. When the popup menu is displayed, select Contact Selector

And there you have it. You now have the ability to select users from SharePoint. From here, you can create workflows that involve these selected users from SharePoint Designer by setting these fields as being available in SharePoint sites (when publishing), but that's another story.

May 1
Sorted List with multiple DateTime keys
Posted by Wei in C# on 05 1st, 2009| | No Comments »

What I needed to do was to sort a list of dates and corresponding names in order of date. Problem was that sometimes the dates duplicate and as a result, a standard SortedList would crash (since keys need to be unique). Anyway, here's a workaround to that problem. We create a new class for the project as follows:

    public class ComparableDateTime : IComparable
    {
        private DateTime mDT;

        public int CompareTo(object obj)
        {
            if (mDT.Ticks < ((ComparableDateTime)obj).mDT.Ticks) return -1;
            return 1;
        }

        public ComparableDateTime(DateTime myDate)
        {
            mDT = myDate;
        }
    }

Then once we have the class, we can declare a SortedList with that class:

using System.Collections.Generic;

SortedList<ComparableDateTime, string> mySortedList = new SortedList<ComparableDateTime,string>();

DateTime someDate = DateTime.Today;

mySortedList.Add(new ComparableDateTime(someDate,"someString");
mySortedList.Add(new ComparableDateTime(someDate,"someString2");

for (int i = 0; i < mySortedList.Count; i++)
{
    writer.Write(mySortedList.Values[i].ToString());
}

Apr 21

Insert a Content Editor Web Part and edit the source code. Add the following to it:

<input type="button" OnClick="javascript:void(PrintWebPart())" value="Print Web Part">

<script language="JavaScript">
//Controls which Web Part or zone to print
var WebPartElementID = "<WebPartElementID>";

//Function to print Web Part
function PrintWebPart()
{
 var bolWebPartFound = false;
 if (document.getElementById != null)
 {
  //Create html to print in new window
  var PrintingHTML = '<HTML>\n<HEAD>\n';
  //Take data from Head Tag
  if (document.getElementsByTagName != null)
   {
   var HeadData= document.getElementsByTagName("HEAD");
   if (HeadData.length > 0)
    PrintingHTML += HeadData[0].innerHTML;
   }
  PrintingHTML += '\n</HEAD>\n<BODY>\n';
  var WebPartData = document.getElementById(WebPartElementID);
  if (WebPartData != null)
  {
   PrintingHTML += WebPartData.innerHTML;
   bolWebPartFound = true;
  }
  else
  {
   bolWebPartFound = false;
   alert ('Cannot Find Web Part');
  }
 }
 PrintingHTML += '\n</BODY>\n</HTML>';
 //Open new window to print
 if (bolWebPartFound)
 {
  var PrintingWindow = window.open("","PrintWebPart", "toolbar,width=800,height=600,scrollbars,resizable,menubar");
  PrintingWindow.document.open();
  PrintingWindow.document.write(PrintingHTML);
  // Open Print Window
  PrintingWindow.print();
 }
}
</script>

Once you have done the above, you need to find the web part id of the web part you want to print when this button is clicked.

To do that, you view the source of the page and look for the web part title corresponding to the web part. It looks something like this:

<div WebPartID="0e77b913-99e6-402c-8558-cdd5a2100eb2" HasPers="false" id="WebPartctl00_m_g_0e77b913_99e6_402c_8558_cdd5a2100eb2" width="100%" class="ms-WPBody" allowDelete="false" style="" >

The id that you're interested in to replace <WebPartElementID> in the javascript above is highlighted.

Once it's all there, click on the button and a window will pop open that contains only the contents of the web part. Feel free to print.

Apr 20

Here's a little function that I wrote to return you the Monday's date for this week, next week, etc...

GetNextWeekDates(DayOfWeek.Monday, 0);

Change DayOfWeek.Monday to any day of the week and it will return you the next date on that particular day. The integer represents which date you want to return. 0 means that you want this week's Monday. Set it to 1, then it's the coming Monday. Set it to 2 and you get the date of the Monday after.

        private DateTime GetNextWeekDates(DayOfWeek targetDay, int weekNumber)
        {
            int daysDifference = (int)targetDay - (int)DateTime.Today.DayOfWeek;

            if (daysDifference == 0) weekNumber++;

            DateTime returnDate;

            if (daysDifference < 0)
            {
                returnDate = DateTime.Today.AddDays(daysDifference + 7 + ((weekNumber - 1) * 7));
            }
            else
            {
                returnDate = DateTime.Today.AddDays(daysDifference + ((weekNumber - 1) * 7));
            }

            return returnDate;
        }

Apr 6

In this post, I'll describe how we can create a custom style for a content query web part.

A reason why we may need to do something like this is because sometimes the OOTB content query web part does not display exactly what we need when querying articles for example. I wanted to the web part to display the date, title, and some of the body text (and a read more link). Unfortunately, this is something that needs to be customized since it's not available OOTB.

Firstly, you need to open ItemStyle.xsl in SharePoint Designer. Check the file out, so you can roll back if you make any mistakes in it.

Scroll to the bottom of the file and add the following just before the </xsl:stylesheet> tag:

     <xsl:template name="WeiStyle" match="Row[@Style='WeiStyle']" mode="itemstyle">
        <xsl:variable name="SafeLinkUrl">
            <xsl:call-template name="OuterTemplate.GetSafeLink">
                <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="SafeImageUrl">
            <xsl:call-template name="OuterTemplate.GetSafeStaticUrl">
                <xsl:with-param name="UrlColumnName" select="'ImageUrl'"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="DisplayTitle">
            <xsl:call-template name="OuterTemplate.GetTitle">
                <xsl:with-param name="Title" select="@Title"/>
                <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="LinkTarget">
            <xsl:if test="@OpenInNewWindow = 'True'" >_blank</xsl:if>
        </xsl:variable>
        <xsl:variable name="Created">
            <xsl:value-of select="ddwrt:FormatDateTime(string(@Created) ,1033 ,'dd-MM-yyyy')" />
        </xsl:variable>
        <div id="linkitem" class="item">
            <xsl:if test="string-length($SafeImageUrl) != 0">
                <div class="image-area-left">
                    <a href="{$SafeLinkUrl}" target="{$LinkTarget}">
                        <img class="image" src="{$SafeImageUrl}" alt="{@ImageUrlAltText}" />
                    </a>
                </div>
            </xsl:if>
            <div class="link-item">
                <xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>    
                <a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}">
                  <xsl:value-of select="$Created"/> - <xsl:value-of select="$DisplayTitle"/>
                </a>
                <div class="description">
                  <xsl:value-of select="substring(@PublishingPageContent, 0, 200)" disable-output-escaping="yes"/>
                  <a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="Read more">...</a>
                </div>
            </div>
        </div>
    </xsl:template>

Note that in the code above that you pasted, there is a xsl variable that you set that formats the date in any way you like. To make the date formatting work, you need to add the following at the top of the xsl (namespace attribute):

  xmlns:ddwrt="http://schemas.microsoft.com/WebParts/v2/DataView/runtime"

Now save the document and refresh the page where the CQWP resides. You'll see that everything works except there is no body (yet). To make the summarised body appear, you need to export the CQWP and edit the .webpart file it in Notepad. This needs to be done because you need to add the scope to the web part.

Look for the property name CommonViewFields and change it as follows:

<property name="CommonViewFields" type="string">ExternalUrl,URL;PublishingPageImage,Image;PublishingPageContent,Note;</property>

Save the .webpart file and then go back to where the CQWP resides, delete the web part that's there and re-add a new web part. Click Advanced Web Part gallery and options, then click the "Browse" drop down and select Import. Look for the .webpart file and import that web part. You should now be able to see the web part with the date, title, content (to 200 chars) and then a ... to read more.

But that's not all. While I was doing this, I found that the first 200 chars that the web part displays actually includes any HTML code that's in there. And it just so happened (while I was testing), that if the 200th character happens to be within the HTML tag itself, the "..." read more link wouldn't work. In addition, there is a big ugly gap between the title and the summary body (because of the <p> tag in the body). So I had to figure out how to strip all HTML tags from the summary.

Go back to the ItemStyle.xsl file and add the following at the end just before the </xsl:stylesheet> tag:

<xsl:template name="RemoveHtmlTags">
    <xsl:param name="html"/>
    <xsl:choose>
        <xsl:when test="contains($html, '&lt;')">
            <xsl:value-of select="substring-before($html, '&lt;')"/>
            <!-- Recurse through HTML -->
            <xsl:call-template name="removeHtmlTags">
                <xsl:with-param name="html" select="substring-after($html, '&gt;')"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$html"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

This is the template that will remove all html code (when called).

Now, let's re-visit the original code you entered into the ItemStyle above. We need to add a new variable that calls this RemoveHtmlTags template in order to remove the HTML tags in the summary.

    <xsl:template name="DetailedStyle" match="Row[@Style='DetailedStyle']" mode="itemstyle">
        <xsl:variable name="SafeLinkUrl">
            <xsl:call-template name="OuterTemplate.GetSafeLink">
                <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="SafeImageUrl">
            <xsl:call-template name="OuterTemplate.GetSafeStaticUrl">
                <xsl:with-param name="UrlColumnName" select="'ImageUrl'"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="DisplayTitle">
            <xsl:call-template name="OuterTemplate.GetTitle">
                <xsl:with-param name="Title" select="@Title"/>
                <xsl:with-param name="UrlColumnName" select="'LinkUrl'"/>
            </xsl:call-template>
        </xsl:variable>
        <xsl:variable name="LinkTarget">
            <xsl:if test="@OpenInNewWindow = 'True'" >_blank</xsl:if>
        </xsl:variable>
        <xsl:variable name="Created">
            <xsl:value-of select="ddwrt:FormatDateTime(string(@Created) ,1033 ,'dd-MM-yyyy')" />
        </xsl:variable>
        <xsl:variable name="PureTextBody">
            <xsl:call-template name="RemoveHtmlTags">
                <xsl:with-param name="html" select="@PublishingPageContent" />
            </xsl:call-template>
        </xsl:variable>

        <div id="linkitem" class="item">
            <xsl:if test="string-length($SafeImageUrl) != 0">
                <div class="image-area-left">
                    <a href="{$SafeLinkUrl}" target="{$LinkTarget}">
                        <img class="image" src="{$SafeImageUrl}" alt="{@ImageUrlAltText}" />
                    </a>
                </div>
            </xsl:if>
            <div class="link-item">
                <xsl:call-template name="OuterTemplate.CallPresenceStatusIconTemplate"/>    
                <a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="{@LinkToolTip}">
                  <xsl:value-of select="$Created"/> - <xsl:value-of select="$DisplayTitle"/>
                </a>
                <div class="description">
                  <xsl:value-of select="substring($PureTextBody, 0, 200)" disable-output-escaping="yes"/>
                  <a href="{$SafeLinkUrl}" target="{$LinkTarget}" title="Read more">...</a>
                </div>
            </div>
        </div>
    </xsl:template>

I have highlighted the difference in <bold> so you can see what was done to strip out the HTML.

« Previous Entries