Tuesday, December 28, 2010

ERROR: One or more types failed to load.

Let me save someone some time.

So I was trying to run SharePoint Products and Technology Configuration Wizard for MOSS 2007, and during the course, I faced the error message, as seen from the screen dump above, "One or more types failed to load. Please refer to the upgrade log for more details". After alot of research, I came to learn that this was being caused by Office 2010 which was installed on the same machine as MOSS 2007. Therefore, the error went when I uninstalled Office 2010.

Happy holidays ;)

Tuesday, December 14, 2010

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 room and run a workshop to identify the scope. What you want from them is an agreed set of major deliverables to be produced by the SharePoint project. You also want to know "what's out of scope".
Run the workshop by asking each stakeholder for a list of the deliverables they expect the SharePoint project team to deliver. Take the full list of deliverables generated in the workshop and get them to agree on what's mandatory and what's optional. Then ask them to prioritize the list, so you know what has to be delivered first.

Step 3: Fleshing it out

You now have an agreed list of deliverables. But it's still not enough. You need to define each deliverable in depth. Work with the relevant people in your business to describe how each deliverable will look and feel, how it would operate and how it would be supported etc. Your goal here is to make it so specific that your customer cannot state later in the SharePoint project that "when they said this, they really meant that".

Step 4: Assessing Feasibility

So you now have a detailed list and description of every deliverable to be produced by your SharePoint project, in priority order and separated as mandatory / optional. Great! But is it feasible to achieve within the project end date? Before you confirm the scope, you need to review every deliverable in the list and get a general indication from your SharePoint team as to whether they can all be completed before your SharePoint project end date. If they can't, then which deliverables can you remove from the list to make your end date more achievable?

Step 5: Get the thumbs up

Present the prioritized set of deliverables to your SharePoint project Sponsor and ask them to approve the list as your SharePoint project scope. Ask them to agree to the priorities, the deliverable descriptions and the items out of scope.
By getting formal sign-off, you're in a great position to be able to manage the SharePoint project scope down the track. So when your Sponsor says to you in a few weeks time "Can you please add these deliverables to the list?", you can respond by saying "Yes, but I'll either have to remove some items from the list to do it, or extend the SharePoint project end date. Which is it to be?". You can easily manage your Sponsors expectations with a detailed scope document at your side.

The scope document is the SharePoint project Manager's armor. It protects them from changes and makes them feel invincible!

Thursday, December 9, 2010

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/

Wednesday, October 13, 2010

SMS integration with SharePoint

As part of my Code|Influence projects, I embarked on developing and copyrighted an SMS powered application, that would receive text messages in form of SMS perform various types of functions based on the SMS content, and reply back to the sender the results via SMS.

With the SharePoint passion in me, I then went further to see how this would work with SharePoint. With a proof-of-concept done, I finally can perform various SharePoint functions e.g create list items, kick off workflows, search etc...all via SMS.

The good thing to note is that this SMS application's various operations that it can perform are so unlimited, including those outside the SharePoint world. For now, I will end here. Enjoy!

Thursday, October 7, 2010

How to implement a SharePoint "Change Management Process"

Not so much from the technical point of view, SharePoint Change Management is the process of monitoring and controlling changes within a SharePoint project. By managing the implementation of change, you can:

• Reduce the impact of changes to the SharePoint project

• Identify new issues and risks as a result of changes raised

• Ensure that changes do not affect the SharePoint project's ability to achieve its desired objectives

• Control the cost of change within the SharePoint project

Change Management is comprised of the following processes:

Step 1: Identify Change: The first step in the change process is to identify the need for change. Any team member can suggest a change to the SharePoint project, if he or she believes it is needed to keep the SharePoint project producing deliverables to the customer's specified requirements. After identifying a need for change, the team member records relevant information on a Change Request Form (commonly called a CRF), describing the change, and identifying drivers, benefits, costs and likely impact of the change on the SharePoint project. The CRF is forwarded to the SharePoint Project Manager for review and approval.

Step 2: Review Change: The SharePoint Project Manager investigates the change to identify the reason for it and its impact. Then he or she decides whether it is critical to the successful delivery of the project. Changes which are not critical to SharePoint Project delivery should be avoided whenever possible to prevent "scope creep" (i.e. the gradual increase in scope throughout the SharePoint project Lifecycle).
If the change is deemed critical to success, the SharePoint Project Manager either approves the request or seeks approval for the CRF raised. In some cases, the SharePoint Project Manager has the direct authority to approval minor change requests; however, in most cases the SharePoint Project Manager needs to seek CRF approval from the Project Board.

Step 3: Approve Change: The Project Board reviews the details in the CRF to determine whether or not the change should be implemented. Based on the level of risk, impact, benefits and cost to the SharePoint project, it may decide to decline, delay or approve the change request.

Step 4: Implement Change: The SharePoint Project Manager approves all changes, which are then are scheduled and implemented accordingly. After implementation, the SharePoint Project Manager reviews the effects of the change on the SharePoint project to ensure that it achieved the desired outcome, when the change is then closed in the Change Register.
Throughout the Change Management Process, the SharePoint Project Manager can monitor and control changes to the SharePoint project by keeping this Change Register up-to-date.

There you have it. By completing these 4 steps, you can carefully monitor and control SharePoint project changes, to increase your likelihood of success.

Wednesday, October 6, 2010

How to Plan Your SharePoint Projects

Because I have always looked at SharePoint as a platform for building your organisations solutions that help improve business productivity, I thought I could write about a few simple project management steps that can aid when building these business solutions, classified as SharePoint Projects.

Step 1: Set the Direction

