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.

Apr 3

First thing to clear up is this... a document library is not a folder and a folder is not a document library. A folder resides in a document library and the SPFolder class doesn't have the same methods as the SPDocumentLibrary class (unfortunately).

For example, you can get the last modified date of any file within an entire document library, but you can't get the last modified date of any file within a folder within that document library. I found this frustrating because that was exactly what I had to do.

Anyway, when you browse to a document library and click on a folder within that document library, you get a huge URL. One that looks something like http://intranet/site/subsite/DocLib/Forms/AllItems.aspx?RootFolder=%2fsite%2fsubsite%2fDocLib%2fFolderName&blah blah blah. Copy that link into a list with a URL field and sometimes you see this... http://intranet/site/subsite/DocLib/FolderName. Now, that's annoying when trying to figure out what the folder is in the URL that the user pastes.

So firstly, what you need to do is check if there is a value for RootFolder in the URL and if there is, convert it into the shortened version so you can more easily manipulate it.

    if (strURL.Contains("RootFolder="))
    {
        // need to shorten it
        int equalMark = strURL.IndexOf("=");
        int ampersandMark = strURL.IndexOf("&");
        string folderURL = SPEncode.UrlDecodeAsUrl(strURL.Substring((equalMark + 1), (ampersandMark - equalMark - 1)));

        SPSite site = new SPSite(strURL);
        strURL = site.Url + folderURL; // now the url is the link direct to the folder itself.
    }

From this smaller URL, you can get the document library details (see here). Then as far as I know, you have to loop through all the folders in the document library to find the one you are after.

    SPSite site = new SPSite(strURL);
    SPWeb web = site.OpenWeb();

    string[] explode = strURL.Replace(web.Url, "").Split(new char[] { '/' });
    string splitURL = explode[1];
    string splitFolderName = explode[2];

    string docLibName = SPEncode.UrlDecodeAsUrl(splitURL); // (this is also the list name with the location we're after)

    foreach (SPListItem folderListItem in web.Lists[docLibName].Folders)
    {
        if (folderListItem.Name == strFolderName) // compare
        {
            // then now we go through the items in this folder and see if there is anything new
            foreach (SPFile file in folderListItem.Folder.Files)
            {
                // you can now go through each file in that folder
            }
        }
    }

Note that web.Lists[docLibName].Folders is of type SPFolder already so you can manipulate the folder if you need to.

Apr 3

Here's what was happening. I needed to extract the document library name from an intranet URL that a user enters. So they would enter something like this as the URL: http://intranet/site/subsite/DocLib1/Forms/AllItems.aspx and from there I need to extract DocLib1 as SPDocumentLibrary. Problem here is that no matter the depth, I still need to find the document library name and manipulate it as SPDocumentLibrary.

I'm not sure if my way is the best way to do it, but it did work...

            SPSite site = new SPSite(strURL);
            SPWeb web = site.OpenWeb();

            string[] explode = strURL.Replace(web.Url, "").Split(new char[] { '/' });
            string splitURL = explode[1];

            string docLibName = SPEncode.UrlDecodeAsUrl(splitURL); // (this is also the list name with the location we're after)
            SPList thisDocLib = web.Lists[docLibName];

If you do a check for thisDocLib.BaseType, you will find it's of the type DocumentLibrary.

Now, how would it work if it were the folder that we were after instead of a document library?

« Previous Entries