Skip to main content

TagCloud Webpart in SharePoint 2007

While everyone else right now seems to be blogging about SharePoint 2010, I decided to blog a little bit about the previous product, SharePoint 2007.

Recently, I had to develop a webpart that shows Tags from either a Site collection level or subsite level.

I will give you the code but firstly, here is how it works:

Assumining that you already have a library/list that has a choice field called Category(it can have any name), the webpart will search the site collection/subsite(depending on the scope you choose) for all columns that are named 'Category', and when found, will pull out the selected choices for display. Remember that this is a choice column, meaning that the choices will be repeatitive, and therefore, the more repeative the choices are, the bigger the font size of the Tag name will appear on the webpart.

Secondly, the tags will get random colors on page load, while at the same time will be hyperlinked, and when you click on a tag, it will be passed to the Search and generate search results for you on the search page to library/list items you have permissions on.

Thirdly, on the webpart properties, you get the privilege of changing the choice column name to point to, the scope(site collection or subsite), as well as change the search string to use, and also enable caching etc.

Fouthly, I have a feeling that this is going to be the longest blog post have ever made, nevertheless, the following is the name space code:

**remember to generate your own GUID.

using System;
using System.Data;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.ComponentModel;

using Microsoft.SharePoint;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

namespace TagCloud.TagCloud
{
[Guid("9eb18673-6617-4c63-b716-8cf8f935318e")]
public class TagCloudClass : System.Web.UI.WebControls.WebParts.WebPart
{
// Fields
private string documentLibraryType = "1";
private bool isActivatedCache = true;
private string listType = "0";
private bool openItemsInNewWindows;
private readonly Random rnd = new Random(DateTime.Now.Millisecond);
private Enumerations.SearchScopes scope = Enumerations.SearchScopes.SiteCollection;
private char separator = ',';
private string tagField = "Category";
private readonly Dictionary Tags = new Dictionary();
private string targetUrl = "/_layouts/OSSSearchResults.aspx?k=";

// Methods
public TagCloudClass()
{
this.rnd = new Random(DateTime.Now.Millisecond);
this.Tags = new Dictionary();
this.documentLibraryType = "1";
this.listType = "0";
this.scope = Enumerations.SearchScopes.SiteCollection;
this.separator = ',';
this.tagField = "Category";
this.targetUrl = "/_layouts/OSSSearchResults.aspx?k=";
this.isActivatedCache = true;
}


private void AddLinks(string key)
{
Tag tag = this.Tags[key];
this.AddSeparator();
Table child = new Table();
child.Width = new Unit(100.0, UnitType.Percentage);
foreach (TagLink link in tag.Links)
{
TableRow row = new TableRow();
child.Rows.Add(row);
TableCell cell = new TableCell();
row.Cells.Add(cell);
HyperLink link2 = new HyperLink();
link2.Text = link.Title;
link2.NavigateUrl = link.ItemUrl;
cell.Controls.Add(link2);
}
this.Controls.Add(child);
}

private void AddSeparator()
{
Table child = new Table();
child.Width = new Unit(100.0, UnitType.Percentage);
TableRow row = new TableRow();
child.Rows.Add(row);
TableCell cell = new TableCell();
cell.HorizontalAlign = HorizontalAlign.Center;
row.Cells.Add(cell);
Label label = new Label();
label.Text = "----------------";
cell.Controls.Add(label);
this.Controls.Add(child);
}

private void AddTag(DataRow row, string localTag)
{
Tag newTag = new Tag();
newTag.Title = localTag;
SaveTag(newTag, row);
this.Tags.Add(localTag, newTag);
}

private void AddTags(string listType, Enumerations.SearchScopes searchScope)
{
DataTable results = this.GetResults(listType, searchScope);
this.GetTags(results);
}

private void BuildWebPart()
{
try
{
this.AddTags(this.ListType, this.Scope);
this.AddTags(this.DocumentLibraryType, this.Scope);
Table child = new Table();
child.Width = new Unit(100.0, UnitType.Percentage);
TableRow row = new TableRow();
child.Rows.Add(row);
TableCell cell = new TableCell();
cell.HorizontalAlign = HorizontalAlign.Center;
row.Cells.Add(cell);
this.Controls.Add(child);
foreach (KeyValuePair pair in this.Tags)
{
LinkButton button = new LinkButton();
button.Text = pair.Value.Title;
int count = pair.Value.Links.Count;
button.ToolTip = string.Format("{0} occurrance", count);
button.Font.Size = new FontUnit(GetFontSize(count), UnitType.Point);
button.ForeColor = this.GetRandomColor();
button.CommandArgument = pair.Key;
button.Click += new EventHandler(this.Tag_Click);
cell.Controls.Add(button);
Literal literal = new Literal();
literal.Text = " ";
cell.Controls.Add(literal);
}
}
catch (Exception exception)
{
this.SetErrorMessage(exception);
}
}

protected override void CreateChildControls()
{
base.CreateChildControls();
this.BuildWebPart();
}

private static string GetErrorMessage(Exception ex)
{
StringBuilder builder = new StringBuilder();
try
{
StackTrace trace = new StackTrace(ex, true);
builder.AppendLine(string.Format(" Stack trace for current level: {0}", trace));
StackFrame[] frames = trace.GetFrames();
if (frames != null)
{
foreach (StackFrame frame in frames)
{
builder.AppendLine(string.Format(" File: {0}", frame.GetFileName()));
builder.AppendLine(string.Format(" Method: {0}", frame.GetMethod().Name));
builder.AppendLine(string.Format(" Line Number: {0}", frame.GetFileLineNumber()));
builder.AppendLine(string.Format(" Column Number: {0}", frame.GetFileColumnNumber()));
}
}
}
catch
{
}
return builder.ToString();
}

private static double GetFontSize(int count)
{
double num = 8.0;
switch (count)
{
case 2:
num = 10.0;
break;

case 3:
num = 12.0;
break;

case 4:
num = 14.0;
break;

case 5:
num = 16.0;
break;

case 6:
num = 18.0;
break;

case 7:
num = 20.0;
break;

case 8:
num = 22.0;
break;

case 9:
num = 24.0;
break;
}
if (count > 10)
{
num = 26.0;
}
return num;
}

private static string GetItemUrl(string s)
{
string str = string.Empty;
try
{
string str2 = s.Split(new char[] { '#' })[1];
string str3 = str2.Remove(str2.LastIndexOf('/'));
string str4 = s.Substring(s.LastIndexOf('/') + 1);
string str5 = str4.Remove(str4.LastIndexOf('_'));
str = SPContext.Current.Web.Site.Url + "/" + str3 + "/DispForm.aspx?ID=" + str5;
}
catch (Exception)
{
}
return str;
}

private Color GetRandomColor()
{
Color black = Color.Black;
try
{
int red = this.rnd.Next(0, 0xff);
int green = this.rnd.Next(0, 0xff);
int blue = this.rnd.Next(0, 0xff);
black = Color.FromArgb(red, green, blue);
}
catch
{
}
return black;
}

private DataTable GetResults(string listType, Enumerations.SearchScopes searchScope)
{
string str = "";
string str2 = string.Format("", this.TagField);
string str3 = "";
if (!this.isActivatedCache)
{
SPSiteDataQuery query = new SPSiteDataQuery();
query.Lists = str;
query.ViewFields = str2;
query.Webs = str3;
return SPContext.Current.Web.GetSiteData(query);
}
CrossListQueryInfo queryCacheInfo = new CrossListQueryInfo();
queryCacheInfo.WebUrl = SPContext.Current.Site.ServerRelativeUrl;
queryCacheInfo.Lists = str;
queryCacheInfo.Webs = str3;
queryCacheInfo.Query = string.Format("", this.TagField);
queryCacheInfo.ViewFields = str2;
CrossListQueryCache cache = new CrossListQueryCache(queryCacheInfo);
return cache.GetSiteData(SPContext.Current.Site);
}

private void GetTag(DataRow row, string tag)
{
if (this.Tags.ContainsKey(tag))
{
this.UpdateTag(row, tag);
}
else
{
this.AddTag(row, tag);
}
}

private void GetTags(DataTable results)
{
foreach (DataRow row in results.Rows)
{
string[] strArray = row[3].ToString().Split(new char[] { this.Separator });
foreach (string str in strArray)
{
this.GetTag(row, str.Trim());
}
}
}

private static void SaveTag(Tag newTag, DataRow row)
{
TagLink item = new TagLink();
item.ListID = new Guid(row[0].ToString());
item.WebID = new Guid(row[1].ToString());
item.ItemUrl = GetItemUrl(row[4].ToString());
item.Title = row[5].ToString();
newTag.Links.Add(item);
}

private void SetErrorMessage(Exception ex)
{
this.Controls.Clear();
Label child = new Label();
child.Text = GetErrorMessage(ex);
child.CssClass = "ms-formvalidation";
this.Controls.Add(child);
}

private void Tag_Click(object sender, EventArgs e)
{
LinkButton button = sender as LinkButton;
if (button != null)
{
if (string.IsNullOrEmpty(this.TargetUrl))
{
this.AddLinks(button.CommandArgument);
}
else
{
this.Page.Response.Redirect(this.TargetUrl + button.CommandArgument);
}
}
}

private void UpdateTag(DataRow row, string localTag)
{
Tag newTag = this.Tags[localTag];
SaveTag(newTag, row);
}

// Properties
public string DocumentLibraryType
{
get
{
return this.documentLibraryType;
}
set
{
this.documentLibraryType = value;
}
}

[Personalizable(PersonalizationScope.Shared), FriendlyName("Enable Cache"), Description("Flag for activating the cache"), Category("Parameters"), PersistenceMode(PersistenceMode.InnerProperty), WebBrowsable(true)]
public bool IsActivatedCache
{
get
{
return this.isActivatedCache;
}
set
{
this.isActivatedCache = value;
}
}

public string ListType
{
get
{
return this.listType;
}
set
{
this.listType = value;
}
}

[Personalizable(PersonalizationScope.Shared), Description("If checked, allows to open all links in a new window Tag"), Category("Parameters"), PersistenceMode(PersistenceMode.InnerProperty), WebBrowsable(true), FriendlyName("Open links in a new window")]
public bool OpenItemsInNewWindows
{
get
{
return this.openItemsInNewWindows;
}
set
{
this.openItemsInNewWindows = value;
}
}

[Category("Parameters"), Personalizable(PersonalizationScope.Shared), FriendlyName("Search Scope"), Description("Set the search scope for Tag: only the current site or the entire site collection"), WebBrowsable(true), PersistenceMode(PersistenceMode.InnerProperty)]
public Enumerations.SearchScopes Scope
{
get
{
return this.scope;
}
set
{
this.scope = value;
}
}

[WebBrowsable(true), Description("Set the value of the separator character for Tag"), Category("Parameters"), PersistenceMode(PersistenceMode.InnerProperty), Personalizable(PersonalizationScope.Shared), FriendlyName("Separator character for Tag")]
public char Separator
{
get
{
return this.separator;
}
set
{
this.separator = value;
}
}

[PersistenceMode(PersistenceMode.InnerProperty), Category("Parameters"), Personalizable(PersonalizationScope.Shared), FriendlyName("Tag Name column to search"), WebBrowsable(true), Description("Sets the name tag on the columns to search")]
public string TagField
{
get
{
return this.tagField;
}
set
{
this.tagField = value;
}
}

[WebBrowsable(true), Personalizable(PersonalizationScope.Shared), Description("Set the URL of the page to search for Tag"), FriendlyName("Url of the page to search for Tag"), Category("Parameters"), PersistenceMode(PersistenceMode.InnerProperty)]
public string TargetUrl
{
get
{
return this.targetUrl;
}
set
{
this.targetUrl = value;
}
}

}
internal class TagLink
{
// Fields
private string itemUrl;
private Guid listID;
private string title;
private Guid webID;

// Properties
public string ItemUrl
{
get
{
return this.itemUrl;
}
set
{
this.itemUrl = value;
}
}

public Guid ListID
{
get
{
return this.listID;
}
set
{
this.listID = value;
}
}

public string Title
{
get
{
return this.title;
}
set
{
this.title = value;
}
}

public Guid WebID
{
get
{
return this.webID;
}
set
{
this.webID = value;
}
}
}


internal class Tag
{
// Fields
private List links = new List();
private string title;

// Properties
public List Links
{
get
{
return this.links;
}
set
{
this.links = value;
}
}

public string Title
{
get
{
return this.title;
}
set
{
this.title = value;
}
}
}


public class Enumerations
{
// Nested Types
public enum SearchScopes
{
SiteCollection,
Recursive,
Web
}
}
}