Before you start out, set the direction for the SharePoint project. Do this by clearly identifying the SharePoint project vision, goals and deliverables. State the overall timeframes for delivery and clarify the amount of resource available. Determine what is "in scope" and "out of scope". Identify the benefits and costs in delivering the SharePoint project and any milestones and constraints. Only once this is agreed with your SharePoint project Sponsor will you know what it is that you have to achieve.

Step 2: Task Selection

You're now ready to start planning. Identify the groups of tasks that need to be completed to build your SharePoint project deliverables. Then for each group of tasks, breakdown those tasks into sub-tasks to create what is known as a "Work Breakdown Structure" (WBS). Your WBS is essentially a hierarchical list of tasks, in order. Assign start and end dates to each task, as well as task durations. Always add a little extra time (e.g. 10%) to your durations, providing you with contingency. Next add Milestones to your plan. These are tasks that represent major achievements along the way.

Step 3: Inter-linking

The next step is to add links (or dependencies) between SharePoint project tasks. While there are a variety of link types, most SharePoint project Managers add "finish-to-start" links so that one task cannot start until another one finishes. To make your SharePoint project achievable, only add links between tasks if there is a critical dependency between them. Remember, when one task slips, all tasks linked to it may slip as well. So use links wisely.

Step 4: Resource Assignment

Now comes the fun part, assigning resources. A "resource" may be a person, equipment, location or materials. Against each task in your plan, assign one or more resources required to complete it. As you assign resources, watch your resource utilization. In other words, make sure you don't over-assign a specific resource to multiple tasks, so that it’s impossible for that resource to complete everything assigned to it.

Step 5: Baseline, Actuals and Reporting

With a fully completed SharePoint project plan, you're now ready to save it as a "baseline", so that you can later compare your progress against it. Then start recording your actual progress against the plan. Every day, record the amount of time you've spent against each task. Also record the new planned start and finish dates, and monitor the overall SharePoint project completion date. Report on progress as you go. By regularly updating the SharePoint project plan with your progress, you can control the delivery of your SharePoint project and meet those critical goals set.

Wednesday, August 11, 2010

Types of Event Receivers in SharePoint 2010

I recently have come to learn that there are 6 types of Event Receivers that can be done in SharePoint 2010. I thought I could share them here.

List Events -
Adding/ed a new list field.
Updating/ed a field.

List Item Events -
Adding/ed a new list item or document.
Document checking/ed in or out.
Adding/ed an attachment.
Deleting/ed an item or document.

List Email Events -
A list received an email.

Web Events -
Deleting/ed a site collection or site.
Creating/ed a new site collection or sub site.

Feature Events -
Feature activating/ed or deactivating/ed.

List Workflow Events -
A workflow is starting/ed, postponed, or completed.

Thanks to Isha.

Wednesday, July 7, 2010

SharePoint Training Kit: Assignment Not Available

Hello fox,

While going through a training video of the Collaboration module of the SharePoint Training Kit, I happened to to have clicked "Complete Training". After which, when I tried to view the video again, its assigned action read as "Continue", so when I clicked on "Continue", it brought up a message saying "Assignment Not Available. This assignment is not available because it has been submitted as complete. You can review this assignment after it is returned by your instructor.".

So I tried to log in to the site as an instructor but i still couldn't review any assignments. I therefore went into the SQL Database, tried to study the tables in the DB, and i finally found that in the STKTrainingResult table, a record for every training module you take is entered in this table, and there was a column named "TrainingStatus" on my particular training record that needed to change from 0 to 1 the time I had clicked on "complete training", but it didn't change. I therefore changed this field manually and I was able to retake the training video successfully.

Am sure this is not the recommended workaround though.

Wednesday, June 30, 2010

Workflows from SPD 2010 wont automatically start

I recently had to do a workflow from SharePoint Designer 2010, that sends an email once a list item is created. After publishing it to its associated list in SharePoint 2010, I found that the workflow was not automatically starting when I create a list item, but when I manually start it, it would work. After some research, I found that I initially created it using the system account. So I then tried to use my own user account that was site collection admin on the site, to re-create the workflow, published it, and it now worked. Am still yet to understand why this is so.

Thursday, January 21, 2010

A quick ROI on SharePoint Intranet

To Start Year 2010, I thought I could come up with a list of a few simple things you can do with SharePoint Intranet to quickly start getting your ROI:

1. You can use your SharePoint lists to organize and track your organizations travel schedules.

2. You can create a web based company notice board.

3. You can set up departmental sites for your organization.

4. On your departmental sites, you can use the shared calendars to schedule meetings, display when key staff would be away from office, as well as show company recognized public holidays.

5. With company naming standards in place, you can upload your standard operating procedures (SOPs) to designations Document libraries.

6. Using lists, you can track your company’s invoices from the point of receipt to the point of paying it off.

7. You can set up a news site that has RSS feeds from other external news websites.

8. You can set up a helpdesk system that would allow your organizations users to log in calls online and be able to track them, with the ability of email notification.

9. You can set up an online leave application process, where users can request to go on leave by doing an online application.

10. In monthly/daily company production/sales/financial budgets reporting, you can upload the spreadsheets (Excel 2007/10) that are used to generate the graphs from, and publish them, to maintain one version of the truth and with controlled access.

11. You can create a company internal training site.

12. You can set up a company internal adverts site for items that are on sale.

13. You can set up a company assets allocation list, specifying who, when and where the asset has been allocated to.

14. You can create a simple site to manage your organizations change management.

15. And you can quickly take a walk around your organization, identify the manual processes that require automation onto SharePoint, and then contact me.

16. etc