Happy days!!!
References: http://www.codeplex.com/

Comments

Popular posts from this blog

SharePoint: How to create a custom action to open Word Documents using "Edit in Microsoft Word".

Imagine you have a SharePoint custom search webpart, and on your search results, you return word documents, you will obviously want to at times be able to open them in your MS Word client program for editing. So basically, depending on your office client installed on your local machine, there are 2 different approaches that can be made for Office 2003 and Office 2007/10, using the same function " editDocumentWithProgID2 ". For Office 2003: - If your document libraries versioning settings have got "Require Check out" ticked, then you will first want to check out the document using: onclick ="CheckoutviaXmlhttp(‘{SiteURL}’, ‘{DocumentDownloadURL}’)" - Then to open the document, you use: onclick =" return editDocumentWithProgID2(‘ {DocumentDownloadURL} ’, ”, ‘SharePoint.OpenDocuments’, ’1′,’ {SiteURL} ’, ’0′);" href ="#" - and now combining the above 2 actions into one clickable action: onclick ="CheckoutviaXmlhttp(‘ {SiteURL} ’, ‘ {...

Zambia's first K2 BlackPoint roll-out

Reporting to you live from Code|Influence... My colleague and I have been managing our organization's SharePoint infrastructure for some time now and we have just rolled out the first K2 BlackPoint in the country, intended mostly for SharePoint workflow developments.

How to Scope your SharePoint Projects

The "SharePoint project scope" is all of the things that must be produced to complete a SharePoint project. These 'things' are called deliverables and you need to describe them in depth as early in the SharePoint project as possible, so everyone knows what needs to be produced. Take these 5 Steps to scope your SharePoint projects: Step 1: Set the Direction Start off by setting the direction for the SharePoint project. Do you have an agreed SharePoint project Vision, Objectives and Timeframes? Are they specified in depth and has your customer agreed to them? Does everyone in the SharePoint project team truly understand them and why they are important? Only by fixing the SharePoint project direction can you truly fix the SharePoint project scope. Step 2: Scope Workshops The best way to get buy-in to your SharePoint project scope is to get all of the relevant stakeholders to help you define it. So get your SharePoint project sponsor, customer and other stakeholders in a ...